[SCM] PostGIS branch master updated. 3.6.0rc2-257-g119f8390a
git at osgeo.org
git at osgeo.org
Mon Dec 15 15:14:38 PST 2025
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 119f8390a9c775ce97af2cab93643af7e3133994 (commit)
from c9a00a2dfbdde5adcf7f9c419b035fd70024e6ab (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 119f8390a9c775ce97af2cab93643af7e3133994
Author: Paul Ramsey <pramsey at cleverelephant.ca>
Date: Mon Dec 15 15:14:17 2025 -0800
Convert POLYGON(EMPTY) a polygon with an empty ring into
POLYGON EMPTY a polygon with no rings, in the WKB input
routine. Handle any existing POLYGON(EMPTY) in the
gserialized_is_empty routine. References #6028
diff --git a/liblwgeom/cunit/cu_gserialized2.c b/liblwgeom/cunit/cu_gserialized2.c
index 6df3aa1f8..dd32828c7 100644
--- a/liblwgeom/cunit/cu_gserialized2.c
+++ b/liblwgeom/cunit/cu_gserialized2.c
@@ -271,33 +271,48 @@ static void test_gserialized2_is_empty(void)
{
int i = 0;
struct gserialized_empty_cases {
- const char* wkt;
+ int ishex;
+ const char* txt;
int isempty;
};
struct gserialized_empty_cases cases[] = {
- { "POINT EMPTY", 1 },
- { "POINT(1 1)", 0 },
- { "LINESTRING EMPTY", 1 },
- { "MULTILINESTRING EMPTY", 1 },
- { "MULTILINESTRING(EMPTY)", 1 },
- { "MULTILINESTRING(EMPTY,EMPTY)", 1 },
- { "MULTILINESTRING(EMPTY,(0 0,1 1))", 0 },
- { "MULTILINESTRING((0 0,1 1),EMPTY)", 0 },
- { "MULTILINESTRING(EMPTY,(0 0,1 1),EMPTY)", 0 },
- { "MULTILINESTRING(EMPTY,EMPTY,EMPTY)", 1 },
- { "GEOMETRYCOLLECTION(POINT EMPTY,MULTILINESTRING(EMPTY,EMPTY,EMPTY))", 1 },
- { "GEOMETRYCOLLECTION(POINT EMPTY,MULTILINESTRING(EMPTY),POINT(1 1))", 0 },
- { "GEOMETRYCOLLECTION(POINT EMPTY,MULTILINESTRING(EMPTY, (0 0)),POINT EMPTY)", 0 },
- { "GEOMETRYCOLLECTION(POLYGON EMPTY,POINT EMPTY,MULTILINESTRING(EMPTY,EMPTY),POINT EMPTY)", 1 },
- { "GEOMETRYCOLLECTION(POLYGON EMPTY,GEOMETRYCOLLECTION(POINT EMPTY),MULTILINESTRING(EMPTY,EMPTY),POINT EMPTY)", 1 },
- { NULL, 0 }
+ { 0, "POINT EMPTY", 1 },
+ { 0, "POINT(1 1)", 0 },
+ { 0, "LINESTRING EMPTY", 1 },
+ { 0, "MULTILINESTRING EMPTY", 1 },
+ { 0, "MULTILINESTRING(EMPTY)", 1 },
+ { 0, "MULTILINESTRING(EMPTY,EMPTY)", 1 },
+ { 0, "MULTILINESTRING(EMPTY,(0 0,1 1))", 0 },
+ { 0, "MULTILINESTRING((0 0,1 1),EMPTY)", 0 },
+ { 0, "MULTILINESTRING(EMPTY,(0 0,1 1),EMPTY)", 0 },
+ { 0, "MULTILINESTRING(EMPTY,EMPTY,EMPTY)", 1 },
+ { 0, "MULTIPOLYGON (((9 9, 9 1, 1 1, 2 4, 7 7, 9 9)), EMPTY)", 0 },
+ { 0, "GEOMETRYCOLLECTION(POINT EMPTY,MULTILINESTRING(EMPTY,EMPTY,EMPTY))", 1 },
+ { 0, "GEOMETRYCOLLECTION(POINT EMPTY,MULTILINESTRING(EMPTY),POINT(1 1))", 0 },
+ { 0, "GEOMETRYCOLLECTION(POINT EMPTY,MULTILINESTRING(EMPTY, (0 0)),POINT EMPTY)", 0 },
+ { 0, "GEOMETRYCOLLECTION(POLYGON EMPTY,POINT EMPTY,MULTILINESTRING(EMPTY,EMPTY),POINT EMPTY)", 1 },
+ { 0, "GEOMETRYCOLLECTION(POLYGON EMPTY,GEOMETRYCOLLECTION(POINT EMPTY),MULTILINESTRING(EMPTY,EMPTY),POINT EMPTY)", 1 },
+ { 1, "0101000000000000000000F87F000000000000F87F", 1 }, /* POINT EMPTY */
+ { 1, "010200000000000000", 1 }, /* LINESTRING EMPTY */
+ { 1, "010400000000000000", 1 }, /* MULTIPOINT EMPTY */
+ { 1, "0105000000020000000102000000020000000000000000000000000000000000000000000000000000000000000000000000010200000000000000", 0 }, /* MULTILINESTRING ((0 0, 0 0), EMPTY) */
+ { 1, "0105000000020000000102000000000000000102000000020000000000000000000000000000000000000000000000000000000000000000000000", 0 }, /* MULTILINESTRING (EMPTY,(0 0, 0 0)) */
+ { 1, "010300000000000000", 1 }, /* POLYGON EMPTY */
+ { 1, "01030000000100000000000000", 1 }, /* POLYGON(EMPTY) */
+ { 1, "010300000002000000000000000100000000000000000000000000000000000000", 0 }, /* POLYGON(EMPTY, (0 0)) */
+ { 1, "0107000000030000000102000000000000000103000000020000000000000000000000010200000000000000", 1}, /* GEOMETRYCOLLECTION(LINESTRING EMPTY, POLYGON(EMPTY, EMPTY), LINESTRING EMPTY) */
+ { 1, NULL, 0 }
};
- while( cases[i].wkt )
+ while( cases[i].txt )
{
- // i = 11;
- LWGEOM *lw = lwgeom_from_wkt(cases[i].wkt, LW_PARSER_CHECK_NONE);
+ LWGEOM *lw = NULL;
+ if (cases[i].ishex)
+ lw = lwgeom_from_hexwkb(cases[i].txt, LW_PARSER_CHECK_NONE);
+ else
+ lw = lwgeom_from_wkt(cases[i].txt, LW_PARSER_CHECK_NONE);
+
GSERIALIZED *g = gserialized2_from_lwgeom(lw, 0);
int ie = gserialized2_is_empty(g);
// printf("%s: we say %d, they say %d\n", cases[i].wkt, cases[i].isempty, ie);
@@ -309,7 +324,6 @@ static void test_gserialized2_is_empty(void)
}
-
static void test_on_gser2_lwgeom_count_vertices(void)
{
LWGEOM *lwgeom;
diff --git a/liblwgeom/gserialized2.c b/liblwgeom/gserialized2.c
index 5c40615f5..f2d824b17 100644
--- a/liblwgeom/gserialized2.c
+++ b/liblwgeom/gserialized2.c
@@ -224,16 +224,19 @@ void gserialized2_set_srid(GSERIALIZED *g, int32_t srid)
static size_t gserialized2_is_empty_recurse(const uint8_t *p, int *isempty);
static size_t gserialized2_is_empty_recurse(const uint8_t *p, int *isempty)
{
- int i;
- int32_t type, num;
+ uint32_t type = 0, num = 0;
+
+ /* Short circuit if we found any non-empty component */
+ if (!*isempty) return 0;
memcpy(&type, p, 4);
memcpy(&num, p+4, 4);
if (lwtype_is_collection(type))
{
+ /* Recurse into collections */
size_t lz = 8;
- for ( i = 0; i < num; i++ )
+ for ( uint32_t i = 0; i < num; i++ )
{
lz += gserialized2_is_empty_recurse(p+lz, isempty);
if (!*isempty)
@@ -244,14 +247,44 @@ static size_t gserialized2_is_empty_recurse(const uint8_t *p, int *isempty)
}
else
{
- *isempty = (num == 0 ? LW_TRUE : LW_FALSE);
- return 8;
+ size_t lz = 8;
+ /* Any non-collection with zero elements is empty */
+ if ( num == 0 )
+ {
+ *isempty = LW_TRUE;
+ }
+ /*
+ * Special case to handle polygon with a non-zero
+ * set of empty rings
+ * https://trac.osgeo.org/postgis/ticket/6028
+ */
+ else if ( num > 0 && type == POLYGONTYPE )
+ {
+ for ( uint32_t i = 0; i < num; i++ )
+ {
+ uint32_t lrnum;
+ memcpy(&lrnum, p+lz, 4);
+ lz += 4;
+ if ( lrnum > 0 )
+ {
+ *isempty = LW_FALSE;
+ return lz;
+ }
+ }
+ *isempty = LW_TRUE;
+ }
+ /* Any other non-collection with more than zero elements is not empty */
+ else
+ {
+ *isempty = LW_FALSE;
+ }
+ return lz;
}
}
int gserialized2_is_empty(const GSERIALIZED *g)
{
- int isempty = 0;
+ int isempty = LW_TRUE;
uint8_t *p = gserialized2_get_geometry_p(g);
gserialized2_is_empty_recurse(p, &isempty);
return isempty;
diff --git a/liblwgeom/lwin_wkb.c b/liblwgeom/lwin_wkb.c
index 476ff8ee2..26a59f1fc 100644
--- a/liblwgeom/lwin_wkb.c
+++ b/liblwgeom/lwin_wkb.c
@@ -578,6 +578,14 @@ static LWPOLY* lwpoly_from_wkb_state(wkb_parse_state *s)
return NULL;
}
+ /* Skip zero-member rings, they add nothing */
+ if ( pa->npoints == 0)
+ {
+ LWDEBUGF(2, "Skipping empty ring [%d]", i);
+ ptarray_free(pa);
+ continue;
+ }
+
/* Add ring to polygon */
if ( lwpoly_add_ring(poly, pa) == LW_FAILURE )
{
diff --git a/regress/core/tickets.sql b/regress/core/tickets.sql
index e24bcef05..eec195810 100644
--- a/regress/core/tickets.sql
+++ b/regress/core/tickets.sql
@@ -1664,3 +1664,15 @@ SELECT
FROM
(VALUES ('LINESTRING (170 290, 205 272)'),('LINESTRING (120 215, 176 197)'),('LINESTRING (170 290, 205 272)')) AS a(geom),
(VALUES ('POLYGON ((100 200, 140 230, 180 310, 280 310, 390 270, 400 210, 320 140, 215 141, 150 170, 100 200))')) AS b(geom);
+
+
+-- -------------------------------------------------------------------------------------
+-- #6028
+
+CREATE TABLE fault6028 (fid integer, geom geometry(Polygon,5015));
+CREATE INDEX fault6028_x ON fault6028 USING GIST (geom);
+INSERT INTO fault6028 (fid, geom)
+ VALUES (1, '0103000020971300000100000000000000'::GEOMETRY);
+SELECT * FROM fault6028;
+DROP TABLE IF EXISTS fault6028;
+
diff --git a/regress/core/tickets_expected b/regress/core/tickets_expected
index 6637f2d89..d8f7f5cf5 100644
--- a/regress/core/tickets_expected
+++ b/regress/core/tickets_expected
@@ -499,3 +499,4 @@ public|test5978|shape|2|4326|POINT
#5938|1FF00F212|t
#5938|1FF00F212|t
#5938|1FF00F212|t
+1|01030000209713000000000000
-----------------------------------------------------------------------
Summary of changes:
liblwgeom/cunit/cu_gserialized2.c | 56 ++++++++++++++++++++++++---------------
liblwgeom/gserialized2.c | 45 ++++++++++++++++++++++++++-----
liblwgeom/lwin_wkb.c | 8 ++++++
regress/core/tickets.sql | 12 +++++++++
regress/core/tickets_expected | 1 +
5 files changed, 95 insertions(+), 27 deletions(-)
hooks/post-receive
--
PostGIS
More information about the postgis-tickets
mailing list