[postgis-tickets] [SCM] PostGIS branch stable-3.0 updated. 36bcfa1737a9a6c6ee2d9a8710eba6be4c51769b

git at osgeo.org git at osgeo.org
Tue Jan 7 04:20:15 PST 2020


This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "PostGIS".

The branch, stable-3.0 has been updated
       via  36bcfa1737a9a6c6ee2d9a8710eba6be4c51769b (commit)
      from  41475b02d27ab752cd03d95a5dbc33df6dcccbed (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 36bcfa1737a9a6c6ee2d9a8710eba6be4c51769b
Author: Raúl Marín <git at rmr.ninja>
Date:   Tue Jan 7 13:08:57 2020 +0100

    PG12: Fix several bugs in the index support function
    
    - ST_Covers and ST_CoveredBy for geography were using the wrong strategy (which didn't exist).
    - ST_ContainsProperly for geometry was using the wrong strategy.
    - ST_3DIntersects was duplicated.
    
    Closes #4608

diff --git a/NEWS b/NEWS
index 18bae40..2bab8e8 100644
--- a/NEWS
+++ b/NEWS
@@ -11,8 +11,9 @@ XXXX/XX/XX
   - #4606, Respect user's LDFLAGS in postgis module build (Sandro Santilli)
   - #4610, Add in logic to install postgis_tiger_geocoder from unpackaged (Regina obe)
   - #4581, installing postgis_raster from unpackaged tries to use wrong schema
-  - #4596, The script to generate nation_script_load.sh is missing 
+  - #4596, The script to generate nation_script_load.sh is missing
            a trailing quote (Bill Mill)
+  - #4608, PG12: Fix several bugs in the index support function (Raúl Marín)
 
 PostGIS 3.0.0
 2019/10/20
diff --git a/postgis/gserialized_supportfn.c b/postgis/gserialized_supportfn.c
index 4af5a1d..ff018a8 100644
--- a/postgis/gserialized_supportfn.c
+++ b/postgis/gserialized_supportfn.c
@@ -45,6 +45,7 @@
 
 /* PostGIS */
 #include "liblwgeom.h"
+#include "lwgeom_pg.h"
 
 /* Local prototypes */
 Datum postgis_index_supportfn(PG_FUNCTION_ARGS);
@@ -53,6 +54,83 @@ Datum postgis_index_supportfn(PG_FUNCTION_ARGS);
 float8 gserialized_joinsel_internal(PlannerInfo *root, List *args, JoinType jointype, int mode);
 float8 gserialized_sel_internal(PlannerInfo *root, List *args, int varRelid, int mode);
 
+enum ST_FUNCTION_IDX
+{
+	ST_INTERSECTS_IDX = 0,
+	ST_DWITHIN_IDX = 1,
+	ST_CONTAINS_IDX = 2,
+	ST_WITHIN_IDX = 3,
+	ST_TOUCHES_IDX = 4,
+	ST_3DINTERSECTS_IDX = 5,
+	ST_CONTAINSPROPERLY_IDX = 6,
+	ST_COVEREDBY_IDX = 7,
+	ST_OVERLAPS_IDX = 8,
+	ST_COVERS_IDX = 9,
+	ST_CROSSES_IDX = 10,
+	ST_DFULLYWITHIN_IDX = 11,
+	ST_3DDWITHIN_IDX = 12,
+	ST_3DDFULLYWITHIN_IDX = 13,
+	ST_LINECROSSINGDIRECTION_IDX = 14,
+	ST_ORDERINGEQUALS_IDX = 15,
+	ST_EQUALS_IDX = 16
+};
+
+static const int16 GeometryStrategies[] = {
+	[ST_INTERSECTS_IDX]             = RTOverlapStrategyNumber,
+	[ST_DWITHIN_IDX]                = RTOverlapStrategyNumber,
+	[ST_CONTAINS_IDX]               = RTContainsStrategyNumber,
+	[ST_WITHIN_IDX]                 = RTContainedByStrategyNumber,
+	[ST_TOUCHES_IDX]                = RTOverlapStrategyNumber,
+	[ST_3DINTERSECTS_IDX]           = RTOverlapStrategyNumber,
+	[ST_CONTAINSPROPERLY_IDX]       = RTContainsStrategyNumber,
+	[ST_COVEREDBY_IDX]              = RTContainedByStrategyNumber,
+	[ST_OVERLAPS_IDX]               = RTOverlapStrategyNumber,
+	[ST_COVERS_IDX]                 = RTContainsStrategyNumber,
+	[ST_CROSSES_IDX]                = RTOverlapStrategyNumber,
+	[ST_DFULLYWITHIN_IDX]           = RTOverlapStrategyNumber,
+	[ST_3DDWITHIN_IDX]              = RTOverlapStrategyNumber,
+	[ST_3DDFULLYWITHIN_IDX]         = RTOverlapStrategyNumber,
+	[ST_LINECROSSINGDIRECTION_IDX]  = RTOverlapStrategyNumber,
+	[ST_ORDERINGEQUALS_IDX]         = RTSameStrategyNumber,
+	[ST_EQUALS_IDX]                 = RTSameStrategyNumber
+};
+
+/* We use InvalidStrategy for the functions that don't currently exist for geography */
+static const int16 GeographyStrategies[] = {
+	[ST_INTERSECTS_IDX]             = RTOverlapStrategyNumber,
+	[ST_DWITHIN_IDX]                = RTOverlapStrategyNumber,
+	[ST_CONTAINS_IDX]               = InvalidStrategy,
+	[ST_WITHIN_IDX]                 = InvalidStrategy,
+	[ST_TOUCHES_IDX]                = InvalidStrategy,
+	[ST_3DINTERSECTS_IDX]           = InvalidStrategy,
+	[ST_CONTAINSPROPERLY_IDX]       = InvalidStrategy,
+	[ST_COVEREDBY_IDX]              = RTOverlapStrategyNumber, /* This is different than geometry */
+	[ST_OVERLAPS_IDX]               = InvalidStrategy,
+	[ST_COVERS_IDX]                 = RTOverlapStrategyNumber, /* This is different than geometry */
+	[ST_CROSSES_IDX]                = InvalidStrategy,
+	[ST_DFULLYWITHIN_IDX]           = InvalidStrategy,
+	[ST_3DDWITHIN_IDX]              = InvalidStrategy,
+	[ST_3DDFULLYWITHIN_IDX]         = InvalidStrategy,
+	[ST_LINECROSSINGDIRECTION_IDX]  = InvalidStrategy,
+	[ST_ORDERINGEQUALS_IDX]         = InvalidStrategy,
+	[ST_EQUALS_IDX]                 = InvalidStrategy
+};
+
+static int16
+get_strategy_by_type(Oid first_type, uint16_t index)
+{
+	if (first_type == postgis_oid(GEOMETRYOID))
+	{
+		return GeometryStrategies[index];
+	}
+
+	if (first_type == postgis_oid(GEOGRAPHYOID))
+	{
+		return GeographyStrategies[index];
+	}
+
+	return InvalidStrategy;
+}
 
 /*
 * Depending on the function, we will deploy different
@@ -66,9 +144,9 @@ float8 gserialized_sel_internal(PlannerInfo *root, List *args, int varRelid, int
 typedef struct
 {
 	const char *fn_name;
-	int   strategy_number; /* Index strategy to add */
-	int   nargs;           /* Expected number of function arguments */
-	int   expand_arg;      /* Radius argument for "within distance" search */
+	uint16_t index;     /* Position of the strategy in the arrays */
+	uint8_t nargs;      /* Expected number of function arguments */
+	uint8_t expand_arg; /* Radius argument for "within distance" search */
 } IndexableFunction;
 
 /*
@@ -76,25 +154,24 @@ typedef struct
 * so most common functions first. Could be sorted
 * and searched with binary search.
 */
-const IndexableFunction IndexableFunctions[] = {
-	{"st_intersects", RTOverlapStrategyNumber, 2, 0},
-	{"st_dwithin", RTOverlapStrategyNumber, 3, 3},
-	{"st_contains", RTContainsStrategyNumber, 2, 0},
-	{"st_within", RTContainedByStrategyNumber, 2, 0},
-	{"st_touches", RTOverlapStrategyNumber, 2, 0},
-	{"st_3dintersects", RTOverlapStrategyNumber, 2, 0},
-	{"st_containsproperly", RTOverlapStrategyNumber, 2, 0},
-	{"st_coveredby", RTContainedByStrategyNumber, 2, 0},
-	{"st_overlaps", RTOverlapStrategyNumber, 2, 0},
-	{"st_covers", RTContainsStrategyNumber, 2, 0},
-	{"st_crosses", RTOverlapStrategyNumber, 2, 0},
-	{"st_dfullywithin", RTOverlapStrategyNumber, 3, 3},
-	{"st_3dintersects", RTOverlapStrategyNumber, 3, 3},
-	{"st_3ddwithin", RTOverlapStrategyNumber, 3, 3},
-	{"st_3ddfullywithin", RTOverlapStrategyNumber, 3, 3},
-	{"st_linecrossingdirection", RTOverlapStrategyNumber, 2, 0},
-	{"st_orderingequals", RTSameStrategyNumber, 2, 0},
-	{"st_equals", RTSameStrategyNumber, 2, 0},
+static const IndexableFunction IndexableFunctions[] = {
+	{"st_intersects", ST_INTERSECTS_IDX, 2, 0},
+	{"st_dwithin", ST_DWITHIN_IDX, 3, 3},
+	{"st_contains", ST_CONTAINS_IDX, 2, 0},
+	{"st_within", ST_WITHIN_IDX, 2, 0},
+	{"st_touches", ST_TOUCHES_IDX, 2, 0},
+	{"st_3dintersects", ST_3DINTERSECTS_IDX, 2, 0},
+	{"st_containsproperly", ST_CONTAINSPROPERLY_IDX, 2, 0},
+	{"st_coveredby", ST_COVEREDBY_IDX, 2, 0},
+	{"st_overlaps", ST_OVERLAPS_IDX, 2, 0},
+	{"st_covers", ST_COVERS_IDX, 2, 0},
+	{"st_crosses", ST_CROSSES_IDX, 2, 0},
+	{"st_dfullywithin", ST_DFULLYWITHIN_IDX, 3, 3},
+	{"st_3ddwithin", ST_3DDWITHIN_IDX, 3, 3},
+	{"st_3ddfullywithin", ST_3DDFULLYWITHIN_IDX, 3, 3},
+	{"st_linecrossingdirection", ST_LINECROSSINGDIRECTION_IDX, 2, 0},
+	{"st_orderingequals", ST_ORDERINGEQUALS_IDX, 2, 0},
+	{"st_equals", ST_EQUALS_IDX, 2, 0},
 	{NULL, 0, 0, 0}
 };
 
@@ -302,9 +379,16 @@ Datum postgis_index_supportfn(PG_FUNCTION_ARGS)
 				* desired strategy number we can now lookup the operator
 				* we want (usually && or &&&).
 				*/
-				oproid = get_opfamily_member(opfamilyoid, leftdatatype, rightdatatype, idxfn.strategy_number);
+				oproid = get_opfamily_member(opfamilyoid,
+							     leftdatatype,
+							     rightdatatype,
+							     get_strategy_by_type(leftdatatype, idxfn.index));
 				if (!OidIsValid(oproid))
-					elog(ERROR, "no spatial operator found for opfamily %u strategy %d", opfamilyoid, idxfn.strategy_number);
+					elog(ERROR,
+					     "no spatial operator found for '%s': opfamily %u type %d",
+					     idxfn.fn_name,
+					     opfamilyoid,
+					     leftdatatype);
 
 				/*
 				* For the ST_DWithin variants we need to build a more complex return.
diff --git a/regress/core/regress_brin_index_geography.sql b/regress/core/regress_brin_index_geography.sql
index 8df9f07..697547c 100644
--- a/regress/core/regress_brin_index_geography.sql
+++ b/regress/core/regress_brin_index_geography.sql
@@ -50,6 +50,9 @@ SELECT 'scan_idx', qnodes('select * from test where the_geog && ST_GeographyFrom
 SELECT 'scan_idx', qnodes('SELECT * FROM test WHERE the_geog IS NULL');
  SELECT COUNT(num) FROM test WHERE the_geog IS NULL;
 
+SELECT '#4608-1', count(*) FROM test where ST_Covers(ST_GeogFromText('POLYGON((0 0, 45 0, 45 45, 0 45, 0 0))'), the_geog);
+SELECT '#4608-2', count(*) FROM test where ST_CoveredBy(the_geog, ST_GeogFromText('POLYGON((0 0, 45 0, 45 45, 0 45, 0 0))'));
+
 DROP INDEX brin_geog;
 
 -- cleanup
diff --git a/regress/core/regress_brin_index_geography_expected b/regress/core/regress_brin_index_geography_expected
index b427a5f..c83d7b9 100644
--- a/regress/core/regress_brin_index_geography_expected
+++ b/regress/core/regress_brin_index_geography_expected
@@ -168,3 +168,5 @@ scan_idx|Bitmap Heap Scan,Bitmap Index Scan
 42.99|POINT Z (42.99 42.99 42.99)
 scan_idx|Bitmap Heap Scan,Bitmap Index Scan
 1001
+#4608-1|3681
+#4608-2|3681

-----------------------------------------------------------------------

Summary of changes:
 NEWS                                               |   3 +-
 postgis/gserialized_supportfn.c                    | 132 +++++++++++++++++----
 regress/core/regress_brin_index_geography.sql      |   3 +
 regress/core/regress_brin_index_geography_expected |   2 +
 4 files changed, 115 insertions(+), 25 deletions(-)


hooks/post-receive
-- 
PostGIS


More information about the postgis-tickets mailing list