[postgis-tickets] [SCM] PostGIS branch master updated. 64d4a1a69d8aab3ffe7a0db6e0f0e68cb3ef1bb9

git at osgeo.org git at osgeo.org
Tue Jan 7 04:10:55 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, master has been updated
       via  64d4a1a69d8aab3ffe7a0db6e0f0e68cb3ef1bb9 (commit)
      from  9f22d34b5a0c6a697d4e4aa303642ff5bd450019 (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 64d4a1a69d8aab3ffe7a0db6e0f0e68cb3ef1bb9
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.
    
    References #4608
    Closes https://github.com/postgis/postgis/pull/528

diff --git a/NEWS b/NEWS
index a7ab9ba..822c1bd 100644
--- a/NEWS
+++ b/NEWS
@@ -36,6 +36,7 @@ PostGIS 3.1.0
   - #4592, Add missing CPPFLAGS in multiple Makefiles (Raúl Marín)
   - #4599, ST_AddPoint: Accept -1 as a valid position (Raúl Marín)
   - #4600, Improve precision of ST_TileEnvelope (Raúl Marín)
+  - #4608, PG12: Fix several bugs in the index support function (Raúl Marín)
 
 
 PostGIS 3.0.0
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                                               |   1 +
 postgis/gserialized_supportfn.c                    | 132 +++++++++++++++++----
 regress/core/regress_brin_index_geography.sql      |   3 +
 regress/core/regress_brin_index_geography_expected |   2 +
 4 files changed, 114 insertions(+), 24 deletions(-)


hooks/post-receive
-- 
PostGIS


More information about the postgis-tickets mailing list