From f9976f0977d700891081590a4806fa470233f4c0 Mon Sep 17 00:00:00 2001 From: Paul Ramsey Date: Mon, 30 Jan 2012 00:37:45 +0000 Subject: [PATCH] GML for empty geometries should be NULL (#1377) git-svn-id: http://svn.osgeo.org/postgis/trunk@8966 b70326c6-7e19-0410-871a-916f4a2858ee --- liblwgeom/cunit/cu_out_gml.c | 75 ------------------------------------ liblwgeom/lwout_gml.c | 8 ++++ postgis/geography_inout.c | 5 +++ postgis/lwgeom_export.c | 9 +++-- postgis/lwgeom_in_gml.c | 32 +++++++++++++++ regress/empty_expected | 36 ++++++++--------- regress/tickets.sql | 10 +++++ regress/tickets_expected | 7 ++++ 8 files changed, 86 insertions(+), 96 deletions(-) diff --git a/liblwgeom/cunit/cu_out_gml.c b/liblwgeom/cunit/cu_out_gml.c index 706e01b16..f53261d39 100644 --- a/liblwgeom/cunit/cu_out_gml.c +++ b/liblwgeom/cunit/cu_out_gml.c @@ -721,19 +721,6 @@ static void out_gml_test_geoms_prefix(void) "0 12 3 4 5", NULL, 0, 0, "custom:"); - - /* GML2 - Empty GeometryCollection */ - do_gml2_test_prefix( - "GEOMETRYCOLLECTION EMPTY", - "", - NULL, 0, "custom:"); - - /* GML3 - Empty GeometryCollection */ - do_gml3_test_prefix( - "GEOMETRYCOLLECTION EMPTY", - "", - NULL, 0, 0, "custom:"); - /* GML2 - Nested GeometryCollection */ do_gml2_test_prefix( "GEOMETRYCOLLECTION(POINT(0 1),GEOMETRYCOLLECTION(LINESTRING(2 3,4 5)))", @@ -855,19 +842,6 @@ static void out_gml_test_geoms_prefix(void) "0 12 3 4 5", NULL, 0, 0, ""); - - /* GML2 - Empty GeometryCollection */ - do_gml2_test_prefix( - "GEOMETRYCOLLECTION EMPTY", - "", - NULL, 0, ""); - - /* GML3 - Empty GeometryCollection */ - do_gml3_test_prefix( - "GEOMETRYCOLLECTION EMPTY", - "", - NULL, 0, 0, ""); - /* GML2 - Nested GeometryCollection */ do_gml2_test_prefix( "GEOMETRYCOLLECTION(POINT(0 1),GEOMETRYCOLLECTION(LINESTRING(2 3,4 5)))", @@ -1103,54 +1077,6 @@ static void out_gml3_extent(void) } - -static void out_gml_test_empty(void) -{ - /* POINT EMPTY, GML2 */ - do_gml2_test("POINT EMPTY", "", NULL, 0); - - /* POINT EMPTY, GML3 */ - do_gml3_test("POINT EMPTY", "", NULL, 0, 0); - - /* LINESTRING EMPTY, GML2 */ - do_gml2_test("LINESTRING EMPTY", "", NULL, 0); - - /* LINESTRING EMPTY, GML3 */ - do_gml3_test("LINESTRING EMPTY", "", NULL, 0, 0); - - /* POLYGON EMPTY, GML2 */ - do_gml2_test("POLYGON EMPTY", "", NULL, 0); - - /* POLYGON EMPTY, GML3 */ - do_gml3_test("POLYGON EMPTY", "", NULL, 0, 0); - - /* MULTIPOINT EMPTY, GML2 */ - do_gml2_test("MULTIPOINT EMPTY", "", NULL, 0); - - /* MULTIPOINT EMPTY, GML3 */ - do_gml3_test("MULTIPOINT EMPTY", "", NULL, 0, 0); - - /* MULTILINESTRING EMPTY, GML2 */ - do_gml2_test("MULTILINESTRING EMPTY", "", NULL, 0); - - /* MULTILINESTRING EMPTY, GML3 */ - do_gml3_test("MULTILINESTRING EMPTY", "", NULL, 0, 0); - - /* MULTIPOLYGON EMPTY, GML2 */ - do_gml2_test("MULTIPOLYGON EMPTY", "", NULL, 0); - - /* MULTIPOLYGON EMPTY, GML3 */ - do_gml3_test("MULTIPOLYGON EMPTY", "", NULL, 0, 0); - - /* GEOMETRYCOLLECTION EMPTY, GML2 */ - do_gml2_test("GEOMETRYCOLLECTION EMPTY", "", NULL, 0); - - /* GEOMETRYCOLLECTION EMPTY, GML3 */ - do_gml3_test("GEOMETRYCOLLECTION EMPTY", "", NULL, 0, 0); - -} - - /* ** Used by test harness to register the tests in this file. */ @@ -1165,7 +1091,6 @@ CU_TestInfo out_gml_tests[] = PG_TEST(out_gml_test_geoms_nodims), PG_TEST(out_gml2_extent), PG_TEST(out_gml3_extent), - PG_TEST(out_gml_test_empty), CU_TEST_INFO_NULL }; CU_SuiteInfo out_gml_suite = {"out_gml", NULL, NULL, out_gml_tests}; diff --git a/liblwgeom/lwout_gml.c b/liblwgeom/lwout_gml.c index da6a834e9..04e5fe3a5 100644 --- a/liblwgeom/lwout_gml.c +++ b/liblwgeom/lwout_gml.c @@ -212,6 +212,10 @@ lwgeom_to_gml2(const LWGEOM *geom, const char *srs, int precision, const char* p { int type = geom->type; + /* Return null for empty (#1377) */ + if ( lwgeom_is_empty(geom) ) + return NULL; + switch (type) { case POINTTYPE: @@ -703,6 +707,10 @@ lwgeom_to_gml3(const LWGEOM *geom, const char *srs, int precision, int opts, con { int type = geom->type; + /* Return null for empty (#1377) */ + if ( lwgeom_is_empty(geom) ) + return NULL; + switch (type) { case POINTTYPE: diff --git a/postgis/geography_inout.c b/postgis/geography_inout.c index cd0bfea85..f710dc416 100644 --- a/postgis/geography_inout.c +++ b/postgis/geography_inout.c @@ -279,6 +279,11 @@ Datum geography_as_gml(PG_FUNCTION_ARGS) lwgeom_free(lwgeom); PG_FREE_IF_COPY(g, 1); + /* Return null on null */ + if ( ! gml ) + PG_RETURN_NULL(); + + /* Turn string result into text for return */ result = cstring2text(gml); lwfree(gml); diff --git a/postgis/lwgeom_export.c b/postgis/lwgeom_export.c index 2829b64de..f64f0c83e 100644 --- a/postgis/lwgeom_export.c +++ b/postgis/lwgeom_export.c @@ -234,11 +234,11 @@ Datum LWGEOM_asGML(PG_FUNCTION_ARGS) lwgeom = lwgeom_from_gserialized(geom); - if (version == 2 && lwopts & LW_GML_EXTENT) + if (version == 2 && lwopts & LW_GML_EXTENT) gml = lwgeom_extent_to_gml2(lwgeom, srs, precision, prefix); else if (version == 2) gml = lwgeom_to_gml2(lwgeom, srs, precision, prefix); - else if (version == 3 && lwopts & LW_GML_EXTENT) + else if (version == 3 && lwopts & LW_GML_EXTENT) gml = lwgeom_extent_to_gml3(lwgeom, srs, precision, lwopts, prefix); else if (version == 3) gml = lwgeom_to_gml3(lwgeom, srs, precision, lwopts, prefix); @@ -246,9 +246,12 @@ Datum LWGEOM_asGML(PG_FUNCTION_ARGS) lwgeom_free(lwgeom); PG_FREE_IF_COPY(geom, 1); + /* Return null on null */ + if ( ! gml ) + PG_RETURN_NULL(); + result = cstring2text(gml); lwfree(gml); - PG_RETURN_TEXT_P(result); } diff --git a/postgis/lwgeom_in_gml.c b/postgis/lwgeom_in_gml.c index a116698a7..3c6fc9c61 100644 --- a/postgis/lwgeom_in_gml.c +++ b/postgis/lwgeom_in_gml.c @@ -1473,6 +1473,10 @@ static LWGEOM* parse_gml_tin(xmlNodePtr xnode, bool *hasz, int *root_srid) if (is_xlink(xnode)) xnode = get_xlink_node(xnode); + parse_gml_srs(xnode, &srs); + if (*root_srid == SRID_UNKNOWN && srs.srid != SRID_UNKNOWN) + *root_srid = srs.srid; + geom = (LWGEOM *)lwcollection_construct_empty(TINTYPE, *root_srid, 1, 0); if (xnode->children == NULL) @@ -1519,6 +1523,10 @@ static LWGEOM* parse_gml_mpoint(xmlNodePtr xnode, bool *hasz, int *root_srid) if (is_xlink(xnode)) xnode = get_xlink_node(xnode); + parse_gml_srs(xnode, &srs); + if (*root_srid == SRID_UNKNOWN && srs.srid != SRID_UNKNOWN) + *root_srid = srs.srid; + geom = (LWGEOM *)lwcollection_construct_empty(MULTIPOINTTYPE, *root_srid, 1, 0); if (xnode->children == NULL) @@ -1550,6 +1558,10 @@ static LWGEOM* parse_gml_mline(xmlNodePtr xnode, bool *hasz, int *root_srid) if (is_xlink(xnode)) xnode = get_xlink_node(xnode); + parse_gml_srs(xnode, &srs); + if (*root_srid == SRID_UNKNOWN && srs.srid != SRID_UNKNOWN) + *root_srid = srs.srid; + geom = (LWGEOM *)lwcollection_construct_empty(MULTILINETYPE, *root_srid, 1, 0); if (xnode->children == NULL) @@ -1581,6 +1593,10 @@ static LWGEOM* parse_gml_mcurve(xmlNodePtr xnode, bool *hasz, int *root_srid) if (is_xlink(xnode)) xnode = get_xlink_node(xnode); + parse_gml_srs(xnode, &srs); + if (*root_srid == SRID_UNKNOWN && srs.srid != SRID_UNKNOWN) + *root_srid = srs.srid; + geom = (LWGEOM *)lwcollection_construct_empty(MULTILINETYPE, *root_srid, 1, 0); if (xnode->children == NULL) @@ -1613,6 +1629,10 @@ static LWGEOM* parse_gml_mpoly(xmlNodePtr xnode, bool *hasz, int *root_srid) if (is_xlink(xnode)) xnode = get_xlink_node(xnode); + parse_gml_srs(xnode, &srs); + if (*root_srid == SRID_UNKNOWN && srs.srid != SRID_UNKNOWN) + *root_srid = srs.srid; + geom = (LWGEOM *)lwcollection_construct_empty(MULTIPOLYGONTYPE, *root_srid, 1, 0); if (xnode->children == NULL) @@ -1644,6 +1664,10 @@ static LWGEOM* parse_gml_msurface(xmlNodePtr xnode, bool *hasz, int *root_srid) if (is_xlink(xnode)) xnode = get_xlink_node(xnode); + parse_gml_srs(xnode, &srs); + if (*root_srid == SRID_UNKNOWN && srs.srid != SRID_UNKNOWN) + *root_srid = srs.srid; + geom = (LWGEOM *)lwcollection_construct_empty(MULTIPOLYGONTYPE, *root_srid, 1, 0); if (xnode->children == NULL) @@ -1677,6 +1701,10 @@ static LWGEOM* parse_gml_psurface(xmlNodePtr xnode, bool *hasz, int *root_srid) if (is_xlink(xnode)) xnode = get_xlink_node(xnode); + parse_gml_srs(xnode, &srs); + if (*root_srid == SRID_UNKNOWN && srs.srid != SRID_UNKNOWN) + *root_srid = srs.srid; + geom = (LWGEOM *)lwcollection_construct_empty(POLYHEDRALSURFACETYPE, *root_srid, 1, 0); if (xnode->children == NULL) @@ -1721,6 +1749,10 @@ static LWGEOM* parse_gml_coll(xmlNodePtr xnode, bool *hasz, int *root_srid) if (is_xlink(xnode)) xnode = get_xlink_node(xnode); + parse_gml_srs(xnode, &srs); + if (*root_srid == SRID_UNKNOWN && srs.srid != SRID_UNKNOWN) + *root_srid = srs.srid; + geom = (LWGEOM *)lwcollection_construct_empty(COLLECTIONTYPE, *root_srid, 1, 0); if (xnode->children == NULL) diff --git a/regress/empty_expected b/regress/empty_expected index cf8d4f431..53f4e8b47 100644 --- a/regress/empty_expected +++ b/regress/empty_expected @@ -5,24 +5,24 @@ T2.1|SRID=4326;POLYGON EMPTY T2.2|SRID=4326;POLYGON EMPTY T2.3|SRID=4326;POLYGON EMPTY T2.4|4326|POLYGON -T3.1| -T3.2| -T3.3| -T3.4| -T3.5| -T3.6| -T3.7| -T3.8| -T3.9| -T3.10| -T3.11| -T3.12| -T3.13| -T3.14| -T3.15| -T3.16| -T3.17| -T3.18| +T3.1| +T3.2| +T3.3| +T3.4| +T3.5| +T3.6| +T3.7| +T3.8| +T3.9| +T3.10| +T3.11| +T3.12| +T3.13| +T3.14| +T3.15| +T3.16| +T3.17| +T3.18| ST_Buffer(empty, tolerance) == empty|010300000000000000 ST_Union(geometry, empty) == geometry|0103000000010000000400000000000000000000000000000000000000000000000000244000000000000000000000000000001440000000000000144000000000000000000000000000000000 ST_Union(empty, empty) == empty|010300000000000000 diff --git a/regress/tickets.sql b/regress/tickets.sql index 2dd4d00c0..8c5396883 100644 --- a/regress/tickets.sql +++ b/regress/tickets.sql @@ -330,6 +330,16 @@ SELECT '#677',round(ST_Distance_Spheroid(ST_GeomFromEWKT('MULTIPOLYGON(((-10 40, -- #680 -- SELECT '#680', encode(ST_AsBinary(geography(foo1.the_geom)),'hex') As result FROM ((SELECT ST_SetSRID(ST_MakePointM(i,j,m),4326) As the_geom FROM generate_series(-10,50,10) As i CROSS JOIN generate_series(50,70, 20) AS j CROSS JOIN generate_series(1,2) As m ORDER BY i, j, i*j*m)) As foo1 LIMIT 1; +-- #681 -- +SELECT '#681a', ST_AsGML(ST_GeomFromText('POINT EMPTY', 4326)); +SELECT '#681b', ST_AsGML(ST_GeomFromText('POLYGON EMPTY', 4326)); +SELECT '#681c', ST_AsGML(ST_GeomFromText('LINESTRING EMPTY', 4326)); +SELECT '#681d', ST_AsGML(ST_GeomFromText('MULTIPOINT EMPTY', 4326)); +SELECT '#681e', ST_AsGML(ST_GeomFromText('MULTILINESTRING EMPTY', 4326)); +SELECT '#681f', ST_AsGML(ST_GeomFromText('MULTIPOLYGON EMPTY', 4326)); +SELECT '#681g', ST_AsGML(ST_GeomFromText('GEOMETRYCOLLECTION EMPTY', 4326)); + + -- #682 -- SELECT '#682', ST_Buffer(ST_GeomFromText('POLYGON EMPTY',4326) , 0.5); diff --git a/regress/tickets_expected b/regress/tickets_expected index 223d681ed..57a99e628 100644 --- a/regress/tickets_expected +++ b/regress/tickets_expected @@ -99,6 +99,13 @@ NOTICE: IllegalArgumentException: Invalid number of points in LinearRing found #667|SRID=4326;CURVEPOLYGON(CIRCULARSTRING(30 40,-49.2314112161292 32.1963871193548,30 40)) #677|1121395 #680|01d107000000000000000024c000000000000049400000000000000040 +#681a| +#681b| +#681c| +#681d| +#681e| +#681f| +#681g| #682|0103000020E610000000000000 #683|0103000020E610000000000000 #684|0103000020E610000000000000 -- 2.50.1