[postgis-tickets] r16058 - Make geometry a hashable type, allowing recursive CTEs

Paul Ramsey pramsey at cleverelephant.ca
Tue Oct 24 14:25:46 PDT 2017


Author: pramsey
Date: 2017-10-24 14:25:45 -0700 (Tue, 24 Oct 2017)
New Revision: 16058

Modified:
   trunk/NEWS
   trunk/postgis/lwgeom_btree.c
   trunk/postgis/postgis.sql.in
   trunk/regress/mvt.sql
   trunk/regress/mvt_expected
   trunk/regress/tickets.sql
   trunk/regress/tickets_expected
Log:
Make geometry a hashable type, allowing recursive CTEs
to use geometry in their signatures.
Closes #1014


Modified: trunk/NEWS
===================================================================
--- trunk/NEWS	2017-10-24 19:58:19 UTC (rev 16057)
+++ trunk/NEWS	2017-10-24 21:25:45 UTC (rev 16058)
@@ -1,5 +1,6 @@
 PostGIS 2.5.0
 2018/xx/xx
+
 * New Features *
   - #3876, ST_Angle function (RĂ©mi Cura)
   - #3564, ST_LineInterpolatePoints (Dan Baston)
@@ -21,7 +22,9 @@
   - #3234, Do not accept EMPTY points as topology nodes (Sandro Santilli)
   - #3892, Prevent version mixup when creating extension from unpackaged
            (Sandro Santilli)
+  - #1014, Hashable geometry, allowing direct use in CTE signatures (Paul Ramsey)
 
+
 PostGIS 2.4.0
 2017/09/30
 

Modified: trunk/postgis/lwgeom_btree.c
===================================================================
--- trunk/postgis/lwgeom_btree.c	2017-10-24 19:58:19 UTC (rev 16057)
+++ trunk/postgis/lwgeom_btree.c	2017-10-24 21:25:45 UTC (rev 16058)
@@ -27,6 +27,7 @@
 
 #include "postgres.h"
 #include "fmgr.h"
+#include "access/hash.h"
 #include "utils/geo_decls.h"
 
 #include "../postgis_config.h"
@@ -127,3 +128,18 @@
 	PG_RETURN_INT32(ret);
 }
 
+PG_FUNCTION_INFO_V1(lwgeom_hash);
+Datum lwgeom_hash(PG_FUNCTION_ARGS)
+{
+	GSERIALIZED *g1 = PG_GETARG_GSERIALIZED_P(0);
+	size_t sz1 = VARSIZE(g1);
+	size_t hsz1 = gserialized_header_size(g1);
+	uint8_t *b1 = (uint8_t*)g1 + hsz1;
+	size_t bsz1 = sz1 - hsz1;
+	Datum hval = hash_any(b1, bsz1);
+	PG_FREE_IF_COPY(g1, 0);
+	PG_RETURN_DATUM(hval);
+}
+
+
+

Modified: trunk/postgis/postgis.sql.in
===================================================================
--- trunk/postgis/postgis.sql.in	2017-10-24 19:58:19 UTC (rev 16057)
+++ trunk/postgis/postgis.sql.in	2017-10-24 21:25:45 UTC (rev 16058)
@@ -408,6 +408,23 @@
 	FUNCTION	1	geometry_cmp (geom1 geometry, geom2 geometry);
 
 
+--
+-- Sorting operators for Btree
+--
+
+-- Availability: 2.5.0
+CREATE FUNCTION geometry_hash(geometry)
+	RETURNS integer
+	AS 'MODULE_PATHNAME','lwgeom_hash'
+	LANGUAGE 'c' STRICT IMMUTABLE _PARALLEL;
+
+-- Availability: 2.5.0
+CREATE OPERATOR CLASS hash_geometry_ops
+	DEFAULT FOR TYPE geometry USING hash AS
+    OPERATOR    1   = ,
+    FUNCTION    1   geometry_hash(geometry);
+
+
 -----------------------------------------------------------------------------
 -- GiST 2D GEOMETRY-over-GSERIALIZED INDEX
 -----------------------------------------------------------------------------

