diff --git a/mysql-test/main/gis.result b/mysql-test/main/gis.result index 2a32dcc61a9..967a0f0cea2 100644 --- a/mysql-test/main/gis.result +++ b/mysql-test/main/gis.result @@ -4582,6 +4582,12 @@ SELECT ST_ISSIMPLE(1); ERROR HY000: Illegal parameter data type int for operation 'st_issimple' SELECT ST_ISSIMPLE('test'); ERROR HY000: Illegal parameter data type varchar for operation 'st_issimple' +SELECT ST_ISVALID(ROW(1,1)); +ERROR HY000: Illegal parameter data type row for operation 'st_isvalid' +SELECT ST_ISVALID(1); +ERROR HY000: Illegal parameter data type int for operation 'st_isvalid' +SELECT ST_ISVALID('test'); +ERROR HY000: Illegal parameter data type varchar for operation 'st_isvalid' SELECT ST_ISRING(ROW(1,1)); ERROR HY000: Illegal parameter data type row for operation 'st_isring' SELECT ST_ISRING(1); @@ -5568,4 +5574,51 @@ CREATE TABLE t1 (a INT, b POINT GENERATED ALWAYS AS (a)); ERROR HY000: Cannot cast 'int' as 'point' in assignment of `test`.`t1`.`b` CREATE TABLE t1 (a POINT, b INT GENERATED ALWAYS AS (a)); ERROR HY000: Cannot cast 'point' as 'int' in assignment of `test`.`t1`.`b` +# # End of 11.5 tests +# +# +# Start of 11.6 tests +# +# +# MDEV-34276 Tests for ST_isValid +# +# Some tests for Point, multipoint, linestring +SET @g = ST_GEOMFROMTEXT('POINT(0 0)'); +SELECT ST_ISVALID(@g); +ST_ISVALID(@g) +1 +SELECT ISVALID(@g); +ISVALID(@g) +1 +SET @g = ST_GEOMFROMTEXT('POINT(15 0)'); +SELECT ST_ISVALID(@g); +ST_ISVALID(@g) +1 +SET @g = ST_GEOMFROMTEXT('MULTIPOINT(15 0, 10 0, 0 0, 11 11)'); +SELECT ST_ISVALID(@g); +ST_ISVALID(@g) +1 +SET @g = ST_GEOMFROMTEXT('LINESTRING(0 0, 1 1, 2 2, 2 3)'); +SELECT ST_ISVALID(@g); +ST_ISVALID(@g) +1 +# Some tests for Polygons +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((40 40, 20 45, 45 30, 40 40)), ((20 35, 10 30, 10 10, 30 5, 45 20, 20 35), (30 20, 20 15, 20 25, 30 20))')); +ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((40 40, 20 45, 45 30, 40 40)), ((20 35, 10 30, 10 10, 30 5, 45 20, 20 35), (30 20, 20 15, 20 25, 30 20))')) +1 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((30 10, 40 40, 20 40, 10 20, 30 10))')); +ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((30 10, 40 40, 20 40, 10 20, 30 10))')) +1 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((0 0, 0 2, 2 2, 1 1, 2 0, 0 0))')); +ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((0 0, 0 2, 2 2, 1 1, 2 0, 0 0))')) +1 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON(((0 0, 0 2, 2 2, 2 0, 0 0)),((4 4, 4 5, 5 5, 5 4, 4 4)))')) AS a; +a +1 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0), (15 15, 15 20, 20 20, 20 15, 15 15))')) as t; +t +0 +# +# End of 11.6 tests +# diff --git a/mysql-test/main/gis.test b/mysql-test/main/gis.test index abae0af4c3b..085c8a410b3 100644 --- a/mysql-test/main/gis.test +++ b/mysql-test/main/gis.test @@ -2628,6 +2628,13 @@ SELECT ST_ISSIMPLE(1); --error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION SELECT ST_ISSIMPLE('test'); +--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION +SELECT ST_ISVALID(ROW(1,1)); +--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION +SELECT ST_ISVALID(1); +--error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION +SELECT ST_ISVALID('test'); + --error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION SELECT ST_ISRING(ROW(1,1)); --error ER_ILLEGAL_PARAMETER_DATA_TYPE_FOR_OPERATION @@ -3573,4 +3580,46 @@ CREATE TABLE t1 (a INT, b POINT GENERATED ALWAYS AS (a)); --error ER_ILLEGAL_PARAMETER_DATA_TYPES2_FOR_OPERATION CREATE TABLE t1 (a POINT, b INT GENERATED ALWAYS AS (a)); + +--echo # --echo # End of 11.5 tests +--echo # + +--echo # +--echo # Start of 11.6 tests +--echo # + +--echo # +--echo # MDEV-34276 Tests for ST_isValid +--echo # + +--echo # Some tests for Point, multipoint, linestring + +SET @g = ST_GEOMFROMTEXT('POINT(0 0)'); +SELECT ST_ISVALID(@g); +SELECT ISVALID(@g); + +SET @g = ST_GEOMFROMTEXT('POINT(15 0)'); +SELECT ST_ISVALID(@g); + +SET @g = ST_GEOMFROMTEXT('MULTIPOINT(15 0, 10 0, 0 0, 11 11)'); +SELECT ST_ISVALID(@g); + +SET @g = ST_GEOMFROMTEXT('LINESTRING(0 0, 1 1, 2 2, 2 3)'); +SELECT ST_ISVALID(@g); + +--echo # Some tests for Polygons + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((40 40, 20 45, 45 30, 40 40)), ((20 35, 10 30, 10 10, 30 5, 45 20, 20 35), (30 20, 20 15, 20 25, 30 20))')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((30 10, 40 40, 20 40, 10 20, 30 10))')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((0 0, 0 2, 2 2, 1 1, 2 0, 0 0))')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON(((0 0, 0 2, 2 2, 2 0, 0 0)),((4 4, 4 5, 5 5, 5 4, 4 4)))')) AS a; + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((0 0, 10 0, 10 10, 0 10, 0 0), (15 15, 15 20, 20 20, 20 15, 15 15))')) as t; + +--echo # +--echo # End of 11.6 tests +--echo # diff --git a/mysql-test/main/spatial_utility_function_isvalid.result b/mysql-test/main/spatial_utility_function_isvalid.result new file mode 100644 index 00000000000..1278cd40cd2 --- /dev/null +++ b/mysql-test/main/spatial_utility_function_isvalid.result @@ -0,0 +1,411 @@ +# Creating the spatial Geometry object +USE test; +CREATE TABLE gis_geometrycollection (fid INTEGER NOT NULL PRIMARY KEY, g GEOMETRY); +SET @star_elem_vertical= 'POLYGON((5 0,15 25,25 0,15 5,5 0))'; +SET @star_elem_horizontal= 'POLYGON((25 0,0 15,30 15,22 10,25 0))'; +SET @star_center= 'POINT(15 10)'; +SET @star_top= 'POINT(15 25)'; +SET @star_bottom_left= 'POINT(5 0)'; +SET @star_bottom_right= 'POINT(25 0)'; +SET @star_bottom_points= 'MULTIPOINT(5 0,25 0)'; +SET @star_all_points= 'MULTIPOINT(5 0,25 0,15 10,15 25)'; +SET @star_line_horizontal= 'LINESTRING(10 15,20 15)'; +SET @star_line_vertical= 'LINESTRING(15 5,15 25)'; +SET @star_top_to_center= 'LINESTRING(15 25,15 10)'; +SET @star_lines_near_horizontal= 'MULTILINESTRING((25 0,0 15,15 30,0 5))'; +SET @star_lines_near_vertical= 'MULTILINESTRING((0 5,15 25,0 25))'; +SET @star= 'POLYGON((5 0,7 10,0 15,10 15,15 25,20 15,30 15,22 10,25 0,15 5,5 0))'; +SET @star_of_elems='MULTIPOLYGON(((5 0,15 25,25 0,15 5,5 0)),((25 0,0 15,30 15,22 10,25 0)))'; +SET @star_collection_elems='GEOMETRYCOLLECTION(MULTIPOLYGON(((5 0,15 25,25 0,15 5,5 0)),((25 0,0 15,30 15,22 10,25 0))),POLYGON((5 0,7 10,0 15,10 15,15 25,20 15,30 15,22 10,25 0,15 5,5 0)),LINESTRING(15 25,15 10),MULTIPOINT(5 0,25 0),POINT(15 25))'; +SET @star_collection_multilinestr='GEOMETRYCOLLECTION(MULTIPOLYGON(((5 0,15 25,25 0,15 5,5 0)),((25 0,0 15,30 15,22 10,25 0))),POLYGON((5 0,7 10,0 15,10 15,15 25,20 15,30 15,22 10,25 0,15 5,5 0)),MULTILINESTRING((25 0,0 15,15 30,0 5)),LINESTRING(15 25,15 10),MULTIPOINT(5 0,25 0),POINT(15 25))'; +# INSERT base star +INSERT INTO gis_geometrycollection VALUES +(100,ST_GEOMFROMTEXT(@star)), +(101,ST_GEOMFROMTEXT(@star_elem_vertical)), +(102,ST_GEOMFROMTEXT(@star_elem_horizontal)), +(103,ST_GEOMFROMTEXT(@star_of_elems)), +(104,ST_GEOMFROMTEXT(@star_top)), +(105,ST_GEOMFROMTEXT(@star_center)), +(106,ST_GEOMFROMTEXT(@star_bottom_left)), +(107,ST_GEOMFROMTEXT(@star_bottom_right)), +(108,ST_GEOMFROMTEXT(@star_bottom_points)), +(109,ST_GEOMFROMTEXT(@star_all_points)), +(110,ST_GEOMFROMTEXT(@star_line_horizontal)), +(111,ST_GEOMFROMTEXT(@star_line_vertical)), +(112,ST_GEOMFROMTEXT(@star_top_to_center)), +(113,ST_GEOMFROMTEXT(@star_lines_near_horizontal)), +(114,ST_GEOMFROMTEXT(@star_lines_near_vertical)), +(115,ST_GEOMFROMTEXT(@star_collection_elems)), +(116,ST_GEOMFROMTEXT(@star_collection_multilinestr)); +# Checking the integrity of the above create/insert statements +# 17 rows. +SELECT count(ST_ASTEXT(g) != 'NULL') FROM gis_geometrycollection; +count(ST_ASTEXT(g) != 'NULL') +17 +##################################################################################### +# ST_ISVALID(geometry) +##################################################################################### +#==================================================================================== +# point +#==================================================================================== +SELECT ST_ISVALID(ST_GEOMFROMTEXT(@star_center)); +ST_ISVALID(ST_GEOMFROMTEXT(@star_center)) +1 +SELECT ST_ISVALID(ST_GEOMFROMTEXT(@star_top)); +ST_ISVALID(ST_GEOMFROMTEXT(@star_top)) +1 +SELECT ST_ISVALID(g) FROM gis_geometrycollection WHERE fid=105; +ST_ISVALID(g) +1 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POINT(2.34 -2.34)')); +ST_ISVALID(ST_GEOMFROMTEXT('POINT(2.34 -2.34)')) +1 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POINT(1e308 -1e308)')); +ST_ISVALID(ST_GEOMFROMTEXT('POINT(1e308 -1e308)')) +1 +#==================================================================================== +# multipoint +#==================================================================================== +SELECT ST_ISVALID(ST_GEOMFROMTEXT(@star_all_points)); +ST_ISVALID(ST_GEOMFROMTEXT(@star_all_points)) +1 +SELECT ST_ISVALID(ST_GEOMFROMTEXT(@star_bottom_points)); +ST_ISVALID(ST_GEOMFROMTEXT(@star_bottom_points)) +1 +SELECT ST_ISVALID(g) FROM gis_geometrycollection WHERE fid=108; +ST_ISVALID(g) +1 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOINT(0 0,0 0,0 0,0 0)')); +ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOINT(0 0,0 0,0 0,0 0)')) +1 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOINT(0 0,0 5,5 5,5 0,0 0)')); +ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOINT(0 0,0 5,5 5,5 0,0 0)')) +1 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOINT(1 -1,1e308 -1e308,0.0001 0.000)')); +ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOINT(1 -1,1e308 -1e308,0.0001 0.000)')) +1 +#==================================================================================== +# linestring +#==================================================================================== +SELECT ST_ISVALID(ST_GEOMFROMTEXT(@star_top_to_center)); +ST_ISVALID(ST_GEOMFROMTEXT(@star_top_to_center)) +1 +SELECT ST_ISVALID(ST_GEOMFROMTEXT(@star_line_horizontal)); +ST_ISVALID(ST_GEOMFROMTEXT(@star_line_horizontal)) +1 +SELECT ST_ISVALID(g) FROM gis_geometrycollection WHERE fid=110; +ST_ISVALID(g) +1 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('LINESTRING(0 0)')); +ST_ISVALID(ST_GEOMFROMTEXT('LINESTRING(0 0)')) +0 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('LINESTRING(0 0,-0.00 0,0.0 0)')); +ST_ISVALID(ST_GEOMFROMTEXT('LINESTRING(0 0,-0.00 0,0.0 0)')) +0 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('LINESTRING(0 0,0 5,5 5,5 0,0 0)')); +ST_ISVALID(ST_GEOMFROMTEXT('LINESTRING(0 0,0 5,5 5,5 0,0 0)')) +1 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('LINESTRING(1 -1,1e308 -1e308,0.0001 0.000)')); +ST_ISVALID(ST_GEOMFROMTEXT('LINESTRING(1 -1,1e308 -1e308,0.0001 0.000)')) +1 +#==================================================================================== +# multilinestring +#==================================================================================== +SELECT ST_ISVALID(ST_GEOMFROMTEXT(@star_lines_near_vertical)); +ST_ISVALID(ST_GEOMFROMTEXT(@star_lines_near_vertical)) +1 +SELECT ST_ISVALID(ST_GEOMFROMTEXT(@star_lines_near_horizontal)); +ST_ISVALID(ST_GEOMFROMTEXT(@star_lines_near_horizontal)) +1 +SELECT ST_ISVALID(g) FROM gis_geometrycollection WHERE fid=114; +ST_ISVALID(g) +1 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTILINESTRING((0 0))')); +ST_ISVALID(ST_GEOMFROMTEXT('MULTILINESTRING((0 0))')) +0 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTILINESTRING((0 0,1 1,2 2),(3 3))')); +ST_ISVALID(ST_GEOMFROMTEXT('MULTILINESTRING((0 0,1 1,2 2),(3 3))')) +0 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTILINESTRING((0 0,-0.00 0),(0.0 0))')); +ST_ISVALID(ST_GEOMFROMTEXT('MULTILINESTRING((0 0,-0.00 0),(0.0 0))')) +0 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTILINESTRING((0 0,0 5,5 5,5 0,0 0))')); +ST_ISVALID(ST_GEOMFROMTEXT('MULTILINESTRING((0 0,0 5,5 5,5 0,0 0))')) +1 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTILINESTRING((0 10,10 0),(10 0,0 0),(0 0,10 10))')); +ST_ISVALID(ST_GEOMFROMTEXT('MULTILINESTRING((0 10,10 0),(10 0,0 0),(0 0,10 10))')) +1 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTILINESTRING((1 -1,1e308 -1e308,0.0001 0.000),(2 2,4 -9.002))')); +ST_ISVALID(ST_GEOMFROMTEXT('MULTILINESTRING((1 -1,1e308 -1e308,0.0001 0.000),(2 2,4 -9.002))')) +1 +#==================================================================================== +# polygon +#==================================================================================== +SELECT ST_ISVALID(ST_GEOMFROMTEXT(@star)); +ST_ISVALID(ST_GEOMFROMTEXT(@star)) +1 +SELECT ST_ISVALID(ST_GEOMFROMTEXT(@star_elem_vertical)); +ST_ISVALID(ST_GEOMFROMTEXT(@star_elem_vertical)) +1 +SELECT ST_ISVALID(g) FROM gis_geometrycollection WHERE fid=100; +ST_ISVALID(g) +1 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((0 0))')); +ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((0 0))')) +0 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((0 0,0 5,5 5,0 0))')); +ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((0 0,0 5,5 5,0 0))')) +1 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((0 0,0 10,10 10,10 0,0 0,0 0))')); +ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((0 0,0 10,10 10,10 0,0 0,0 0))')) +1 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((0 0,0 10,10 10,10 0,0 0,0 0,-10 0,-10 -10,0 -10,0 0))')); +ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((0 0,0 10,10 10,10 0,0 0,0 0,-10 0,-10 -10,0 -10,0 0))')) +0 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((0 0,0 10,10 10,10 0,0 0,0 0),(4 4,4 6,6 6,6 4,4 4))')); +ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((0 0,0 10,10 10,10 0,0 0,0 0),(4 4,4 6,6 6,6 4,4 4))')) +1 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((0 0,0 10,10 10,10 0,0 0,0 0),(0 0,0 10,10 10,10 0,0 0))')); +ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((0 0,0 10,10 10,10 0,0 0,0 0),(0 0,0 10,10 10,10 0,0 0))')) +0 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((4 4,4 6,6 6,6 4,4 4,4 4),(0 0,0 10,10 10,10 0,0 0))')); +ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((4 4,4 6,6 6,6 4,4 4,4 4),(0 0,0 10,10 10,10 0,0 0))')) +0 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((4 4,4 6,6 6,6 4,4 4,4 4),(8 8,8 10,10 10,10 8,8 8))')); +ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((4 4,4 6,6 6,6 4,4 4,4 4),(8 8,8 10,10 10,10 8,8 8))')) +0 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((0 0,0 10,10 10,10 0,0 0,0 0),(4 4,6 4,6 6,4 6,4 4),(4 4,4 6,6 6,6 4,4 4))')); +ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((0 0,0 10,10 10,10 0,0 0,0 0),(4 4,6 4,6 6,4 6,4 4),(4 4,4 6,6 6,6 4,4 4))')) +0 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((0 0,0 10,10 10,10 0,0 0,0 0),(4 4,6 4,6 6,4 6,4 4),(6 6,6 8,8 8,8 6,6 6))')); +ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((0 0,0 10,10 10,10 0,0 0,0 0),(4 4,6 4,6 6,4 6,4 4),(6 6,6 8,8 8,8 6,6 6))')) +1 +#==================================================================================== +# multipolygon +#==================================================================================== +SELECT ST_ISVALID(ST_GEOMFROMTEXT(@star_of_elems)); +ST_ISVALID(ST_GEOMFROMTEXT(@star_of_elems)) +0 +SELECT ST_ISVALID(g) FROM gis_geometrycollection WHERE fid=103; +ST_ISVALID(g) +0 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON(((0 0,0 5,5 5,0 0)))')); +ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON(((0 0,0 5,5 5,0 0)))')) +1 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON(((1 1, 1 1, 1 1, 1 1, 1 1)))')); +ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON(((1 1, 1 1, 1 1, 1 1, 1 1)))')) +0 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON(((0 10,10 0,0 0,0 10)),((0 0,10 10,10 0,0 0)))')); +ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON(((0 10,10 0,0 0,0 10)),((0 0,10 10,10 0,0 0)))')) +0 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON(((0 0,0 10,10 10,0 0)),((10 10,10 15,15 15,10 10)))')); +ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON(((0 0,0 10,10 10,0 0)),((10 10,10 15,15 15,10 10)))')) +1 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0,0 0)),((4 4,4 6,6 6,6 4,4 4,4 4)))')); +ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0,0 0)),((4 4,4 6,6 6,6 4,4 4,4 4)))')) +0 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0,0 0),(4 4,4 6,6 6,6 4,4 4)))')); +ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0,0 0),(4 4,4 6,6 6,6 4,4 4)))')) +1 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0,0 0),(0 0,0 10,10 10,10 0,0 0)))')); +ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0,0 0),(0 0,0 10,10 10,10 0,0 0)))')) +0 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON(((4 4,4 6,6 6,6 4,4 4,4 4),(0 0,0 10,10 10,10 0,0 0)))')); +ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON(((4 4,4 6,6 6,6 4,4 4,4 4),(0 0,0 10,10 10,10 0,0 0)))')) +0 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON(((4 4,4 6,6 6,6 4,4 4,4 4),(8 8,8 10,10 10,10 8,8 8)))')); +ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON(((4 4,4 6,6 6,6 4,4 4,4 4),(8 8,8 10,10 10,10 8,8 8)))')) +0 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON(((10 10,10 0,5 10,10 10)),((0 10,0 20,5 10,0 10)))')); +ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON(((10 10,10 0,5 10,10 10)),((0 10,0 20,5 10,0 10)))')) +1 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0,0 0),(4 4,4 6,6 6,6 4,4 4)),((4 4,4 6,6 6,6 4,4 4,4 4)))')); +ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0,0 0),(4 4,4 6,6 6,6 4,4 4)),((4 4,4 6,6 6,6 4,4 4,4 4)))')) +0 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0,0 0),(0 0,0 10,10 10,10 0,0 0)),((0 0,0 10,10 10,10 0,0 0,0 0)))')); +ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0,0 0),(0 0,0 10,10 10,10 0,0 0)),((0 0,0 10,10 10,10 0,0 0,0 0)))')) +0 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0,0 0),(0 0,0 10,10 10,10 0,0 0)),((0 0,0 10,10 10,10 0,0 0,0 0),(4 4,4 6,6 6,4 4)))')); +ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0,0 0),(0 0,0 10,10 10,10 0,0 0)),((0 0,0 10,10 10,10 0,0 0,0 0),(4 4,4 6,6 6,4 4)))')) +0 +#==================================================================================== +# geometrycollection +#==================================================================================== +SELECT ST_ISVALID(ST_GEOMFROMTEXT(@star_collection_elems)); +ST_ISVALID(ST_GEOMFROMTEXT(@star_collection_elems)) +0 +SELECT ST_ISVALID(ST_GEOMFROMTEXT(@star_collection_multilinestr)); +ST_ISVALID(ST_GEOMFROMTEXT(@star_collection_multilinestr)) +0 +SELECT ST_ISVALID(g) FROM gis_geometrycollection WHERE fid=115; +ST_ISVALID(g) +0 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION()')); +ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION()')) +1 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(LINESTRING(0 0))')); +ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(LINESTRING(0 0))')) +0 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(GEOMETRYCOLLECTION()))')); +ERROR 22023: Invalid GIS data provided to function st_isvalid. +SELECT ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(POINT(10 10),MULTIPOINT(0 0,10 10))')); +ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(POINT(10 10),MULTIPOINT(0 0,10 10))')) +1 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(POINT(10 10),MULTIPOINT(0 0,10 10)))')); +ERROR 22023: Invalid GIS data provided to function st_isvalid. +SELECT ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(LINESTRING(0 0),POINT(10 10))')); +ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(LINESTRING(0 0),POINT(10 10))')) +0 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(LINESTRING(0 0),GEOMETRYCOLLECTION())')); +ERROR 22023: Invalid GIS data provided to function st_isvalid. +SELECT ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(POLYGON((0 0,1 1,2 2,0 0)),GEOMETRYCOLLECTION())')); +ERROR 22023: Invalid GIS data provided to function st_isvalid. +SELECT ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(LINESTRING(0 0,10 10,20 20),POLYGON((0 0,10 10,100 100,0 0)))')); +ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(LINESTRING(0 0,10 10,20 20),POLYGON((0 0,10 10,100 100,0 0)))')) +0 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(LINESTRING(0 0),POLYGON((0 0,0 10,10 10,10 0,0 0,0 0),(4 4,4 6,6 6,6 4,4 4)))')); +ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(LINESTRING(0 0),POLYGON((0 0,0 10,10 10,10 0,0 0,0 0),(4 4,4 6,6 6,6 4,4 4)))')) +0 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(LINESTRING(1 1,2 2,3 3),' + 'MULTILINESTRING((0 0,0 10,10 10,10 0),(10 10,10 15,15 15,10 10)))')); +ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(LINESTRING(1 1,2 2,3 3),' + 'MULTILINESTRING((0 0,0 10,10 10,10 0),(10 10,10 15,15 15,10 10)))')) +1 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(POINT(10 10),' + 'MULTIPOINT(0 0,10 10),' + 'LINESTRING(1 1,2 2,3 3),' + 'MULTILINESTRING((0 0,0 10,10 10,10 0),(10 10,10 15,15 15,10 10)))')); +ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(POINT(10 10),' + 'MULTIPOINT(0 0,10 10),' + 'LINESTRING(1 1,2 2,3 3),' + +1 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(POLYGON((0 0,0 10,10 10,10 0,0 0,0 0)))')); +ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(POLYGON((0 0,0 10,10 10,10 0,0 0,0 0)))')) +1 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(' + 'GEOMETRYCOLLECTION(POLYGON((0 0,0 10,10 10,10 0,0 0,0 0)))))')); +ERROR 22023: Invalid GIS data provided to function st_isvalid. +SELECT ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(POLYGON((0 0,0 10,10 10,10 0,0 0,0 0),(4 4,4 6,6 6,6 4,4 4)),' + 'MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0,0 0)),((10 10,10 15,15 15,15 10,10 10))))')); +ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(POLYGON((0 0,0 10,10 10,10 0,0 0,0 0),(4 4,4 6,6 6,6 4,4 4)),' + 'MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0,0 0)),((10 10,10 15,15 15,15 10,10 10))))')) +1 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(POINT(10 10),' + 'MULTIPOINT(0 0,10 10)),' + 'GEOMETRYCOLLECTION(LINESTRING(1 1,2 2,3 3),' + 'MULTILINESTRING((0 0,0 10,10 10,10 0),(10 10,10 15,15 15,10 10))))')); +ERROR 22023: Invalid GIS data provided to function st_isvalid. +SELECT ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(POINT(10 10),' + 'MULTIPOINT(0 0,10 10)),' + 'GEOMETRYCOLLECTION(LINESTRING(1 1,2 2,3 3),' + 'MULTILINESTRING((0 0,0 10,10 10,10 0),(10 10,10 15,15 15,10 10))),' + 'GEOMETRYCOLLECTION(POLYGON((0 0,0 10,10 10,10 0,0 0,0 0),(4 4,4 6,6 6,6 4,4 4)),' + 'MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0,0 0)),((10 10,10 15,15 15,15 10,10 10)))))')); +ERROR 22023: Invalid GIS data provided to function st_isvalid. +SELECT ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(POINT(10 10),' + 'MULTIPOINT(0 0,10 10)),' + 'GEOMETRYCOLLECTION(LINESTRING(1 1,2 2,3 3),' + 'MULTILINESTRING((0 0,0 10,10 10,10 0),(10 10,10 15,15 15,10 10))),' + 'GEOMETRYCOLLECTION(GEOMETRYCOLLECTION()))')); +ERROR 22023: Invalid GIS data provided to function st_isvalid. +SELECT ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(POINT(0 0),' + 'LINESTRING(1 1,2 2,3 3),' + 'POLYGON((0 0,0 10,10 10,10 0,0 0,0 0),(4 4,4 6,6 6,6 4,4 4)),' + 'MULTIPOINT(0 0,10 10),' + 'MULTILINESTRING((0 0,0 10,10 10,10 0),(10 10,10 15,15 15,10 10)),' + 'MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0,0 0)),((10 10,10 15,15 15,15 10,10 10))))')); +ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(POINT(0 0),' + 'LINESTRING(1 1,2 2,3 3),' + 'POLYGON((0 0,0 10,10 10,10 0,0 0,0 0),(4 4,4 6,6 6,6 4,4 4)), +1 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(MULTILINESTRING((-7 -2,-9 3,-2 -8),(3 7,5 6,-7 -9,7 -1,-2 -8,2 9,4 6,-5 -5)),' + 'MULTILINESTRING((2 -2,2 -3,2 -1,-10 7,1 -2,-2 0,-9 -2,10 5,-7 -8,-9 -1,1 -1,-2 3,5 -9,-8 -9,-10 -9)),' + 'MULTIPOINT(-7 -5,6 9,7 4))')); +ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(MULTILINESTRING((-7 -2,-9 3,-2 -8),(3 7,5 6,-7 -9,7 -1,-2 -8,2 9,4 6,-5 -5)),' + 'MULTILINESTRING((2 -2,2 -3,2 -1,-10 7,1 -2,-2 0,-9 -2,10 5,-7 -8,-9 -1,1 -1 +1 +##################################################################################### +# Invalid function calls +##################################################################################### +SELECT ST_ISVALID(); +ERROR 42000: Incorrect parameter count in the call to native function 'ST_ISVALID' +SELECT ST_ISVALID(NULL); +ERROR 22023: Invalid GIS data provided to function st_isvalid. +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POINT()')); +ERROR 22023: Invalid GIS data provided to function st_isvalid. +SELECT ST_ISVALID(ST_GEOMFROMTEXT('LINESTRING()')); +ERROR 22023: Invalid GIS data provided to function st_isvalid. +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON(())')); +ERROR 22023: Invalid GIS data provided to function st_isvalid. +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOINT()')); +ERROR 22023: Invalid GIS data provided to function st_isvalid. +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTILINESTRING(())')); +ERROR 22023: Invalid GIS data provided to function st_isvalid. +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON((()))')); +ERROR 22023: Invalid GIS data provided to function st_isvalid. +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POINT(a 0)')); +ERROR 22023: Invalid GIS data provided to function st_isvalid. +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POINT(! 0)')); +ERROR 22023: Invalid GIS data provided to function st_isvalid. +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POINT('!' 0)')); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '!' 0)'))' at line 1 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POINT(12,34 0)')); +ERROR 22023: Invalid GIS data provided to function st_isvalid. +SELECT ST_ISVALID(ST_GEOMFROMTEXT('LINESTRING(a 0,10 10)')); +ERROR 22023: Invalid GIS data provided to function st_isvalid. +SELECT ST_ISVALID(ST_GEOMFROMTEXT('LINESTRING(0 0,! 10)')); +ERROR 22023: Invalid GIS data provided to function st_isvalid. +SELECT ST_ISVALID(ST_GEOMFROMTEXT('LINESTRING('!' 0,10 10)')); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '!' 0,10 10)'))' at line 1 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('LINESTRING(12,34 0,10 10)')); +ERROR 22023: Invalid GIS data provided to function st_isvalid. +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((a 0,10 10,10 0,0 0))')); +ERROR 22023: Invalid GIS data provided to function st_isvalid. +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((0 0,! 10,10 0,0 0))')); +ERROR 22023: Invalid GIS data provided to function st_isvalid. +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON(('!' 0,10 10,10 0,0 0))')); +ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near '!' 0,10 10,10 0,0 0))'))' at line 1 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((12,34 0,10 10,10 0,0 0))')); +ERROR 22023: Invalid GIS data provided to function st_isvalid. +SELECT ST_ISVALID(ST_GEOMFROMTEXT(@star_center,-1024)); +ST_ISVALID(ST_GEOMFROMTEXT(@star_center,-1024)) +1 +SELECT ST_ISVALID(ST_GEOMFROMTEXT(@star_all_points,-1)); +ST_ISVALID(ST_GEOMFROMTEXT(@star_all_points,-1)) +1 +SELECT ST_ISVALID(ST_GEOMFROMTEXT(@star_lines_near_vertical,4236)); +ST_ISVALID(ST_GEOMFROMTEXT(@star_lines_near_vertical,4236)) +1 +SELECT ST_ISVALID(ST_GEOMFROMTEXT(@star_elem_vertical,4294967295)); +ST_ISVALID(ST_GEOMFROMTEXT(@star_elem_vertical,4294967295)) +1 +SELECT ST_ISVALID(ST_GEOMFROMTEXT(@star_of_elems,4294967297)); +ST_ISVALID(ST_GEOMFROMTEXT(@star_of_elems,4294967297)) +0 +SELECT ST_ISVALID(ST_GEOMFROMTEXT(@star_collection_elems,4294967295000)); +ST_ISVALID(ST_GEOMFROMTEXT(@star_collection_elems,4294967295000)) +0 +SELECT ST_ISVALID( x'e6100000010100000000000000000000000000000000000000'); +ST_ISVALID( x'e6100000010100000000000000000000000000000000000000') +1 +# Clean up +DROP TABLE gis_geometrycollection; +######################################################################## +# BUG#21927394 ST_ISVALID() RETURNS FALSE WITH VALID POLYGON GEOMETRY +######################################################################## +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((72.8714768817168 +-167.0048853643874,9274.40641550926 3433.5957427942167,-58.09039811390054 +187.50989457746405,-81.09039811390053 179.50989457746405,-207.99999999999997 +135.36742435621204,-208 1,-208 0,-208 -276.9111154485375,49.8714768817168 +-176.0048853643874,72.8714768817168 -167.0048853643874))')); +ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((72.8714768817168 +-167.0048853643874,9274.40641550926 3433.5957427942167,-58.09039811390054 +187.50989457746405,-81.09039811390053 179.50989457746405,-207.99999999999997 +135.36742435621204,-208 1,-208 0,-208 -276.9111154 +1 +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((-200 0,-207.99999999999997 +135.36742435621204,-208 1,-208 0,-208 -276.9111154485375,-200 0))')); +ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((-200 0,-207.99999999999997 +135.36742435621204,-208 1,-208 0,-208 -276.9111154485375,-200 0))')) +1 diff --git a/mysql-test/main/spatial_utility_function_isvalid.test b/mysql-test/main/spatial_utility_function_isvalid.test new file mode 100644 index 00000000000..bbedc0e7b2e --- /dev/null +++ b/mysql-test/main/spatial_utility_function_isvalid.test @@ -0,0 +1,382 @@ + +# Copyright (c) 2014, Oracle and/or its affiliates +# Copyright (c) 2024, MariaDB Corporation. +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; version 2 of the License. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software +# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA + + +############################################################################################ +# Creating the spatial objects # +############################################################################################ + +--echo # Creating the spatial Geometry object +USE test; + +CREATE TABLE gis_geometrycollection (fid INTEGER NOT NULL PRIMARY KEY, g GEOMETRY); + +############################################################################################ +# Inserting the values specific to the spatial objects # +############################################################################################ + +# Geometric elements constructing a star and some of its elememts as base +SET @star_elem_vertical= 'POLYGON((5 0,15 25,25 0,15 5,5 0))'; +SET @star_elem_horizontal= 'POLYGON((25 0,0 15,30 15,22 10,25 0))'; +SET @star_center= 'POINT(15 10)'; +SET @star_top= 'POINT(15 25)'; +SET @star_bottom_left= 'POINT(5 0)'; +SET @star_bottom_right= 'POINT(25 0)'; +SET @star_bottom_points= 'MULTIPOINT(5 0,25 0)'; +SET @star_all_points= 'MULTIPOINT(5 0,25 0,15 10,15 25)'; +SET @star_line_horizontal= 'LINESTRING(10 15,20 15)'; +SET @star_line_vertical= 'LINESTRING(15 5,15 25)'; +SET @star_top_to_center= 'LINESTRING(15 25,15 10)'; +SET @star_lines_near_horizontal= 'MULTILINESTRING((25 0,0 15,15 30,0 5))'; +SET @star_lines_near_vertical= 'MULTILINESTRING((0 5,15 25,0 25))'; +SET @star= 'POLYGON((5 0,7 10,0 15,10 15,15 25,20 15,30 15,22 10,25 0,15 5,5 0))'; +SET @star_of_elems='MULTIPOLYGON(((5 0,15 25,25 0,15 5,5 0)),((25 0,0 15,30 15,22 10,25 0)))'; +SET @star_collection_elems='GEOMETRYCOLLECTION(MULTIPOLYGON(((5 0,15 25,25 0,15 5,5 0)),((25 0,0 15,30 15,22 10,25 0))),POLYGON((5 0,7 10,0 15,10 15,15 25,20 15,30 15,22 10,25 0,15 5,5 0)),LINESTRING(15 25,15 10),MULTIPOINT(5 0,25 0),POINT(15 25))'; +SET @star_collection_multilinestr='GEOMETRYCOLLECTION(MULTIPOLYGON(((5 0,15 25,25 0,15 5,5 0)),((25 0,0 15,30 15,22 10,25 0))),POLYGON((5 0,7 10,0 15,10 15,15 25,20 15,30 15,22 10,25 0,15 5,5 0)),MULTILINESTRING((25 0,0 15,15 30,0 5)),LINESTRING(15 25,15 10),MULTIPOINT(5 0,25 0),POINT(15 25))'; + +--echo # INSERT base star +--disable_warnings +INSERT INTO gis_geometrycollection VALUES + (100,ST_GEOMFROMTEXT(@star)), + (101,ST_GEOMFROMTEXT(@star_elem_vertical)), + (102,ST_GEOMFROMTEXT(@star_elem_horizontal)), + (103,ST_GEOMFROMTEXT(@star_of_elems)), + (104,ST_GEOMFROMTEXT(@star_top)), + (105,ST_GEOMFROMTEXT(@star_center)), + (106,ST_GEOMFROMTEXT(@star_bottom_left)), + (107,ST_GEOMFROMTEXT(@star_bottom_right)), + (108,ST_GEOMFROMTEXT(@star_bottom_points)), + (109,ST_GEOMFROMTEXT(@star_all_points)), + (110,ST_GEOMFROMTEXT(@star_line_horizontal)), + (111,ST_GEOMFROMTEXT(@star_line_vertical)), + (112,ST_GEOMFROMTEXT(@star_top_to_center)), + (113,ST_GEOMFROMTEXT(@star_lines_near_horizontal)), + (114,ST_GEOMFROMTEXT(@star_lines_near_vertical)), + (115,ST_GEOMFROMTEXT(@star_collection_elems)), + (116,ST_GEOMFROMTEXT(@star_collection_multilinestr)); +--enable_warnings + +--echo # Checking the integrity of the above create/insert statements + +--echo # 17 rows. +SELECT count(ST_ASTEXT(g) != 'NULL') FROM gis_geometrycollection; + +--echo ##################################################################################### +--echo # ST_ISVALID(geometry) +--echo ##################################################################################### + +--echo #==================================================================================== +--echo # point +--echo #==================================================================================== +SELECT ST_ISVALID(ST_GEOMFROMTEXT(@star_center)); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT(@star_top)); + +SELECT ST_ISVALID(g) FROM gis_geometrycollection WHERE fid=105; + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POINT(2.34 -2.34)')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POINT(1e308 -1e308)')); + +--echo #==================================================================================== +--echo # multipoint +--echo #==================================================================================== +SELECT ST_ISVALID(ST_GEOMFROMTEXT(@star_all_points)); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT(@star_bottom_points)); + +SELECT ST_ISVALID(g) FROM gis_geometrycollection WHERE fid=108; + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOINT(0 0,0 0,0 0,0 0)')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOINT(0 0,0 5,5 5,5 0,0 0)')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOINT(1 -1,1e308 -1e308,0.0001 0.000)')); + +--echo #==================================================================================== +--echo # linestring +--echo #==================================================================================== +SELECT ST_ISVALID(ST_GEOMFROMTEXT(@star_top_to_center)); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT(@star_line_horizontal)); + +SELECT ST_ISVALID(g) FROM gis_geometrycollection WHERE fid=110; + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('LINESTRING(0 0)')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('LINESTRING(0 0,-0.00 0,0.0 0)')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('LINESTRING(0 0,0 5,5 5,5 0,0 0)')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('LINESTRING(1 -1,1e308 -1e308,0.0001 0.000)')); + +--echo #==================================================================================== +--echo # multilinestring +--echo #==================================================================================== +SELECT ST_ISVALID(ST_GEOMFROMTEXT(@star_lines_near_vertical)); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT(@star_lines_near_horizontal)); + +SELECT ST_ISVALID(g) FROM gis_geometrycollection WHERE fid=114; + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTILINESTRING((0 0))')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTILINESTRING((0 0,1 1,2 2),(3 3))')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTILINESTRING((0 0,-0.00 0),(0.0 0))')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTILINESTRING((0 0,0 5,5 5,5 0,0 0))')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTILINESTRING((0 10,10 0),(10 0,0 0),(0 0,10 10))')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTILINESTRING((1 -1,1e308 -1e308,0.0001 0.000),(2 2,4 -9.002))')); + +--echo #==================================================================================== +--echo # polygon +--echo #==================================================================================== +SELECT ST_ISVALID(ST_GEOMFROMTEXT(@star)); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT(@star_elem_vertical)); + +SELECT ST_ISVALID(g) FROM gis_geometrycollection WHERE fid=100; + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((0 0))')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((0 0,0 5,5 5,0 0))')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((0 0,0 10,10 10,10 0,0 0,0 0))')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((0 0,0 10,10 10,10 0,0 0,0 0,-10 0,-10 -10,0 -10,0 0))')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((0 0,0 10,10 10,10 0,0 0,0 0),(4 4,4 6,6 6,6 4,4 4))')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((0 0,0 10,10 10,10 0,0 0,0 0),(0 0,0 10,10 10,10 0,0 0))')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((4 4,4 6,6 6,6 4,4 4,4 4),(0 0,0 10,10 10,10 0,0 0))')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((4 4,4 6,6 6,6 4,4 4,4 4),(8 8,8 10,10 10,10 8,8 8))')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((0 0,0 10,10 10,10 0,0 0,0 0),(4 4,6 4,6 6,4 6,4 4),(4 4,4 6,6 6,6 4,4 4))')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((0 0,0 10,10 10,10 0,0 0,0 0),(4 4,6 4,6 6,4 6,4 4),(6 6,6 8,8 8,8 6,6 6))')); + +--echo #==================================================================================== +--echo # multipolygon +--echo #==================================================================================== +SELECT ST_ISVALID(ST_GEOMFROMTEXT(@star_of_elems)); + +SELECT ST_ISVALID(g) FROM gis_geometrycollection WHERE fid=103; + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON(((0 0,0 5,5 5,0 0)))')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON(((1 1, 1 1, 1 1, 1 1, 1 1)))')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON(((0 10,10 0,0 0,0 10)),((0 0,10 10,10 0,0 0)))')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON(((0 0,0 10,10 10,0 0)),((10 10,10 15,15 15,10 10)))')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0,0 0)),((4 4,4 6,6 6,6 4,4 4,4 4)))')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0,0 0),(4 4,4 6,6 6,6 4,4 4)))')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0,0 0),(0 0,0 10,10 10,10 0,0 0)))')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON(((4 4,4 6,6 6,6 4,4 4,4 4),(0 0,0 10,10 10,10 0,0 0)))')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON(((4 4,4 6,6 6,6 4,4 4,4 4),(8 8,8 10,10 10,10 8,8 8)))')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON(((10 10,10 0,5 10,10 10)),((0 10,0 20,5 10,0 10)))')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0,0 0),(4 4,4 6,6 6,6 4,4 4)),((4 4,4 6,6 6,6 4,4 4,4 4)))')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0,0 0),(0 0,0 10,10 10,10 0,0 0)),((0 0,0 10,10 10,10 0,0 0,0 0)))')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0,0 0),(0 0,0 10,10 10,10 0,0 0)),((0 0,0 10,10 10,10 0,0 0,0 0),(4 4,4 6,6 6,4 4)))')); + +--echo #==================================================================================== +--echo # geometrycollection +--echo #==================================================================================== +SELECT ST_ISVALID(ST_GEOMFROMTEXT(@star_collection_elems)); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT(@star_collection_multilinestr)); + +SELECT ST_ISVALID(g) FROM gis_geometrycollection WHERE fid=115; + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION()')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(LINESTRING(0 0))')); + +--error ER_GIS_INVALID_DATA +SELECT ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(GEOMETRYCOLLECTION()))')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(POINT(10 10),MULTIPOINT(0 0,10 10))')); + +--error ER_GIS_INVALID_DATA +SELECT ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(POINT(10 10),MULTIPOINT(0 0,10 10)))')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(LINESTRING(0 0),POINT(10 10))')); + +--error ER_GIS_INVALID_DATA +SELECT ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(LINESTRING(0 0),GEOMETRYCOLLECTION())')); + +--error ER_GIS_INVALID_DATA +SELECT ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(POLYGON((0 0,1 1,2 2,0 0)),GEOMETRYCOLLECTION())')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(LINESTRING(0 0,10 10,20 20),POLYGON((0 0,10 10,100 100,0 0)))')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(LINESTRING(0 0),POLYGON((0 0,0 10,10 10,10 0,0 0,0 0),(4 4,4 6,6 6,6 4,4 4)))')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(LINESTRING(1 1,2 2,3 3),' + 'MULTILINESTRING((0 0,0 10,10 10,10 0),(10 10,10 15,15 15,10 10)))')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(POINT(10 10),' + 'MULTIPOINT(0 0,10 10),' + 'LINESTRING(1 1,2 2,3 3),' + 'MULTILINESTRING((0 0,0 10,10 10,10 0),(10 10,10 15,15 15,10 10)))')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(POLYGON((0 0,0 10,10 10,10 0,0 0,0 0)))')); + +--error ER_GIS_INVALID_DATA +SELECT ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(' + 'GEOMETRYCOLLECTION(POLYGON((0 0,0 10,10 10,10 0,0 0,0 0)))))')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(POLYGON((0 0,0 10,10 10,10 0,0 0,0 0),(4 4,4 6,6 6,6 4,4 4)),' + 'MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0,0 0)),((10 10,10 15,15 15,15 10,10 10))))')); +--error ER_GIS_INVALID_DATA +SELECT ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(POINT(10 10),' + 'MULTIPOINT(0 0,10 10)),' + 'GEOMETRYCOLLECTION(LINESTRING(1 1,2 2,3 3),' + 'MULTILINESTRING((0 0,0 10,10 10,10 0),(10 10,10 15,15 15,10 10))))')); +--error ER_GIS_INVALID_DATA +SELECT ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(POINT(10 10),' + 'MULTIPOINT(0 0,10 10)),' + 'GEOMETRYCOLLECTION(LINESTRING(1 1,2 2,3 3),' + 'MULTILINESTRING((0 0,0 10,10 10,10 0),(10 10,10 15,15 15,10 10))),' + 'GEOMETRYCOLLECTION(POLYGON((0 0,0 10,10 10,10 0,0 0,0 0),(4 4,4 6,6 6,6 4,4 4)),' + 'MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0,0 0)),((10 10,10 15,15 15,15 10,10 10)))))')); +--error ER_GIS_INVALID_DATA +SELECT ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(GEOMETRYCOLLECTION(POINT(10 10),' + 'MULTIPOINT(0 0,10 10)),' + 'GEOMETRYCOLLECTION(LINESTRING(1 1,2 2,3 3),' + 'MULTILINESTRING((0 0,0 10,10 10,10 0),(10 10,10 15,15 15,10 10))),' + 'GEOMETRYCOLLECTION(GEOMETRYCOLLECTION()))')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(POINT(0 0),' + 'LINESTRING(1 1,2 2,3 3),' + 'POLYGON((0 0,0 10,10 10,10 0,0 0,0 0),(4 4,4 6,6 6,6 4,4 4)),' + 'MULTIPOINT(0 0,10 10),' + 'MULTILINESTRING((0 0,0 10,10 10,10 0),(10 10,10 15,15 15,10 10)),' + 'MULTIPOLYGON(((0 0,0 10,10 10,10 0,0 0,0 0)),((10 10,10 15,15 15,15 10,10 10))))')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('GEOMETRYCOLLECTION(MULTILINESTRING((-7 -2,-9 3,-2 -8),(3 7,5 6,-7 -9,7 -1,-2 -8,2 9,4 6,-5 -5)),' + 'MULTILINESTRING((2 -2,2 -3,2 -1,-10 7,1 -2,-2 0,-9 -2,10 5,-7 -8,-9 -1,1 -1,-2 3,5 -9,-8 -9,-10 -9)),' + 'MULTIPOINT(-7 -5,6 9,7 4))')); + +--echo ##################################################################################### +--echo # Invalid function calls +--echo ##################################################################################### + +--error ER_WRONG_PARAMCOUNT_TO_NATIVE_FCT +SELECT ST_ISVALID(); + +--error ER_GIS_INVALID_DATA +SELECT ST_ISVALID(NULL); + +--error ER_GIS_INVALID_DATA +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POINT()')); + +--error ER_GIS_INVALID_DATA +SELECT ST_ISVALID(ST_GEOMFROMTEXT('LINESTRING()')); + +--error ER_GIS_INVALID_DATA +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON(())')); + +--error ER_GIS_INVALID_DATA +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOINT()')); + +--error ER_GIS_INVALID_DATA +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTILINESTRING(())')); + +--error ER_GIS_INVALID_DATA +SELECT ST_ISVALID(ST_GEOMFROMTEXT('MULTIPOLYGON((()))')); + +--error ER_GIS_INVALID_DATA +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POINT(a 0)')); + +--error ER_GIS_INVALID_DATA +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POINT(! 0)')); + +--error ER_PARSE_ERROR +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POINT('!' 0)')); + +--error ER_GIS_INVALID_DATA +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POINT(12,34 0)')); + +--error ER_GIS_INVALID_DATA +SELECT ST_ISVALID(ST_GEOMFROMTEXT('LINESTRING(a 0,10 10)')); + +--error ER_GIS_INVALID_DATA +SELECT ST_ISVALID(ST_GEOMFROMTEXT('LINESTRING(0 0,! 10)')); + +--error ER_PARSE_ERROR +SELECT ST_ISVALID(ST_GEOMFROMTEXT('LINESTRING('!' 0,10 10)')); + +--error ER_GIS_INVALID_DATA +SELECT ST_ISVALID(ST_GEOMFROMTEXT('LINESTRING(12,34 0,10 10)')); + +--error ER_GIS_INVALID_DATA +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((a 0,10 10,10 0,0 0))')); + +--error ER_GIS_INVALID_DATA +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((0 0,! 10,10 0,0 0))')); + +--error ER_PARSE_ERROR +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON(('!' 0,10 10,10 0,0 0))')); + +--error ER_GIS_INVALID_DATA +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((12,34 0,10 10,10 0,0 0))')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT(@star_center,-1024)); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT(@star_all_points,-1)); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT(@star_lines_near_vertical,4236)); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT(@star_elem_vertical,4294967295)); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT(@star_of_elems,4294967297)); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT(@star_collection_elems,4294967295000)); + +# This is an example of a working wkb, first the SRID, specification it is +# littleendian, and is a point with coordinates (0,0) +SELECT ST_ISVALID( x'e6100000010100000000000000000000000000000000000000'); + +--echo # Clean up +DROP TABLE gis_geometrycollection; + +--echo ######################################################################## +--echo # BUG#21927394 ST_ISVALID() RETURNS FALSE WITH VALID POLYGON GEOMETRY +--echo ######################################################################## +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((72.8714768817168 +-167.0048853643874,9274.40641550926 3433.5957427942167,-58.09039811390054 +187.50989457746405,-81.09039811390053 179.50989457746405,-207.99999999999997 +135.36742435621204,-208 1,-208 0,-208 -276.9111154485375,49.8714768817168 +-176.0048853643874,72.8714768817168 -167.0048853643874))')); + +SELECT ST_ISVALID(ST_GEOMFROMTEXT('POLYGON((-200 0,-207.99999999999997 +135.36742435621204,-208 1,-208 0,-208 -276.9111154485375,-200 0))')); diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc index beec45f7364..14b801e0cc1 100644 --- a/sql/item_geofunc.cc +++ b/sql/item_geofunc.cc @@ -2082,6 +2082,29 @@ mem_error: DBUG_RETURN(str_result); } +longlong Item_func_isvalid::val_int() +{ + String *wkb= args[0]->val_str(&tmp); + Geometry_buffer buffer; + Geometry *geometry; + + int valid; + if ((args[0]->null_value || + !(geometry= Geometry::construct(&buffer, wkb->ptr(), wkb->length())))) + { + my_error(ER_GIS_INVALID_DATA, MYF(0), func_name()); + null_value= 1; + return 1; + } + + if (geometry->is_valid(&valid)) + { + null_value= 1; + return 1; + } + + return (longlong) valid; +} bool Item_func_isempty::val_bool() { @@ -2089,7 +2112,7 @@ bool Item_func_isempty::val_bool() String tmp; String *swkb= args[0]->val_str(&tmp); Geometry_buffer buffer; - + null_value= args[0]->null_value || !(Geometry::construct(&buffer, swkb->ptr(), swkb->length())); return null_value ? 1 : 0; @@ -2100,71 +2123,29 @@ longlong Item_func_issimple::val_int() { String *swkb= args[0]->val_str(&tmp); Geometry_buffer buffer; - Gcalc_operation_transporter trn(&func, &collector); - Geometry *g; - int result= 1; - MBR mbr; - const char *c_end; + Geometry *geometry; DBUG_ENTER("Item_func_issimple::val_int"); DBUG_ASSERT(fixed()); - + null_value= 0; if ((args[0]->null_value || - !(g= Geometry::construct(&buffer, swkb->ptr(), swkb->length())) || - g->get_mbr(&mbr, &c_end))) + !(geometry= Geometry::construct(&buffer, swkb->ptr(), swkb->length())))) { /* We got NULL as an argument. Have to return -1 */ DBUG_RETURN(-1); } - collector.set_extent(mbr.xmin, mbr.xmax, mbr.ymin, mbr.ymax); - - if (g->get_class_info()->m_type_id == Geometry::wkb_point) + if (geometry->get_class_info()->m_type_id == Geometry::wkb_point) DBUG_RETURN(1); - if (g->store_shapes(&trn)) - goto mem_error; - - collector.prepare_operation(); - scan_it.init(&collector); - - while (scan_it.more_points()) - { - const Gcalc_scan_iterator::event_point *ev, *next_ev; - - if (scan_it.step()) - goto mem_error; - - ev= scan_it.get_events(); - if (ev->simple_event()) - continue; - - next_ev= ev->get_next(); - if ((ev->event & (scev_thread | scev_single_point)) && !next_ev) - continue; - - if ((ev->event == scev_two_threads) && !next_ev->get_next()) - continue; - - /* If the first and last points of a curve coincide - that is */ - /* an exception to the rule and the line is considered as simple. */ - if ((next_ev && !next_ev->get_next()) && - (ev->event & (scev_thread | scev_end)) && - (next_ev->event & (scev_thread | scev_end))) - continue; - - result= 0; - break; + int simple; + if (geometry->is_simple(&simple)) { + null_value= 1; + DBUG_RETURN(0); } - collector.reset(); - func.reset(); - scan_it.reset(); - DBUG_RETURN(result); -mem_error: - null_value= 1; - DBUG_RETURN(0); + DBUG_RETURN(simple); } @@ -4240,6 +4221,22 @@ protected: }; +class Create_func_isvalid : public Create_func_arg1 +{ +public: + Item *create_1_arg(THD *thd, Item *arg1) override + { + return new (thd->mem_root) Item_func_isvalid(thd, arg1); + } + + static Create_func_isvalid s_singleton; + +protected: + Create_func_isvalid() = default; + virtual ~Create_func_isvalid() = default; +}; + + class Create_func_issimple : public Create_func_arg1 { public: @@ -4256,7 +4253,6 @@ protected: }; - class Create_func_numgeometries : public Create_func_arg1 { public: @@ -4526,6 +4522,7 @@ Create_func_intersection Create_func_intersection::s_singleton; Create_func_intersects Create_func_intersects::s_singleton; Create_func_isclosed Create_func_isclosed::s_singleton; Create_func_isempty Create_func_isempty::s_singleton; +Create_func_isvalid Create_func_isvalid::s_singleton; Create_func_isring Create_func_isring::s_singleton; Create_func_issimple Create_func_issimple::s_singleton; Create_func_mbr_contains Create_func_mbr_contains::s_singleton; @@ -4595,6 +4592,7 @@ static Native_func_registry func_array_geom[] = { { STRING_WITH_LEN("INTERSECTS") }, GEOM_BUILDER(Create_func_mbr_intersects)}, { { STRING_WITH_LEN("ISCLOSED") }, GEOM_BUILDER(Create_func_isclosed)}, { { STRING_WITH_LEN("ISEMPTY") }, GEOM_BUILDER(Create_func_isempty)}, + { { STRING_WITH_LEN("ISVALID") }, GEOM_BUILDER(Create_func_isvalid)}, { { STRING_WITH_LEN("ISRING") }, GEOM_BUILDER(Create_func_isring)}, { { STRING_WITH_LEN("ISSIMPLE") }, GEOM_BUILDER(Create_func_issimple)}, { { STRING_WITH_LEN("LINEFROMTEXT") }, GEOM_BUILDER(Create_func_geometry_from_text)}, @@ -4677,6 +4675,7 @@ static Native_func_registry func_array_geom[] = { { STRING_WITH_LEN("ST_INTERSECTS") }, GEOM_BUILDER(Create_func_intersects)}, { { STRING_WITH_LEN("ST_ISCLOSED") }, GEOM_BUILDER(Create_func_isclosed)}, { { STRING_WITH_LEN("ST_ISEMPTY") }, GEOM_BUILDER(Create_func_isempty)}, + { { STRING_WITH_LEN("ST_ISVALID") }, GEOM_BUILDER(Create_func_isvalid)}, { { STRING_WITH_LEN("ST_ISRING") }, GEOM_BUILDER(Create_func_isring)}, { { STRING_WITH_LEN("ST_ISSIMPLE") }, GEOM_BUILDER(Create_func_issimple)}, { { STRING_WITH_LEN("ST_LENGTH") }, GEOM_BUILDER(Create_func_glength)}, diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h index 74d448c3095..3522ee2c087 100644 --- a/sql/item_geofunc.h +++ b/sql/item_geofunc.h @@ -959,9 +959,6 @@ public: class Item_func_issimple: public Item_long_func_args_geometry { - Gcalc_heap collector; - Gcalc_function func; - Gcalc_scan_iterator scan_it; String tmp; public: Item_func_issimple(THD *thd, Item *a) @@ -1009,6 +1006,21 @@ public: { return get_item_copy(thd, this); } }; +class Item_func_isvalid: public Item_long_func_args_geometry +{ +public: + String tmp; + Item_func_isvalid(THD *thd, Item *a): Item_long_func_args_geometry(thd, a) {} + longlong val_int() override; + LEX_CSTRING func_name_cstring() const override + { + static LEX_CSTRING name= {STRING_WITH_LEN("st_isvalid") }; + return name; + } + Item *get_copy(THD *thd) override + { return get_item_copy(thd, this); } +}; + class Item_func_dimension: public Item_long_func_args_geometry { public: diff --git a/sql/spatial.cc b/sql/spatial.cc index 5cda8f6c979..1d47230910f 100644 --- a/sql/spatial.cc +++ b/sql/spatial.cc @@ -750,6 +750,56 @@ bool Geometry::envelope(String *result) const return 0; } +int Geometry::is_simple(int *simple) const { + Gcalc_scan_iterator scan_it; + Gcalc_heap collector; + Gcalc_function func; + Gcalc_operation_transporter trn(&func, &collector); + const char *c_end; + MBR mbr; + *simple= 0; + + if(this->get_mbr(&mbr, &c_end)) + return 1; + + collector.set_extent(mbr.xmin, mbr.xmax, mbr.ymin, mbr.ymax); + if (this->store_shapes(&trn)) + return 1; + + collector.prepare_operation(); + scan_it.init(&collector); + + while (scan_it.more_points()) + { + const Gcalc_scan_iterator::event_point *ev, *next_ev; + + if (scan_it.step()) + return 1; + + ev= scan_it.get_events(); + if (ev->simple_event()) + continue; + + next_ev= ev->get_next(); + if ((ev->event & (scev_thread | scev_single_point)) && !next_ev) + continue; + + if ((ev->event == scev_two_threads) && !next_ev->get_next()) + continue; + + /* If the first and last points of a curve coincide - that is */ + /* an exception to the rule and the line is considered as simple. */ + if ((next_ev && !next_ev->get_next()) && + (ev->event & (scev_thread | scev_end)) && + (next_ev->event & (scev_thread | scev_end))) + continue; + + return 0; + } + + *simple= 1; + return 0; +} /* Create a point from data. @@ -763,7 +813,6 @@ bool Geometry::envelope(String *result) const 0 ok 1 Can't reallocate 'result' */ - bool Geometry::create_point(String *result, const char *data) const { if (no_data(data, POINT_DATA_SIZE) || @@ -1045,6 +1094,17 @@ bool Gis_point::get_mbr(MBR *mbr, const char **end) const } +int Gis_point::is_valid(int *valid) const +{ + double x, y; + if (get_xy(&x, &y)) + return 1; + + *valid= 1; + return 0; +} + + int Gis_point::area(double *ar, const char **end) const { *ar= 0; @@ -1444,6 +1504,47 @@ int Gis_line_string::is_closed(int *closed) const } +int Gis_line_string::is_valid(int *valid) const +{ + Geometry_buffer buffer; + Geometry *geometry; + uint32 num_points; + *valid= 0; + + if (no_data(m_data, 4)) + return 1; + + num_points= uint4korr(m_data); + if (not_enough_points(m_data, num_points)) + return 1; + + double x, y, previous_x, previous_y; + for (uint32 i = 1; i <= num_points; i++) + { + String wkb= 0; + + if (wkb.reserve(SRID_SIZE + BYTE_ORDER_SIZE + WKB_HEADER_SIZE)) + return 1; + + wkb.q_append(SRID_PLACEHOLDER); + this->point_n(i, &wkb); + if (!(geometry= Geometry::construct(&buffer, wkb.ptr(), wkb.length()))|| + ((Gis_point *) geometry)->get_xy(&x, &y)) + return 1; + + if ((i != 1) && (x != previous_x || y != previous_y)) + { + *valid= 1; + return 0; + } + + previous_x = x; + previous_y = y; + } + return 0; +} + + int Gis_line_string::num_points(uint32 *n_points) const { *n_points= uint4korr(m_data); @@ -1801,6 +1902,75 @@ bool Gis_polygon::get_mbr(MBR *mbr, const char **end) const } +int Gis_polygon::is_valid(int *valid) const +{ + Geometry *exterior_ring, *interior_ring; + MBR exterior_mbr, interior_mbr; + uint32 num_interior_ring; + Geometry_buffer buffer; + const char *c_end; + String wkb= 0; + *valid= 0; + + if (wkb.reserve(SRID_SIZE + BYTE_ORDER_SIZE + WKB_HEADER_SIZE)) + return 1; + + wkb.q_append(SRID_PLACEHOLDER); + if (this->exterior_ring(&wkb) || + !(exterior_ring= Geometry::construct(&buffer, wkb.ptr(), wkb.length()))) + return 1; + + int valid_ring, simple; + if (exterior_ring->is_valid(&valid_ring) || + exterior_ring->is_simple(&simple)) + return 1; + + if (!valid_ring || !simple) + return 0; + + if (exterior_ring->get_mbr(&exterior_mbr, &c_end) || + this->num_interior_ring(&num_interior_ring)) + return 1; + + std::vector interior_mbrs; + for(uint32 i= 1; i <= num_interior_ring; i++) + { + String interior_wkb= 0; + if (interior_wkb.reserve(SRID_SIZE + BYTE_ORDER_SIZE + WKB_HEADER_SIZE)) + return 1; + + interior_wkb.q_append(SRID_PLACEHOLDER); + if (this->interior_ring_n(i, &interior_wkb)) + break; + + if (!(interior_ring= Geometry::construct(&buffer, interior_wkb.ptr(), + interior_wkb.length())) || + interior_ring->get_mbr(&interior_mbr, &c_end)) + return 1; + + if (!exterior_mbr.contains(&interior_mbr) || + exterior_mbr.equals(&interior_mbr)) + return 0; + + if (interior_ring->is_simple(&simple)) + return 1; + + if (!simple) + return 0; + + for (const auto &mbr : interior_mbrs) + { + if (interior_mbr.equals(&mbr) || interior_mbr.within(&mbr)) + return 0; + } + interior_mbrs.push_back(interior_mbr); + } + + *valid= 1; + return 0; +} + + int Gis_polygon::area(double *ar, const char **end_of_data) const { uint32 n_linear_rings; @@ -2265,6 +2435,21 @@ bool Gis_multi_point::get_data_as_json(String *txt, uint max_dec_digits, } +int Gis_multi_point::is_valid(int *valid) const +{ + uint32 num_points; + if (no_data(m_data, 4)) + return 1; + + num_points= uint4korr(m_data); + if (not_enough_points(m_data, num_points)) + return 1; + + *valid= 1; + return 0; +} + + bool Gis_multi_point::get_mbr(MBR *mbr, const char **end) const { return (*end= get_mbr_for_points(mbr, m_data, WKB_HEADER_SIZE)) == 0; @@ -2656,6 +2841,39 @@ bool Gis_multi_line_string::get_data_as_json(String *txt, uint max_dec_digits, } +int Gis_multi_line_string::is_valid(int *valid) const +{ + uint32 num_linestring; + Geometry_buffer buffer; + Geometry *geometry= NULL; + *valid= 0; + + if (no_data(m_data, 4)) + return 1; + num_linestring= uint4korr(m_data); + + for (uint32 i = 1; i <= num_linestring; i++) + { + String wkb = 0; + + wkb.q_append(SRID_PLACEHOLDER); + if (this->geometry_n(i, &wkb) || + !(geometry= Geometry::construct(&buffer, wkb.ptr(), wkb.length()))) + return 1; + + int line_valid; + if(geometry->is_valid(&line_valid)) + return 1; + + if (!line_valid) + return 0; + } + + *valid= 1; + return 0; +} + + bool Gis_multi_line_string::get_mbr(MBR *mbr, const char **end) const { uint32 n_line_strings; @@ -3079,6 +3297,51 @@ bool Gis_multi_polygon::get_data_as_json(String *txt, uint max_dec_digits, } +int Gis_multi_polygon::is_valid(int *valid) const +{ + Geometry_buffer buffer; + uint32 num_geometries; + std::vector mbrs; + Geometry *geometry; + *valid= 0; + + if (this->num_geometries(&num_geometries)) + return 1; + + for (uint32 i= 1; i <= num_geometries; i++) + { + String wkb= 0; + if (wkb.reserve(SRID_SIZE + BYTE_ORDER_SIZE + WKB_HEADER_SIZE)) + return 0; + + wkb.q_append(SRID_PLACEHOLDER); + if (this->geometry_n(i, &wkb) || + !(geometry= Geometry::construct(&buffer, wkb.ptr(), wkb.length()))) + return 1; + + int internal_valid; + const char *c_end; + MBR interior_mbr; + if (geometry->is_valid(&internal_valid) || + geometry->get_mbr(&interior_mbr, &c_end)) + return 1; + + if (!internal_valid) + return 0; + + for (const auto &mbr : mbrs) + { + if (interior_mbr.intersects(&mbr) && !interior_mbr.touches(&mbr)) + return 0; + } + mbrs.push_back(interior_mbr); + } + + *valid= 1; + return 0; +} + + bool Gis_multi_polygon::get_mbr(MBR *mbr, const char **end) const { uint32 n_polygons; @@ -3307,7 +3570,7 @@ bool Gis_geometry_collection::init_from_wkt(Gis_read_stream *trs, String *wkb) return 1; if (next_word.length != 5 || - (my_charset_latin1.strnncoll("empty", 5, next_word.str, 5) != 0)) + (my_charset_latin1.strnncoll("empty", 5, next_word.str, 5) != 0)) { for (;;) { @@ -3551,6 +3814,41 @@ bool Gis_geometry_collection::get_data_as_json(String *txt, uint max_dec_digits, } +int Gis_geometry_collection::is_valid(int *valid) const +{ + Geometry_buffer buffer; + uint32 num_geometries; + Geometry *geometry; + *valid= 0; + + if (this->num_geometries(&num_geometries)) + return 1; + + for (uint32 i= 1; i <= num_geometries; i++) + { + String wkb= 0; + + if (wkb.reserve(SRID_SIZE + BYTE_ORDER_SIZE + WKB_HEADER_SIZE)) + return 1; + + wkb.q_append(SRID_PLACEHOLDER); + if(this->geometry_n(i, &wkb) || + !(geometry= Geometry::construct(&buffer, wkb.ptr(), wkb.length()))) + return 1; + + int internal_valid; + if (geometry->is_valid(&internal_valid)) + return 1; + + if (!internal_valid) + return 0; + } + + *valid= 1; + return 0; +} + + bool Gis_geometry_collection::get_mbr(MBR *mbr, const char **end) const { uint32 n_objects; diff --git a/sql/spatial.h b/sql/spatial.h index f0e173eaaf2..291a65ebb74 100644 --- a/sql/spatial.h +++ b/sql/spatial.h @@ -19,6 +19,7 @@ #define SPATIAL_INCLUDED #include "sql_string.h" /* String, LEX_STRING */ +#include #include #include @@ -27,8 +28,10 @@ class Gis_read_stream; #include "gcalc_tools.h" const uint SRID_SIZE= 4; +const uint32 SRID_PLACEHOLDER= 0; const uint SIZEOF_STORED_DOUBLE= 8; -const uint POINT_DATA_SIZE= (SIZEOF_STORED_DOUBLE * 2); +const uint BYTE_ORDER_SIZE= 1; +const uint POINT_DATA_SIZE= (SIZEOF_STORED_DOUBLE * 2); const uint WKB_HEADER_SIZE= 1+4; const uint32 GET_SIZE_ERROR= ((uint32) -1); @@ -289,6 +292,7 @@ public: virtual int geom_length(double *len, const char **end) const { return -1; } virtual int area(double *ar, const char **end) const { return -1;} virtual int is_closed(int *closed) const { return -1; } + virtual int is_valid(int *valid) const { return -1; } virtual int num_interior_ring(uint32 *n_int_rings) const { return -1; } virtual int num_points(uint32 *n_points) const { return -1; } virtual int num_geometries(uint32 *num) const { return -1; } @@ -337,6 +341,7 @@ public: } bool envelope(String *result) const; + int is_simple(int *simple) const; static Class_info *ci_collection[wkb_last+1]; static bool create_point(String *result, double x, double y); @@ -405,7 +410,7 @@ public: bool get_data_as_json(String *txt, uint max_dec_digits, const char **end) const override; bool get_mbr(MBR *mbr, const char **end) const override; - + int is_valid(int *valid) const override; int get_xy(double *x, double *y) const { const char *data= m_data; @@ -479,6 +484,7 @@ public: int area(double *ar, const char **end) const override; int is_closed(int *closed) const override; int num_points(uint32 *n_points) const override; + int is_valid(int *valid) const override; int start_point(String *point) const override; int end_point(String *point) const override; int point_n(uint32 n, String *result) const override; @@ -509,6 +515,7 @@ public: bool get_data_as_json(String *txt, uint max_dec_digits, const char **end) const override; bool get_mbr(MBR *mbr, const char **end) const override; + int is_valid(int *valid) const override; int area(double *ar, const char **end) const override; int exterior_ring(String *result) const override; int num_interior_ring(uint32 *n_int_rings) const override; @@ -545,6 +552,7 @@ public: bool get_data_as_wkt(String *txt, const char **end) const override; bool get_data_as_json(String *txt, uint max_dec_digits, const char **end) const override; + int is_valid(int *valid) const override; bool get_mbr(MBR *mbr, const char **end) const override; int num_geometries(uint32 *num) const override; int geometry_n(uint32 num, String *result) const override; @@ -576,6 +584,7 @@ public: bool get_data_as_wkt(String *txt, const char **end) const override; bool get_data_as_json(String *txt, uint max_dec_digits, const char **end) const override; + int is_valid(int *valid) const override; bool get_mbr(MBR *mbr, const char **end) const override; int num_geometries(uint32 *num) const override; int geometry_n(uint32 num, String *result) const override; @@ -606,6 +615,7 @@ public: bool get_data_as_wkt(String *txt, const char **end) const override; bool get_data_as_json(String *txt, uint max_dec_digits, const char **end) const override; + int is_valid(int *valid) const override; bool get_mbr(MBR *mbr, const char **end) const override; int num_geometries(uint32 *num) const override; int geometry_n(uint32 num, String *result) const override; @@ -638,6 +648,7 @@ public: bool get_data_as_wkt(String *txt, const char **end) const override; bool get_data_as_json(String *txt, uint max_dec_digits, const char **end) const override; + int is_valid(int *valid) const override; bool get_mbr(MBR *mbr, const char **end) const override; int area(double *ar, const char **end) const override; int geom_length(double *len, const char **end) const override;