Modified: trunk/regress/mvt.sql
===================================================================
--- trunk/regress/mvt.sql	2017-10-24 19:58:19 UTC (rev 16057)
+++ trunk/regress/mvt.sql	2017-10-24 21:25:45 UTC (rev 16058)
@@ -87,7 +87,7 @@
     ST_MakeBox2D(ST_Point(0, 0), ST_Point(4096, 4096)), 4096, 0, false)) AS geom
     UNION
     SELECT 2 AS c1, ST_Normalize(ST_AsMVTGeom(ST_GeomFromText('POINT(25 17)'),
-    ST_MakeBox2D(ST_Point(0, 0), ST_Point(4096, 4096)), 4096, 0, false)) AS geom) AS q;
+    ST_MakeBox2D(ST_Point(0, 0), ST_Point(4096, 4096)), 4096, 0, false)) AS geom ORDER BY c1) AS q;
 SELECT 'TA5', encode(ST_AsMVT(q, 'test', 4096, 'geom'), 'base64') FROM (SELECT
     ST_Normalize(ST_AsMVTGeom(ST_GeomFromText('POINT(25 17)'),
     ST_MakeBox2D(ST_Point(0, 0), ST_Point(4096, 4096)), 4096, 0, false)) AS geom, 1 AS c1, 'abcd'::text AS c2) AS q;
@@ -95,23 +95,23 @@
     ST_Normalize(ST_AsMVTGeom(ST_GeomFromText('POINT(25 17)'),
     ST_MakeBox2D(ST_Point(0, 0), ST_Point(4096, 4096)), 4096, 0, false)) AS geom) AS q;
 SELECT 'TA7', encode(ST_AsMVT(q, 'test', 4096, 'geom'), 'base64') FROM (
-    SELECT 'test' AS c1, ST_Normalize(ST_AsMVTGeom(ST_GeomFromText('POINT(25 17)'),
+    SELECT 'test' AS c1, 1 AS c2, ST_Normalize(ST_AsMVTGeom(ST_GeomFromText('POINT(25 17)'),
     ST_MakeBox2D(ST_Point(0, 0), ST_Point(4096, 4096)), 4096, 0, false)) AS geom
     UNION
-    SELECT 'test' AS c1, ST_Normalize(ST_AsMVTGeom(ST_GeomFromText('POINT(26 18)'),
+    SELECT 'test' AS c1, 2 AS c2, ST_Normalize(ST_AsMVTGeom(ST_GeomFromText('POINT(26 18)'),
     ST_MakeBox2D(ST_Point(0, 0), ST_Point(4096, 4096)), 4096, 0, false)) AS geom
     UNION
-    SELECT 'othertest' AS c1, ST_Normalize(ST_AsMVTGeom(ST_GeomFromText('POINT(26 18)'),
-    ST_MakeBox2D(ST_Point(0, 0), ST_Point(4096, 4096)), 4096, 0, false)) AS geom) AS q;
+    SELECT 'othertest' AS c1, 3 AS c2, ST_Normalize(ST_AsMVTGeom(ST_GeomFromText('POINT(26 18)'),
+    ST_MakeBox2D(ST_Point(0, 0), ST_Point(4096, 4096)), 4096, 0, false)) AS geom ORDER BY c2) AS q;
 SELECT 'TA8', encode(ST_AsMVT(q, 'test', 4096, 'geom'), 'base64') FROM (
-    SELECT 1::int AS c1, ST_Normalize(ST_AsMVTGeom(ST_GeomFromText('POINT(25 17)'),
+    SELECT 1::int AS c1, 1 AS c2, ST_Normalize(ST_AsMVTGeom(ST_GeomFromText('POINT(25 17)'),
     ST_MakeBox2D(ST_Point(0, 0), ST_Point(4096, 4096)), 4096, 0, false)) AS geom
     UNION
-    SELECT 1::int AS c1, ST_Normalize(ST_AsMVTGeom(ST_GeomFromText('POINT(26 18)'),
+    SELECT 1::int AS c1, 2 AS c2, ST_Normalize(ST_AsMVTGeom(ST_GeomFromText('POINT(26 18)'),
     ST_MakeBox2D(ST_Point(0, 0), ST_Point(4096, 4096)), 4096, 0, false)) AS geom
     UNION
-    SELECT 2::int AS c1, ST_Normalize(ST_AsMVTGeom(ST_GeomFromText('POINT(26 18)'),
-    ST_MakeBox2D(ST_Point(0, 0), ST_Point(4096, 4096)), 4096, 0, false)) AS geom) AS q;
+    SELECT 2::int AS c1, 3 AS c2, ST_Normalize(ST_AsMVTGeom(ST_GeomFromText('POINT(26 18)'),
+    ST_MakeBox2D(ST_Point(0, 0), ST_Point(4096, 4096)), 4096, 0, false)) AS geom ORDER BY c2) AS q;
 SELECT 'TA9', length(ST_AsMVT(q))
 FROM (
 	SELECT 1 AS c1, -1 AS c2,

Modified: trunk/regress/mvt_expected
===================================================================
--- trunk/regress/mvt_expected	2017-10-24 19:58:19 UTC (rev 16057)
+++ trunk/regress/mvt_expected	2017-10-24 21:25:45 UTC (rev 16058)
@@ -25,10 +25,10 @@
 TA4|GjMKBHRlc3QSDBICAAAYASIECTLePxIMEgIAARgBIgQJMt4/GgJjMSICKAEiAigCKIAgeAI=
 TA5|Gi8KBHRlc3QSDhIEAAABARgBIgQJMt4/GgJjMRoCYzIiAigBIgYKBGFiY2QogCB4Ag==
 TA6|GisKBHRlc3QSDhIEAAABARgBIgQJMt4/GgJjMRoCYzIiAigBIgIwASiAIHgC
-TA7|Gk4KBHRlc3QSDBICAAAYASIECTTcPxIMEgIAARgBIgQJMt4/EgwSAgABGAEiBAk03D8aAmMxIgsK
-CW90aGVydGVzdCIGCgR0ZXN0KIAgeAI=
-TA8|GkEKBHRlc3QSDBICAAAYASIECTLePxIMEgIAABgBIgQJNNw/EgwSAgABGAEiBAk03D8aAmMxIgIo
-ASICKAIogCB4Ag==
+TA7|GmQKBHRlc3QSDhIEAAABARgBIgQJMt4/Eg4SBAAAAQIYASIECTTcPxIOEgQAAwEEGAEiBAk03D8a
+AmMxGgJjMiIGCgR0ZXN0IgIoASICKAIiCwoJb3RoZXJ0ZXN0IgIoAyiAIHgC
+TA8|Gk8KBHRlc3QSDhIEAAABABgBIgQJMt4/Eg4SBAAAAQEYASIECTTcPxIOEgQAAQECGAEiBAk03D8a
+AmMxGgJjMiICKAEiAigCIgIoAyiAIHgC
 TA9|0
 TA10|49
 D1|Gi8KBHRlc3QSDhIEAAABARgBIgQJMt4/GgJjMRoCYzIiAigBIgYKBGFiY2QogCB4Ag==

Modified: trunk/regress/tickets.sql
===================================================================
--- trunk/regress/tickets.sql	2017-10-24 19:58:19 UTC (rev 16057)
+++ trunk/regress/tickets.sql	2017-10-24 21:25:45 UTC (rev 16058)
@@ -1025,5 +1025,31 @@
 -- #3774
 select '#3774', abs(pi() + 2 - st_length('COMPOUNDCURVE(CIRCULARSTRING(0 0, 1 1, 2 0), (2 0, 4 0))'::geometry)) < 0.000000001;
 
+-- #1014
+SELECT '#1014a', ST_AsText(g) FROM (
+	SELECT 'POINT(-0 0)'::geometry AS g
+	UNION
+	SELECT 'POINT(0 0)'::geometry AS g
+) a;
+SELECT '#1014b', ST_AsText(g) FROM (
+	SELECT 'POINT(0 1)'::geometry AS g
+	UNION
+	SELECT 'POINT(0 1)'::geometry AS g
+) a;
+CREATE TABLE rec (id integer, g geometry);
+INSERT INTO rec VALUES (1, 'POINT(0 1)');
+INSERT INTO rec VALUES (2, 'POINT(1 2)');
+INSERT INTO rec VALUES (3, 'POINT(2 3)');
+WITH RECURSIVE path (id, g) AS (
+    SELECT id, g FROM rec WHERE id = 1
+    UNION
+    SELECT rec.id, rec.g
+    FROM path, rec
+    WHERE ST_Y(path.g) = ST_X(rec.g)
+)
+SELECT '#1014c', id, st_astext(g) FROM path;
+DROP TABLE IF EXISTS rec;
+
+
 -- Clean up
 DELETE FROM spatial_ref_sys;

Modified: trunk/regress/tickets_expected
===================================================================
--- trunk/regress/tickets_expected	2017-10-24 19:58:19 UTC (rev 16057)
+++ trunk/regress/tickets_expected	2017-10-24 21:25:45 UTC (rev 16058)
@@ -306,3 +306,9 @@
 #3704|t
 #3709|t
 #3774|t
+#1014a|POINT(0 0)
+#1014a|POINT(-0 0)
+#1014b|POINT(0 1)
+#1014c|1|POINT(0 1)
+#1014c|2|POINT(1 2)
+#1014c|3|POINT(2 3)



More information about the postgis-tickets mailing list