diff --git a/contrib/babelfishpg_common/sql/geography.sql b/contrib/babelfishpg_common/sql/geography.sql index 8e6e2147390..00ad2c7f97d 100644 --- a/contrib/babelfishpg_common/sql/geography.sql +++ b/contrib/babelfishpg_common/sql/geography.sql @@ -433,6 +433,19 @@ CREATE OR REPLACE FUNCTION sys.STDimension(geom sys.GEOGRAPHY) END; $$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE; +--Parse +CREATE OR REPLACE FUNCTION sys.Geography__Parse(geography_tagged_text sys.NVARCHAR) + RETURNS sys.GEOGRAPHY + AS $$ + BEGIN + IF UPPER(geography_tagged_text COLLATE sys.DATABASE_DEFAULT) = 'NULL' THEN + RETURN NULL; + END IF; + + RETURN sys.geogfromtext_helper(geography_tagged_text, 4326); + END; + $$ LANGUAGE plpgsql STRICT IMMUTABLE PARALLEL SAFE; + --STGeomType CREATE OR REPLACE FUNCTION sys.STGeometryType(geog sys.GEOGRAPHY) RETURNS sys.NVARCHAR(4000) diff --git a/contrib/babelfishpg_common/sql/geometry.sql b/contrib/babelfishpg_common/sql/geometry.sql index eb470643d95..e5ec6d71908 100644 --- a/contrib/babelfishpg_common/sql/geometry.sql +++ b/contrib/babelfishpg_common/sql/geometry.sql @@ -449,6 +449,19 @@ CREATE OR REPLACE FUNCTION sys.STGeometryType(geom sys.GEOMETRY) END; $$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE; +--Parse +CREATE OR REPLACE FUNCTION sys.Geometry__Parse(geometry_tagged_text sys.NVARCHAR) + RETURNS sys.GEOMETRY + AS $$ + BEGIN + IF UPPER(geometry_tagged_text COLLATE sys.DATABASE_DEFAULT) = 'NULL' THEN + RETURN NULL; + END IF; + + RETURN sys.geomfromtext_helper(geometry_tagged_text, 0); + END; + $$ LANGUAGE plpgsql STRICT IMMUTABLE PARALLEL SAFE; + -- STDisjoint -- Checks if two geometries have no points in common CREATE OR REPLACE FUNCTION sys.STDisjoint(geom1 sys.GEOMETRY, geom2 sys.GEOMETRY) diff --git a/contrib/babelfishpg_common/sql/upgrades/spatial_types--6.0.0--6.1.0.sql b/contrib/babelfishpg_common/sql/upgrades/spatial_types--6.0.0--6.1.0.sql index be61622b28c..1a6c7621827 100644 --- a/contrib/babelfishpg_common/sql/upgrades/spatial_types--6.0.0--6.1.0.sql +++ b/contrib/babelfishpg_common/sql/upgrades/spatial_types--6.0.0--6.1.0.sql @@ -1,8 +1,34 @@ ------------------------------------------------------- ---- Include changes related to spatial types here ---- ------------------------------------------------------- ---STGeomType +--parse +--Geometry +CREATE OR REPLACE FUNCTION sys.Geometry__Parse(geometry_tagged_text sys.NVARCHAR) + RETURNS sys.GEOMETRY + AS $$ + BEGIN + IF UPPER(geometry_tagged_text COLLATE sys.DATABASE_DEFAULT) = 'NULL' THEN + RETURN NULL; + END IF; + + RETURN sys.geomfromtext_helper(geometry_tagged_text, 0); + END; + $$ LANGUAGE plpgsql STRICT IMMUTABLE PARALLEL SAFE; +--Geography +CREATE OR REPLACE FUNCTION sys.Geography__Parse(geography_tagged_text sys.NVARCHAR) + RETURNS sys.GEOGRAPHY + AS $$ + BEGIN + IF UPPER(geography_tagged_text COLLATE sys.DATABASE_DEFAULT) = 'NULL' THEN + RETURN NULL; + END IF; + + RETURN sys.geogfromtext_helper(geography_tagged_text, 4326); + END; + $$ LANGUAGE plpgsql STRICT IMMUTABLE PARALLEL SAFE; + +--STGeomType --Geometry CREATE OR REPLACE FUNCTION sys.STGeometryType(geom sys.GEOMETRY) RETURNS sys.NVARCHAR(4000) @@ -43,4 +69,4 @@ CREATE OR REPLACE FUNCTION sys.STGeometryType(geog sys.GEOGRAPHY) RAISE EXCEPTION 'Unexpected geometry type format: %. Expected ST_* prefix.', geom_type; END; - $$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE; \ No newline at end of file + $$ LANGUAGE plpgsql IMMUTABLE STRICT PARALLEL SAFE; diff --git a/contrib/babelfishpg_tsql/antlr/TSqlParser.g4 b/contrib/babelfishpg_tsql/antlr/TSqlParser.g4 index aa0fbec23ea..f280a1e1180 100644 --- a/contrib/babelfishpg_tsql/antlr/TSqlParser.g4 +++ b/contrib/babelfishpg_tsql/antlr/TSqlParser.g4 @@ -3962,6 +3962,7 @@ geospatial_static_method | STLINEFROMTEXT | STPOLYFROMTEXT | POINT + | PARSE ; hierarchyid_methods @@ -3970,7 +3971,6 @@ hierarchyid_methods hierarchyid_static_method : GETROOT - | PARSE ; datatype_static_method diff --git a/test/JDBC/expected/Test-spatial-functions-3-vu-cleanup.out b/test/JDBC/expected/Test-spatial-functions-3-vu-cleanup.out index 50f11453245..56f1c67de89 100644 --- a/test/JDBC/expected/Test-spatial-functions-3-vu-cleanup.out +++ b/test/JDBC/expected/Test-spatial-functions-3-vu-cleanup.out @@ -1,3 +1,21 @@ +USE TestGeospatialParse_DB + +DROP TABLE TestGeospatialParse_GeometryTable3 + +DROP TABLE TestGeospatialParse_GeographyTable3 + +USE MASTER + +DROP VIEW TestGeospatialParse_ParseGeomView3 + +DROP VIEW TestGeospatialParse_ParseGeogView3 + +DROP TABLE TestGeospatialParse_GeomTemp3 + +DROP TABLE TestGeospatialParse_GeogTemp3 + +DROP DATABASE TestGeospatialParse_DB + USE TestGeospatialMethods3_DB; DROP VIEW TestGeospatialMethods3_STGeometryType_GEOM_View_db; @@ -15,3 +33,4 @@ DROP TABLE TestGeospatialMethods3_STGeometryType_GEOM_Temp; DROP TABLE TestGeospatialMethods3_STGeometryType_GEOG_Temp; DROP DATABASE TestGeospatialMethods3_DB; + diff --git a/test/JDBC/expected/Test-spatial-functions-3-vu-prepare.out b/test/JDBC/expected/Test-spatial-functions-3-vu-prepare.out index 8c966de7172..5363d55fdff 100644 --- a/test/JDBC/expected/Test-spatial-functions-3-vu-prepare.out +++ b/test/JDBC/expected/Test-spatial-functions-3-vu-prepare.out @@ -1,3 +1,142 @@ +CREATE DATABASE TestGeospatialParse_DB; + +USE TestGeospatialParse_DB; + +CREATE TABLE TestGeospatialParse_GeometryTable3 ( ID INT PRIMARY KEY, GeomColumn geometry ); +INSERT INTO TestGeospatialParse_GeometryTable3 (ID, GeomColumn) VALUES (1, geometry::Parse('POINT(3.0 4.0)')); +~~ROW COUNT: 1~~ + +INSERT INTO TestGeospatialParse_GeometryTable3 (ID, GeomColumn) VALUES (2, geometry::Parse('LINESTRING(0 0, 1 1, 2 2)')); +~~ROW COUNT: 1~~ + +INSERT INTO TestGeospatialParse_GeometryTable3 (ID, GeomColumn) VALUES (3, geometry::Parse('POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))')); +~~ROW COUNT: 1~~ + +INSERT INTO TestGeospatialParse_GeometryTable3 (ID, GeomColumn) VALUES (4, geometry::Parse('POINT(1.0 2.0)')); +~~ROW COUNT: 1~~ + +INSERT INTO TestGeospatialParse_GeometryTable3 (ID, GeomColumn) VALUES (5, geometry::Parse('LINESTRING(0 0, 5 5)')); +~~ROW COUNT: 1~~ + +INSERT INTO TestGeospatialParse_GeometryTable3 (ID, GeomColumn) VALUES (7, geometry::Parse('LINESTRING(0 0 0, 1 1 1, 2 2 2)')); +~~ROW COUNT: 1~~ + +INSERT INTO TestGeospatialParse_GeometryTable3 (ID, GeomColumn) VALUES (8, geometry::Parse('LINESTRING M(0 0 0, 1 1 1, 2 2 2)')); +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: parse error - invalid geometry)~~ + +INSERT INTO TestGeospatialParse_GeometryTable3 (ID, GeomColumn) VALUES (9, geometry::Parse('LINESTRING(0 0 0 0, 1 1 1 1, 2 2 2 2)')); +~~ROW COUNT: 1~~ + +INSERT INTO TestGeospatialParse_GeometryTable3 (ID, GeomColumn) VALUES (10, geometry::Parse('POINT(1 2 3)')); +~~ROW COUNT: 1~~ + +INSERT INTO TestGeospatialParse_GeometryTable3 (ID, GeomColumn) VALUES (11, geometry::Parse('POINT M(1 2 3)')); +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: parse error - invalid geometry)~~ + +INSERT INTO TestGeospatialParse_GeometryTable3 (ID, GeomColumn) VALUES (12, geometry::Parse('POINT(1 2 3 4)')); +~~ROW COUNT: 1~~ + +INSERT INTO TestGeospatialParse_GeometryTable3 (ID, GeomColumn) VALUES (13, geometry::Parse('POLYGON((0 0 0, 0 1 1, 1 1 1, 1 0 0, 0 0 0))')); +~~ROW COUNT: 1~~ + +INSERT INTO TestGeospatialParse_GeometryTable3 (ID, GeomColumn) VALUES (14, geometry::Parse('POLYGON M((0 0 0, 0 1 1, 1 1 1, 1 0 0, 0 0 0))')); +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: parse error - invalid geometry)~~ + +INSERT INTO TestGeospatialParse_GeometryTable3 (ID, GeomColumn) VALUES (15, geometry::Parse('POLYGON((0 0 0 0, 0 1 1 1, 1 1 1 1, 1 0 0 0, 0 0 0 0))')); +~~ROW COUNT: 1~~ + + +CREATE TABLE TestGeospatialParse_GeographyTable3 ( ID INT PRIMARY KEY, GeogColumn geography ); +INSERT INTO TestGeospatialParse_GeographyTable3 (ID, GeogColumn) VALUES (1, geography::Parse('POINT(3.0 4.0)')); +~~ROW COUNT: 1~~ + +INSERT INTO TestGeospatialParse_GeographyTable3 (ID, GeogColumn) VALUES (2, geography::Parse('LINESTRING(0 0, 1 1, 2 2)')); +~~ROW COUNT: 1~~ + +INSERT INTO TestGeospatialParse_GeographyTable3 (ID, GeogColumn) VALUES (3, geography::Parse('POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))')); +~~ROW COUNT: 1~~ + +INSERT INTO TestGeospatialParse_GeographyTable3 (ID, GeogColumn) VALUES (4, geography::Parse('POINT(1.0 2.0)')); +~~ROW COUNT: 1~~ + +INSERT INTO TestGeospatialParse_GeographyTable3 (ID, GeogColumn) VALUES (5, geography::Parse('LINESTRING(0 0, 5 5)')); +~~ROW COUNT: 1~~ + +INSERT INTO TestGeospatialParse_GeographyTable3 (ID, GeogColumn) VALUES (6, geography::Parse('LINESTRING(0 0 0, 1 1 1, 2 2 2)')); +~~ROW COUNT: 1~~ + +INSERT INTO TestGeospatialParse_GeographyTable3 (ID, GeogColumn) VALUES (7, geography::Parse('LINESTRING M(0 0 0, 1 1 1, 2 2 2)')); +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: parse error - invalid geometry)~~ + +INSERT INTO TestGeospatialParse_GeographyTable3 (ID, GeogColumn) VALUES (8, geography::Parse('LINESTRING(0 0 0 0, 1 1 1 1, 2 2 2 2)')); +~~ROW COUNT: 1~~ + +INSERT INTO TestGeospatialParse_GeographyTable3 (ID, GeogColumn) VALUES (9, geography::Parse('POINT(1 2 3)')); +~~ROW COUNT: 1~~ + +INSERT INTO TestGeospatialParse_GeographyTable3 (ID, GeogColumn) VALUES (10, geography::Parse('POINT M(1 2 3)')); +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: parse error - invalid geometry)~~ + +INSERT INTO TestGeospatialParse_GeographyTable3 (ID, GeogColumn) VALUES (11, geography::Parse('POINT(1 2 3 4)')); +~~ROW COUNT: 1~~ + +INSERT INTO TestGeospatialParse_GeographyTable3 (ID, GeogColumn) VALUES (12, geography::Parse('POLYGON((0 0 0, 0 1 1, 1 1 1, 1 0 0, 0 0 0))')); +~~ROW COUNT: 1~~ + +INSERT INTO TestGeospatialParse_GeographyTable3 (ID, GeogColumn) VALUES (13, geography::Parse('POLYGON M((0 0 0, 0 1 1, 1 1 1, 1 0 0, 0 0 0))')); +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: parse error - invalid geometry)~~ + +INSERT INTO TestGeospatialParse_GeographyTable3 (ID, GeogColumn) VALUES (14, geography::Parse('POLYGON((0 0 0 0, 0 1 1 1, 1 1 1 1, 1 0 0 0, 0 0 0 0))')); +~~ROW COUNT: 1~~ + + + +USE MASTER + +CREATE TABLE TestGeospatialParse_GeomTemp3 ( ID INT PRIMARY KEY, GeomColumn geometry ); +INSERT INTO TestGeospatialParse_GeomTemp3 (ID, GeomColumn) VALUES (1, geometry::Parse('POINT(3.0 4.0)')); +~~ROW COUNT: 1~~ + +INSERT INTO TestGeospatialParse_GeomTemp3 (ID, GeomColumn) VALUES (2, geometry::Parse('LINESTRING(0 0, 1 1)')); +~~ROW COUNT: 1~~ + +INSERT INTO TestGeospatialParse_GeomTemp3 (ID, GeomColumn) VALUES (3, geometry::Parse('POLYGON((0 0, 0 2, 2 2, 2 0, 0 0))')); +~~ROW COUNT: 1~~ + +INSERT INTO TestGeospatialParse_GeomTemp3 (ID, GeomColumn) VALUES (4, geometry::Parse('POINT(47.65100 -22.34900)')); +~~ROW COUNT: 1~~ + + +CREATE TABLE TestGeospatialParse_GeogTemp3 ( ID INT PRIMARY KEY, GeogColumn geography ); +INSERT INTO TestGeospatialParse_GeogTemp3 (ID, GeogColumn) VALUES (1, geography::Parse('POINT(3.0 4.0)')); +~~ROW COUNT: 1~~ + +INSERT INTO TestGeospatialParse_GeogTemp3 (ID, GeogColumn) VALUES (2, geography::Parse('LINESTRING(0 0, 1 1)')); +~~ROW COUNT: 1~~ + +INSERT INTO TestGeospatialParse_GeogTemp3 (ID, GeogColumn) VALUES (3, geography::Parse('POLYGON((0 0, 0 2, 2 2, 2 0, 0 0))')); +~~ROW COUNT: 1~~ + +INSERT INTO TestGeospatialParse_GeogTemp3 (ID, GeogColumn) VALUES (4, geography::Parse('POINT(47.65100 -22.34900)')); +~~ROW COUNT: 1~~ + + +CREATE VIEW TestGeospatialParse_ParseGeomView3 AS SELECT GeomColumn.STAsText() AS ParsedGeom FROM TestGeospatialParse_GeomTemp3 ORDER BY GeomColumn.STX; + +CREATE VIEW TestGeospatialParse_ParseGeogView3 AS SELECT GeogColumn.STAsText() AS ParsedGeog FROM TestGeospatialParse_GeogTemp3 ORDER BY GeogColumn.Lat; + CREATE DATABASE TestGeospatialMethods3_DB; USE TestGeospatialMethods3_DB; diff --git a/test/JDBC/expected/Test-spatial-functions-3-vu-verify.out b/test/JDBC/expected/Test-spatial-functions-3-vu-verify.out index 967137cbfa9..35839387aed 100644 --- a/test/JDBC/expected/Test-spatial-functions-3-vu-verify.out +++ b/test/JDBC/expected/Test-spatial-functions-3-vu-verify.out @@ -1,4 +1,911 @@ +--Parse functions test +-- geometry::Parse with POINT +DECLARE @geomText NVARCHAR(MAX); +SET @geomText = 'POINT(1.0 2.0)'; +SELECT geometry::Parse(@geomText).STAsText() AS ParsedGeometry; +go +~~START~~ +nvarchar +POINT(1 2) +~~END~~ + + +-- geometry::Parse with LINESTRING +DECLARE @geomText NVARCHAR(MAX); +SET @geomText = 'LINESTRING(0 0, 1 1, 2 2)'; +SELECT geometry::Parse(@geomText).STAsText() AS ParsedGeometry; +go +~~START~~ +nvarchar +LINESTRING(0 0,1 1,2 2) +~~END~~ + + +DECLARE @geomText NVARCHAR(MAX); +SET @geomText = 'POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))'; +SELECT geometry::Parse(@geomText).STAsText() AS ParsedGeometry; +go +~~START~~ +nvarchar +POLYGON((0 0,0 1,1 1,1 0,0 0)) +~~END~~ + + +DECLARE @geogText NVARCHAR(MAX); +SET @geogText = 'POINT(1.0 2.0)'; +SELECT geography::Parse(@geogText).STAsText() AS ParsedGeography; +go +~~START~~ +nvarchar +POINT(1 2) +~~END~~ + + +DECLARE @geogText NVARCHAR(MAX); +SET @geogText = 'LINESTRING(0 0, 1 1, 2 2)'; +SELECT geography::Parse(@geogText).STAsText() AS ParsedGeography; +go +~~START~~ +nvarchar +LINESTRING(0 0,1 1,2 2) +~~END~~ + + +DECLARE @geogText NVARCHAR(MAX); +SET @geogText = 'POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))'; +SELECT geography::Parse(@geogText).STAsText() AS ParsedGeography; +go +~~START~~ +nvarchar +POLYGON((0 0,0 1,1 1,1 0,0 0)) +~~END~~ + + +-- Parse with real-world coordinates +DECLARE @geomText NVARCHAR(MAX); +SET @geomText = 'POINT(-122.34900 47.65100)'; +SELECT geometry::Parse(@geomText).STAsText() AS ParsedGeometry; +go +~~START~~ +nvarchar +POINT(-122.349 47.651) +~~END~~ + + +DECLARE @geogText NVARCHAR(MAX); +SET @geogText = 'POINT(-122.34900 47.65100)'; +SELECT geography::Parse(@geogText).STAsText() AS ParsedGeography; +go +~~START~~ +nvarchar +POINT(-122.349 47.651) +~~END~~ + + +-- Parse from table column +SELECT ID, geometry::Parse(GeomColumn.STAsText()).STAsText() AS ParsedGeom FROM TestGeospatialParse_GeomTemp3 ORDER BY ID; +go +~~START~~ +int#!#nvarchar +1#!#POINT(3 4) +2#!#LINESTRING(0 0,1 1) +3#!#POLYGON((0 0,0 2,2 2,2 0,0 0)) +4#!#POINT(47.651 -22.349) +~~END~~ + + +SELECT ID, geography::Parse(GeogColumn.STAsText()).STAsText() AS ParsedGeog FROM TestGeospatialParse_GeogTemp ORDER BY ID; +go +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: relation "testgeospatialparse_geogtemp" does not exist)~~ + + +-- Parse with STEquals in WHERE clause +DECLARE @searchText NVARCHAR(MAX); +SET @searchText = 'POINT(3.0 4.0)'; +SELECT ID FROM TestGeospatialParse_GeomTemp3 WHERE geometry::Parse(@searchText).STEquals(GeomColumn) = 1 ORDER BY ID; +go +~~START~~ +int +1 +~~END~~ + + +DECLARE @searchText NVARCHAR(MAX); +SET @searchText = 'POINT(3.0 4.0)'; +SELECT ID FROM TestGeospatialParse_GeogTemp WHERE geography::Parse(@searchText).STEquals(GeogColumn) = 1 ORDER BY ID; +go +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: relation "testgeospatialparse_geogtemp" does not exist)~~ + + +-- Parse with JOIN and STIntersects +DECLARE @refText NVARCHAR(MAX); +SET @refText = 'POINT(3.0 4.0)'; +SELECT g1.ID, g2.ID FROM TestGeospatialParse_GeomTemp3 g1 +JOIN TestGeospatialParse_GeomTemp3 g2 ON geometry::Parse(@refText).STIntersects(g1.GeomColumn) = 1 +ORDER BY g1.ID, g2.ID; +go +~~START~~ +int#!#int +1#!#1 +1#!#2 +1#!#3 +1#!#4 +~~END~~ + + +-- Parse with CASE and STDistance +DECLARE @testText NVARCHAR(MAX); +SET @testText = 'POINT(1.0 2.0)'; +SELECT ID, +CASE WHEN geometry::Parse(@testText).STDistance(GeomColumn) < 5.0 THEN 'Near' ELSE 'Far' END AS Proximity +FROM TestGeospatialParse_GeomTemp3 ORDER BY ID; +go +~~START~~ +int#!#varchar +1#!#Near +2#!#Near +3#!#Near +4#!#Far +~~END~~ + + +-- Parse with CTE +DECLARE @refText NVARCHAR(MAX); +SET @refText = 'POINT(3.0 4.0)'; +WITH ParseCTE AS ( + SELECT ID, geometry::Parse(@refText).STDistance(GeomColumn) AS Distance + FROM TestGeospatialParse_GeomTemp3 +) +SELECT * FROM ParseCTE WHERE Distance < 10.0 ORDER BY Distance; +go +~~START~~ +int#!#float +1#!#0.0 +3#!#2.23606797749979 +2#!#3.605551275463989 +~~END~~ + + +-- Parse with cross-database query (geometry) +DECLARE @refText NVARCHAR(MAX); +SET @refText = 'POINT(3.0 4.0)'; +SELECT ID, geometry::Parse(@refText).STDistance(GeomColumn) AS Distance +FROM TestGeospatialParse_DB.dbo.TestGeospatialParse_GeometryTable3ORDER BY ID; +go +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: syntax error near 'BY' at line 5 and character position 72)~~ + + +-- Parse with cross-database query (geography) +DECLARE @refText NVARCHAR(MAX); +SET @refText = 'POINT(3.0 4.0)'; +SELECT ID, geography::Parse(@refText).STDistance(GeogColumn) AS Distance +FROM TestGeospatialParse_DB.dbo.TestGeospatialParse_GeographyTable3 ORDER BY ID; +go +~~START~~ +int#!#float +1#!#0.0 +2#!#247520.76060020996 +3#!#399384.36945885984 +4#!#313588.39721259556 +5#!#77836.58790621723 +6#!#247520.76060020996 +8#!#247520.76060020996 +9#!#313588.39721259556 +11#!#313588.39721259556 +12#!#399384.36945885984 +14#!#399384.36945885984 +~~END~~ + + +-- NULL variable input (geometry) +DECLARE @nullText NVARCHAR(MAX); +SET @nullText = NULL; +SELECT geometry::Parse(@nullText) AS ParsedGeometry; +go +~~START~~ +geometry + +~~END~~ + + +-- NULL variable input (geography) +DECLARE @nullText NVARCHAR(MAX); +SET @nullText = NULL; +SELECT geography::Parse(@nullText) AS ParsedGeography; +go +~~START~~ +geography + +~~END~~ + + +-- 'NULL' string literal - should error +DECLARE @nullString NVARCHAR(MAX); +SET @nullString = 'NULL'; +SELECT geometry::Parse(@nullString) AS ParsedGeometry; +go +~~START~~ +geometry + +~~END~~ + + +DECLARE @nullString NVARCHAR(MAX); +SET @nullString = 'NULL'; +SELECT geography::Parse(@nullString) AS ParsedGeography; +go +~~START~~ +geography + +~~END~~ + + +-- POINT EMPTY +DECLARE @emptyPoint NVARCHAR(MAX); +SET @emptyPoint = 'POINT EMPTY'; +SELECT geometry::Parse(@emptyPoint).STAsText() AS ParsedGeometry; +go +~~START~~ +nvarchar +POINT EMPTY +~~END~~ + + +DECLARE @emptyPoint NVARCHAR(MAX); +SET @emptyPoint = 'POINT EMPTY'; +SELECT geography::Parse(@emptyPoint).STAsText() AS ParsedGeography; +go +~~START~~ +nvarchar +POINT EMPTY +~~END~~ + + +-- Whitespace handling +DECLARE @geomText NVARCHAR(MAX); +SET @geomText = ' POINT ( 1.0 2.0 ) '; +SELECT geometry::Parse(@geomText).STAsText() AS ParsedGeometry; +go +~~START~~ +nvarchar +POINT(1 2) +~~END~~ + + +DECLARE @geogText NVARCHAR(MAX); +SET @geogText = ' POINT ( 1.0 2.0 ) '; +SELECT geography::Parse(@geogText).STAsText() AS ParsedGeography; +go +~~START~~ +nvarchar +POINT(1 2) +~~END~~ + + +-- Parse with different case +DECLARE @lowerText NVARCHAR(MAX); +SET @lowerText = 'point(1.0 2.0)'; +SELECT geometry::Parse(@lowerText).STAsText() AS ParsedGeometry; +go +~~START~~ +nvarchar +POINT(1 2) +~~END~~ + + +DECLARE @upperText NVARCHAR(MAX); +SET @upperText = 'POINT(1.0 2.0)'; +SELECT geography::Parse(@upperText).STAsText() AS ParsedGeography; +go +~~START~~ +nvarchar +POINT(1 2) +~~END~~ + + +-- Nested function calls +SELECT ID, geometry::Parse(GeomColumn.STAsText()).STDimension() AS Dimension +FROM TestGeospatialParse_GeomTemp3 ORDER BY ID; +go +~~START~~ +int#!#int +1#!#0 +2#!#1 +3#!#2 +4#!#0 +~~END~~ + + +SELECT ID, geography::Parse(GeogColumn.STAsText()).STDimension() AS Dimension +FROM TestGeospatialParse_GeogTemp3 ORDER BY ID; +go +~~START~~ +int#!#int +1#!#0 +2#!#1 +3#!#2 +4#!#0 +~~END~~ + + +-- Parse with function results +SELECT geometry::Parse(geometry::Point(1.0, 2.0, 4326).STAsText()).STAsText() AS ParsedFromFunction; +go +~~START~~ +nvarchar +POINT(1 2) +~~END~~ + + +SELECT geography::Parse(geography::Point(1.0, 2.0, 4326).STAsText()).STAsText() AS ParsedFromFunction; +go +~~START~~ +nvarchar +POINT(2 1) +~~END~~ + + +-- Direct NULL input +SELECT geometry::Parse(NULL); +go +~~START~~ +geometry + +~~END~~ + + +SELECT geography::Parse(NULL); +go +~~START~~ +geography + +~~END~~ + + +-- 'NULL' string literal +SELECT geometry::Parse('NULL'); +go +~~START~~ +geometry + +~~END~~ + + +SELECT geography::Parse('NULL'); +go +~~START~~ +geography + +~~END~~ + + +SELECT geometry::Parse(' NULL '); +go +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Invalid geometry)~~ + + +-- XYZM coordinates (4D) +SELECT geometry::Parse('POINT(1 2 3 4)').STAsText(); +go +~~START~~ +nvarchar +POINT(1 2) +~~END~~ + + +SELECT geography::Parse('POINT(1 2 3 4)').STAsText(); +go +~~START~~ +nvarchar +POINT(1 2) +~~END~~ + + +-- XYZ coordinates (3D) +SELECT geometry::Parse('POINT(1 2 3)').STAsText(); +go +~~START~~ +nvarchar +POINT(1 2) +~~END~~ + + +SELECT geography::Parse('POINT(1 2 3)').STAsText(); +go +~~START~~ +nvarchar +POINT(1 2) +~~END~~ + + +-- Invalid: single coordinate - should error +SELECT geometry::Parse('POINT(1)'); +go +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Invalid geometry)~~ + + +SELECT geography::Parse('POINT(1)').STAsText(); +go +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Invalid geometry)~~ + + +-- Invalid polygon: insufficient points - should error +SELECT geometry::Parse('POLYGON((0 0, 1 1))'); +go +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: geometry requires more points)~~ + + +SELECT geography::Parse('POLYGON((0 0, 1 1))'); +go +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: geometry requires more points)~~ + + +-- Invalid WKT string - should error +SELECT geometry::Parse('hello'); +go +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Invalid geometry)~~ + + +SELECT geography::Parse('hello'); +go +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Invalid geometry)~~ + + +-- Large coordinate values +SELECT geometry::Parse('POINT(999999999 999999999)').STAsText(); +go +~~START~~ +nvarchar +POINT(999999999 999999999) +~~END~~ + + +SELECT geography::Parse('POINT(999999999 999999999)').STAsText(); +go +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Latitude values must be between -90 and 90 degrees)~~ + + +-- Boundary coordinate values +SELECT geometry::Parse('POINT(-180 -90)').STAsText(); +go +~~START~~ +nvarchar +POINT(-180 -90) +~~END~~ + + +SELECT geography::Parse('POINT(-180 -90)').STAsText(); +go +~~START~~ +nvarchar +POINT(-180 -90) +~~END~~ + + +-- LINESTRING EMPTY +SELECT geometry::Parse('LINESTRING EMPTY').STAsText(); +go +~~START~~ +nvarchar +LINESTRING EMPTY +~~END~~ + + +-- Case insensitivity for LINESTRING +SELECT geometry::Parse('lineString(0 0, 1 1)').STAsText(); +go +~~START~~ +nvarchar +LINESTRING(0 0,1 1) +~~END~~ + + +SELECT geography::Parse('LINESTRING EMPTY').STAsText(); +go +~~START~~ +nvarchar +LINESTRING EMPTY +~~END~~ + + +SELECT geography::Parse('lineString(0 0, 1 1)').STAsText(); +go +~~START~~ +nvarchar +LINESTRING(0 0,1 1) +~~END~~ + + +-- UNION with Parse +SELECT geometry::Parse('POINT(1 2)').STAsText() AS geom +UNION +SELECT geometry::Parse('POINT(3 4)').STAsText() +UNION +SELECT geometry::Parse('NULL').STAsText(); +ORDER BY geom DESC; +go +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: syntax error near 'ORDER' at line 7 and character position 0)~~ + + +-- GROUP BY with spatial type +SELECT GeomColumn.STGeometryType() AS GeomType, + COUNT(*) AS Count +FROM TestGeospatialParse_GeomTemp3 +GROUP BY GeomColumn.STGeometryType() +ORDER BY GeomType; +go +~~START~~ +nvarchar#!#int +LineString#!#1 +Point#!#2 +Polygon#!#1 +~~END~~ + + +-- Window function with Parse +SELECT ID, + geometry::Parse('POINT(0 0)').STDistance(GeomColumn) AS Distance, + ROW_NUMBER() OVER (ORDER BY geometry::Parse('POINT(0 0)').STDistance(GeomColumn)) AS RowNum +FROM TestGeospatialParse_GeomTemp3; +go +~~START~~ +int#!#float#!#bigint +2#!#0.0#!#1 +3#!#0.0#!#2 +1#!#5.0#!#3 +4#!#52.63169769255026#!#4 +~~END~~ + + +-- CAST result to VARCHAR +SELECT CAST(geometry::Parse('POINT(1 2)').STAsText() AS VARCHAR(100)) AS Result; +go +~~START~~ +varchar +POINT(1 2) +~~END~~ + + +-- Empty string - should error +SELECT geometry::Parse(''); +go +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Invalid input: string is empty or contains only whitespace characters)~~ + + +-- hierarchyid::Parse +select hierarchyid::Parse('/1/3/2/'); +go +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: 'HIERARCHYID datatype' is not currently supported in Babelfish)~~ + + +-- hierarchyid::Parse with variable +DECLARE @node hierarchyid; +SET @node = hierarchyid::Parse('/1/3/2/'); +SELECT @node AS NodeValue; +go +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: 'HIERARCHYID datatype' is not currently supported in Babelfish)~~ + + +-- CTE with multiple geometry types +WITH ParseCTE AS ( + SELECT 1 AS ID, geometry::Parse('POINT(1 2)').STAsText() AS GeomText + UNION ALL + SELECT 2, geometry::Parse('LINESTRING(0 0, 1 1)').STAsText() + UNION ALL + SELECT 3, geometry::Parse('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))').STAsText() +) +SELECT ID, GeomText FROM ParseCTE ORDER BY ID; +go +~~START~~ +int#!#nvarchar +1#!#POINT(1 2) +2#!#LINESTRING(0 0,1 1) +3#!#POLYGON((0 0,0 10,10 10,10 0,0 0)) +~~END~~ + + +-- CTE with geography types +WITH GeogCTE AS ( + SELECT 1 AS ID, geography::Parse('POINT(-122.349 47.651)').STAsText() AS GeogText + UNION ALL + SELECT 2, geography::Parse('LINESTRING(-122.36 47.65, -122.34 47.66)').STAsText() +) +SELECT ID, GeogText FROM GeogCTE ORDER BY ID; +go +~~START~~ +int#!#nvarchar +1#!#POINT(-122.349 47.651) +2#!#LINESTRING(-122.36 47.65,-122.34 47.66) +~~END~~ + + +-- Window function with STDimension +SELECT *, ROW_NUMBER() OVER (ORDER BY Dimension) AS RowNum FROM ( + SELECT 1 AS ID, geometry::Parse('POINT(1 2)').STDimension() AS Dimension + UNION ALL + SELECT 2, geometry::Parse('LINESTRING(0 0, 1 1)').STDimension() + UNION ALL + SELECT 3, geometry::Parse('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))').STDimension() +) AS Results; +go +~~START~~ +int#!#int#!#bigint +1#!#0#!#1 +2#!#1#!#2 +3#!#2#!#3 +~~END~~ + + +-- Schema-qualified Parse +SELECT sys.geometry::Parse('POINT(1 2)').STAsText() AS Result; +go +~~START~~ +nvarchar +POINT(1 2) +~~END~~ + + +-- Invalid geometry type - should error +SELECT geometry::Parse('INVALID(1 2)'); +go +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: Invalid geometry)~~ + + +-- GROUP BY with STDimension +SELECT Dimension, COUNT(*) AS Count FROM ( + SELECT geometry::Parse('POINT(1 2)').STDimension() AS Dimension + UNION ALL + SELECT geometry::Parse('POINT(3 4)').STDimension() + UNION ALL + SELECT geometry::Parse('LINESTRING(0 0, 1 1)').STDimension() + UNION ALL + SELECT geometry::Parse('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))').STDimension() +) AS Results +GROUP BY Dimension +ORDER BY Dimension; +go +~~START~~ +int#!#int +0#!#2 +1#!#1 +2#!#1 +~~END~~ + + +-- Parse returning geometry object (no STAsText) +SELECT geometry::Parse('POINT(1 2 3 4)'); +go +~~START~~ +geometry +00000000010F000000000000F03F000000000000004000000000000008400000000000001040 +~~END~~ + + +SELECT geometry::Parse('LINESTRING(0 0, 1 1)'); +go +~~START~~ +geometry +00000000011400000000000000000000000000000000000000000000F03F000000000000F03F +~~END~~ + + +SELECT geometry::Parse('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'); +go +~~START~~ +geometry +00000000010005000000000000000000000000000000000000000000000000000000000000000000244000000000000024400000000000002440000000000000244000000000000000000000000000000000000000000000000001000000020000000001000000FFFFFFFF0000000003 +~~END~~ + + +SELECT geometry::Parse('POINT(999999999 999999999)'); +go +~~START~~ +geometry +00000000010C000080FF64CDCD41000080FF64CDCD41 +~~END~~ + + +-- Z coordinate (elevation) +SELECT geometry::Parse('POINT Z(1 2 3)'); +go +~~START~~ +geometry +00000000010D000000000000F03F00000000000000400000000000000840 +~~END~~ + + +-- M coordinate (measure) +SELECT geometry::Parse('POINT M(1 2 4)'); +go +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: parse error - invalid geometry)~~ + + +-- M coordinate (measure) +SELECT geometry::Parse('POLYGON M((0 0 0, 0 10 0, 10 10 0, 10 0 0, 0 0 0))'); +go +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: parse error - invalid geometry)~~ + + +-- geography with XYZM +SELECT geography::Parse('POINT(1 2 3 4)'); +go +~~START~~ +geography +E6100000010F0000000000000040000000000000F03F00000000000008400000000000001040 +~~END~~ + + +SELECT geometry::Parse('LINESTRING Z(0 0 0, 1 1 1, 2 2 2)'); +go +~~START~~ +geometry +0000000001050300000000000000000000000000000000000000000000000000F03F000000000000F03F000000000000004000000000000000400000000000000000000000000000F03F000000000000004001000000010000000001000000FFFFFFFF0000000002 +~~END~~ + + +SELECT geography::Parse('LINESTRING Z(0 0 0, 1 1 1)'); +go +~~START~~ +geography +E6100000011500000000000000000000000000000000000000000000F03F000000000000F03F0000000000000000000000000000F03F +~~END~~ + + +SELECT geography::Parse('POINT Z(1 2 3)'); +go +~~START~~ +geography +E6100000010D0000000000000040000000000000F03F0000000000000840 +~~END~~ + + +SELECT geography::Parse('LINESTRING Z(0 0 0, 1 1 1)'); +go +~~START~~ +geography +E6100000011500000000000000000000000000000000000000000000F03F000000000000F03F0000000000000000000000000000F03F +~~END~~ + + +SELECT geography::Parse('POLYGON Z((0 0 0, 0 1 0, 1 1 0, 1 0 0, 0 0 0))'); +go +~~START~~ +geography +E610000001010500000000000000000000000000000000000000000000000000F03F0000000000000000000000000000F03F000000000000F03F0000000000000000000000000000F03F000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000001000000020000000001000000FFFFFFFF0000000003 +~~END~~ + + +SELECT geography::Parse('point z(1 2 3)'); +go +~~START~~ +geography +E6100000010D0000000000000040000000000000F03F0000000000000840 +~~END~~ + + +SELECT geography::Parse('POINT ZM(1 2 3 4)'); +go +~~START~~ +geography +E6100000010F0000000000000040000000000000F03F00000000000008400000000000001040 +~~END~~ + + +SELECT geography::Parse('LINESTRING ZM(0 0 0 0, 1 1 1 1)'); +go +~~START~~ +geography +E6100000011700000000000000000000000000000000000000000000F03F000000000000F03F0000000000000000000000000000F03F0000000000000000000000000000F03F +~~END~~ + + +SELECT geography::Parse('point zm(1 2 3 4)'); +go +~~START~~ +geography +E6100000010F0000000000000040000000000000F03F00000000000008400000000000001040 +~~END~~ + + +SELECT geography::Parse('POINT(1 2 3 4)'); +go +~~START~~ +geography +E6100000010F0000000000000040000000000000F03F00000000000008400000000000001040 +~~END~~ + + +SELECT geography::Parse('LINESTRING(0 0, 1 1)'); +go +~~START~~ +geography +E6100000011400000000000000000000000000000000000000000000F03F000000000000F03F +~~END~~ + + +SELECT geography::Parse('POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))'); +go +~~START~~ +geography +E610000001000500000000000000000000000000000000000000000000000000F03F0000000000000000000000000000F03F000000000000F03F0000000000000000000000000000F03F0000000000000000000000000000000001000000020000000001000000FFFFFFFF0000000003 +~~END~~ + + +SELECT geography::Parse('POINT M(1 2 4)'); +go +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: parse error - invalid geometry)~~ + + +SELECT geography::Parse('LINESTRING M(0 0 0, 1 1 1)'); +go +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: parse error - invalid geometry)~~ + + +SELECT geography::Parse('POLYGON M((0 0 0, 0 1 0, 1 1 0, 1 0 0, 0 0 0))'); +go +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: parse error - invalid geometry)~~ + + +SELECT geography::Parse('point m(1 2 4)'); +go +~~ERROR (Code: 33557097)~~ + +~~ERROR (Message: parse error - invalid geometry)~~ + + +SELECT geography::Parse('POINT(-122.349 47.651)'); +go +~~START~~ +geography +E6100000010C17D9CEF753D347407593180456965EC0 +~~END~~ + + + +--STGeometryType() USE TestGeospatialMethods3_DB; go diff --git a/test/JDBC/input/datatypes/Test-spatial-functions-3-vu-cleanup.txt b/test/JDBC/input/datatypes/Test-spatial-functions-3-vu-cleanup.txt index 0f0f1f9ac44..56f1c67de89 100644 --- a/test/JDBC/input/datatypes/Test-spatial-functions-3-vu-cleanup.txt +++ b/test/JDBC/input/datatypes/Test-spatial-functions-3-vu-cleanup.txt @@ -1,3 +1,21 @@ +USE TestGeospatialParse_DB + +DROP TABLE TestGeospatialParse_GeometryTable3 + +DROP TABLE TestGeospatialParse_GeographyTable3 + +USE MASTER + +DROP VIEW TestGeospatialParse_ParseGeomView3 + +DROP VIEW TestGeospatialParse_ParseGeogView3 + +DROP TABLE TestGeospatialParse_GeomTemp3 + +DROP TABLE TestGeospatialParse_GeogTemp3 + +DROP DATABASE TestGeospatialParse_DB + USE TestGeospatialMethods3_DB; DROP VIEW TestGeospatialMethods3_STGeometryType_GEOM_View_db; @@ -14,4 +32,5 @@ DROP VIEW TestGeospatialMethods3_STGeometryType_GEOG_View_Temp; DROP TABLE TestGeospatialMethods3_STGeometryType_GEOM_Temp; DROP TABLE TestGeospatialMethods3_STGeometryType_GEOG_Temp; -DROP DATABASE TestGeospatialMethods3_DB; \ No newline at end of file +DROP DATABASE TestGeospatialMethods3_DB; + diff --git a/test/JDBC/input/datatypes/Test-spatial-functions-3-vu-prepare.txt b/test/JDBC/input/datatypes/Test-spatial-functions-3-vu-prepare.txt index f96adec8698..c567213b767 100644 --- a/test/JDBC/input/datatypes/Test-spatial-functions-3-vu-prepare.txt +++ b/test/JDBC/input/datatypes/Test-spatial-functions-3-vu-prepare.txt @@ -1,3 +1,58 @@ +CREATE DATABASE TestGeospatialParse_DB; + +USE TestGeospatialParse_DB; + +CREATE TABLE TestGeospatialParse_GeometryTable3 ( ID INT PRIMARY KEY, GeomColumn geometry ); +INSERT INTO TestGeospatialParse_GeometryTable3 (ID, GeomColumn) VALUES (1, geometry::Parse('POINT(3.0 4.0)')); +INSERT INTO TestGeospatialParse_GeometryTable3 (ID, GeomColumn) VALUES (2, geometry::Parse('LINESTRING(0 0, 1 1, 2 2)')); +INSERT INTO TestGeospatialParse_GeometryTable3 (ID, GeomColumn) VALUES (3, geometry::Parse('POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))')); +INSERT INTO TestGeospatialParse_GeometryTable3 (ID, GeomColumn) VALUES (4, geometry::Parse('POINT(1.0 2.0)')); +INSERT INTO TestGeospatialParse_GeometryTable3 (ID, GeomColumn) VALUES (5, geometry::Parse('LINESTRING(0 0, 5 5)')); +INSERT INTO TestGeospatialParse_GeometryTable3 (ID, GeomColumn) VALUES (7, geometry::Parse('LINESTRING(0 0 0, 1 1 1, 2 2 2)')); +INSERT INTO TestGeospatialParse_GeometryTable3 (ID, GeomColumn) VALUES (8, geometry::Parse('LINESTRING M(0 0 0, 1 1 1, 2 2 2)')); +INSERT INTO TestGeospatialParse_GeometryTable3 (ID, GeomColumn) VALUES (9, geometry::Parse('LINESTRING(0 0 0 0, 1 1 1 1, 2 2 2 2)')); +INSERT INTO TestGeospatialParse_GeometryTable3 (ID, GeomColumn) VALUES (10, geometry::Parse('POINT(1 2 3)')); +INSERT INTO TestGeospatialParse_GeometryTable3 (ID, GeomColumn) VALUES (11, geometry::Parse('POINT M(1 2 3)')); +INSERT INTO TestGeospatialParse_GeometryTable3 (ID, GeomColumn) VALUES (12, geometry::Parse('POINT(1 2 3 4)')); +INSERT INTO TestGeospatialParse_GeometryTable3 (ID, GeomColumn) VALUES (13, geometry::Parse('POLYGON((0 0 0, 0 1 1, 1 1 1, 1 0 0, 0 0 0))')); +INSERT INTO TestGeospatialParse_GeometryTable3 (ID, GeomColumn) VALUES (14, geometry::Parse('POLYGON M((0 0 0, 0 1 1, 1 1 1, 1 0 0, 0 0 0))')); +INSERT INTO TestGeospatialParse_GeometryTable3 (ID, GeomColumn) VALUES (15, geometry::Parse('POLYGON((0 0 0 0, 0 1 1 1, 1 1 1 1, 1 0 0 0, 0 0 0 0))')); + +CREATE TABLE TestGeospatialParse_GeographyTable3 ( ID INT PRIMARY KEY, GeogColumn geography ); +INSERT INTO TestGeospatialParse_GeographyTable3 (ID, GeogColumn) VALUES (1, geography::Parse('POINT(3.0 4.0)')); +INSERT INTO TestGeospatialParse_GeographyTable3 (ID, GeogColumn) VALUES (2, geography::Parse('LINESTRING(0 0, 1 1, 2 2)')); +INSERT INTO TestGeospatialParse_GeographyTable3 (ID, GeogColumn) VALUES (3, geography::Parse('POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))')); +INSERT INTO TestGeospatialParse_GeographyTable3 (ID, GeogColumn) VALUES (4, geography::Parse('POINT(1.0 2.0)')); +INSERT INTO TestGeospatialParse_GeographyTable3 (ID, GeogColumn) VALUES (5, geography::Parse('LINESTRING(0 0, 5 5)')); +INSERT INTO TestGeospatialParse_GeographyTable3 (ID, GeogColumn) VALUES (6, geography::Parse('LINESTRING(0 0 0, 1 1 1, 2 2 2)')); +INSERT INTO TestGeospatialParse_GeographyTable3 (ID, GeogColumn) VALUES (7, geography::Parse('LINESTRING M(0 0 0, 1 1 1, 2 2 2)')); +INSERT INTO TestGeospatialParse_GeographyTable3 (ID, GeogColumn) VALUES (8, geography::Parse('LINESTRING(0 0 0 0, 1 1 1 1, 2 2 2 2)')); +INSERT INTO TestGeospatialParse_GeographyTable3 (ID, GeogColumn) VALUES (9, geography::Parse('POINT(1 2 3)')); +INSERT INTO TestGeospatialParse_GeographyTable3 (ID, GeogColumn) VALUES (10, geography::Parse('POINT M(1 2 3)')); +INSERT INTO TestGeospatialParse_GeographyTable3 (ID, GeogColumn) VALUES (11, geography::Parse('POINT(1 2 3 4)')); +INSERT INTO TestGeospatialParse_GeographyTable3 (ID, GeogColumn) VALUES (12, geography::Parse('POLYGON((0 0 0, 0 1 1, 1 1 1, 1 0 0, 0 0 0))')); +INSERT INTO TestGeospatialParse_GeographyTable3 (ID, GeogColumn) VALUES (13, geography::Parse('POLYGON M((0 0 0, 0 1 1, 1 1 1, 1 0 0, 0 0 0))')); +INSERT INTO TestGeospatialParse_GeographyTable3 (ID, GeogColumn) VALUES (14, geography::Parse('POLYGON((0 0 0 0, 0 1 1 1, 1 1 1 1, 1 0 0 0, 0 0 0 0))')); + + +USE MASTER + +CREATE TABLE TestGeospatialParse_GeomTemp3 ( ID INT PRIMARY KEY, GeomColumn geometry ); +INSERT INTO TestGeospatialParse_GeomTemp3 (ID, GeomColumn) VALUES (1, geometry::Parse('POINT(3.0 4.0)')); +INSERT INTO TestGeospatialParse_GeomTemp3 (ID, GeomColumn) VALUES (2, geometry::Parse('LINESTRING(0 0, 1 1)')); +INSERT INTO TestGeospatialParse_GeomTemp3 (ID, GeomColumn) VALUES (3, geometry::Parse('POLYGON((0 0, 0 2, 2 2, 2 0, 0 0))')); +INSERT INTO TestGeospatialParse_GeomTemp3 (ID, GeomColumn) VALUES (4, geometry::Parse('POINT(47.65100 -22.34900)')); + +CREATE TABLE TestGeospatialParse_GeogTemp3 ( ID INT PRIMARY KEY, GeogColumn geography ); +INSERT INTO TestGeospatialParse_GeogTemp3 (ID, GeogColumn) VALUES (1, geography::Parse('POINT(3.0 4.0)')); +INSERT INTO TestGeospatialParse_GeogTemp3 (ID, GeogColumn) VALUES (2, geography::Parse('LINESTRING(0 0, 1 1)')); +INSERT INTO TestGeospatialParse_GeogTemp3 (ID, GeogColumn) VALUES (3, geography::Parse('POLYGON((0 0, 0 2, 2 2, 2 0, 0 0))')); +INSERT INTO TestGeospatialParse_GeogTemp3 (ID, GeogColumn) VALUES (4, geography::Parse('POINT(47.65100 -22.34900)')); + +CREATE VIEW TestGeospatialParse_ParseGeomView3 AS SELECT GeomColumn.STAsText() AS ParsedGeom FROM TestGeospatialParse_GeomTemp3 ORDER BY GeomColumn.STX; + +CREATE VIEW TestGeospatialParse_ParseGeogView3 AS SELECT GeogColumn.STAsText() AS ParsedGeog FROM TestGeospatialParse_GeogTemp3 ORDER BY GeogColumn.Lat; + CREATE DATABASE TestGeospatialMethods3_DB; USE TestGeospatialMethods3_DB; diff --git a/test/JDBC/input/datatypes/Test-spatial-functions-3-vu-verify.sql b/test/JDBC/input/datatypes/Test-spatial-functions-3-vu-verify.sql index 2c755d05d7b..26335e88cbf 100644 --- a/test/JDBC/input/datatypes/Test-spatial-functions-3-vu-verify.sql +++ b/test/JDBC/input/datatypes/Test-spatial-functions-3-vu-verify.sql @@ -1,3 +1,433 @@ +--Parse functions test + +-- geometry::Parse with POINT +DECLARE @geomText NVARCHAR(MAX); +SET @geomText = 'POINT(1.0 2.0)'; +SELECT geometry::Parse(@geomText).STAsText() AS ParsedGeometry; +go + +-- geometry::Parse with LINESTRING +DECLARE @geomText NVARCHAR(MAX); +SET @geomText = 'LINESTRING(0 0, 1 1, 2 2)'; +SELECT geometry::Parse(@geomText).STAsText() AS ParsedGeometry; +go + +DECLARE @geomText NVARCHAR(MAX); +SET @geomText = 'POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))'; +SELECT geometry::Parse(@geomText).STAsText() AS ParsedGeometry; +go + +DECLARE @geogText NVARCHAR(MAX); +SET @geogText = 'POINT(1.0 2.0)'; +SELECT geography::Parse(@geogText).STAsText() AS ParsedGeography; +go + +DECLARE @geogText NVARCHAR(MAX); +SET @geogText = 'LINESTRING(0 0, 1 1, 2 2)'; +SELECT geography::Parse(@geogText).STAsText() AS ParsedGeography; +go + +DECLARE @geogText NVARCHAR(MAX); +SET @geogText = 'POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))'; +SELECT geography::Parse(@geogText).STAsText() AS ParsedGeography; +go + +-- Parse with real-world coordinates +DECLARE @geomText NVARCHAR(MAX); +SET @geomText = 'POINT(-122.34900 47.65100)'; +SELECT geometry::Parse(@geomText).STAsText() AS ParsedGeometry; +go + +DECLARE @geogText NVARCHAR(MAX); +SET @geogText = 'POINT(-122.34900 47.65100)'; +SELECT geography::Parse(@geogText).STAsText() AS ParsedGeography; +go + +-- Parse from table column +SELECT ID, geometry::Parse(GeomColumn.STAsText()).STAsText() AS ParsedGeom FROM TestGeospatialParse_GeomTemp3 ORDER BY ID; +go + +SELECT ID, geography::Parse(GeogColumn.STAsText()).STAsText() AS ParsedGeog FROM TestGeospatialParse_GeogTemp ORDER BY ID; +go + +-- Parse with STEquals in WHERE clause +DECLARE @searchText NVARCHAR(MAX); +SET @searchText = 'POINT(3.0 4.0)'; +SELECT ID FROM TestGeospatialParse_GeomTemp3 WHERE geometry::Parse(@searchText).STEquals(GeomColumn) = 1 ORDER BY ID; +go + +DECLARE @searchText NVARCHAR(MAX); +SET @searchText = 'POINT(3.0 4.0)'; +SELECT ID FROM TestGeospatialParse_GeogTemp WHERE geography::Parse(@searchText).STEquals(GeogColumn) = 1 ORDER BY ID; +go + +-- Parse with JOIN and STIntersects +DECLARE @refText NVARCHAR(MAX); +SET @refText = 'POINT(3.0 4.0)'; +SELECT g1.ID, g2.ID FROM TestGeospatialParse_GeomTemp3 g1 +JOIN TestGeospatialParse_GeomTemp3 g2 ON geometry::Parse(@refText).STIntersects(g1.GeomColumn) = 1 +ORDER BY g1.ID, g2.ID; +go + +-- Parse with CASE and STDistance +DECLARE @testText NVARCHAR(MAX); +SET @testText = 'POINT(1.0 2.0)'; +SELECT ID, +CASE WHEN geometry::Parse(@testText).STDistance(GeomColumn) < 5.0 THEN 'Near' ELSE 'Far' END AS Proximity +FROM TestGeospatialParse_GeomTemp3 ORDER BY ID; +go + +-- Parse with CTE +DECLARE @refText NVARCHAR(MAX); +SET @refText = 'POINT(3.0 4.0)'; +WITH ParseCTE AS ( + SELECT ID, geometry::Parse(@refText).STDistance(GeomColumn) AS Distance + FROM TestGeospatialParse_GeomTemp3 +) +SELECT * FROM ParseCTE WHERE Distance < 10.0 ORDER BY Distance; +go + +-- Parse with cross-database query (geometry) +DECLARE @refText NVARCHAR(MAX); +SET @refText = 'POINT(3.0 4.0)'; +SELECT ID, geometry::Parse(@refText).STDistance(GeomColumn) AS Distance +FROM TestGeospatialParse_DB.dbo.TestGeospatialParse_GeometryTable3ORDER BY ID; +go + +-- Parse with cross-database query (geography) +DECLARE @refText NVARCHAR(MAX); +SET @refText = 'POINT(3.0 4.0)'; +SELECT ID, geography::Parse(@refText).STDistance(GeogColumn) AS Distance +FROM TestGeospatialParse_DB.dbo.TestGeospatialParse_GeographyTable3 ORDER BY ID; +go + +-- NULL variable input (geometry) +DECLARE @nullText NVARCHAR(MAX); +SET @nullText = NULL; +SELECT geometry::Parse(@nullText) AS ParsedGeometry; +go + +-- NULL variable input (geography) +DECLARE @nullText NVARCHAR(MAX); +SET @nullText = NULL; +SELECT geography::Parse(@nullText) AS ParsedGeography; +go + +-- 'NULL' string literal - should error +DECLARE @nullString NVARCHAR(MAX); +SET @nullString = 'NULL'; +SELECT geometry::Parse(@nullString) AS ParsedGeometry; +go + +DECLARE @nullString NVARCHAR(MAX); +SET @nullString = 'NULL'; +SELECT geography::Parse(@nullString) AS ParsedGeography; +go + +-- POINT EMPTY +DECLARE @emptyPoint NVARCHAR(MAX); +SET @emptyPoint = 'POINT EMPTY'; +SELECT geometry::Parse(@emptyPoint).STAsText() AS ParsedGeometry; +go + +DECLARE @emptyPoint NVARCHAR(MAX); +SET @emptyPoint = 'POINT EMPTY'; +SELECT geography::Parse(@emptyPoint).STAsText() AS ParsedGeography; +go + +-- Whitespace handling +DECLARE @geomText NVARCHAR(MAX); +SET @geomText = ' POINT ( 1.0 2.0 ) '; +SELECT geometry::Parse(@geomText).STAsText() AS ParsedGeometry; +go + +DECLARE @geogText NVARCHAR(MAX); +SET @geogText = ' POINT ( 1.0 2.0 ) '; +SELECT geography::Parse(@geogText).STAsText() AS ParsedGeography; +go + +-- Parse with different case +DECLARE @lowerText NVARCHAR(MAX); +SET @lowerText = 'point(1.0 2.0)'; +SELECT geometry::Parse(@lowerText).STAsText() AS ParsedGeometry; +go + +DECLARE @upperText NVARCHAR(MAX); +SET @upperText = 'POINT(1.0 2.0)'; +SELECT geography::Parse(@upperText).STAsText() AS ParsedGeography; +go + +-- Nested function calls +SELECT ID, geometry::Parse(GeomColumn.STAsText()).STDimension() AS Dimension +FROM TestGeospatialParse_GeomTemp3 ORDER BY ID; +go + +SELECT ID, geography::Parse(GeogColumn.STAsText()).STDimension() AS Dimension +FROM TestGeospatialParse_GeogTemp3 ORDER BY ID; +go + +-- Parse with function results +SELECT geometry::Parse(geometry::Point(1.0, 2.0, 4326).STAsText()).STAsText() AS ParsedFromFunction; +go + +SELECT geography::Parse(geography::Point(1.0, 2.0, 4326).STAsText()).STAsText() AS ParsedFromFunction; +go + +-- Direct NULL input +SELECT geometry::Parse(NULL); +go + +SELECT geography::Parse(NULL); +go + +-- 'NULL' string literal +SELECT geometry::Parse('NULL'); +go + +SELECT geography::Parse('NULL'); +go + +SELECT geometry::Parse(' NULL '); +go + +-- XYZM coordinates (4D) +SELECT geometry::Parse('POINT(1 2 3 4)').STAsText(); +go + +SELECT geography::Parse('POINT(1 2 3 4)').STAsText(); +go + +-- XYZ coordinates (3D) +SELECT geometry::Parse('POINT(1 2 3)').STAsText(); +go + +SELECT geography::Parse('POINT(1 2 3)').STAsText(); +go + +-- Invalid: single coordinate - should error +SELECT geometry::Parse('POINT(1)'); +go + +SELECT geography::Parse('POINT(1)').STAsText(); +go + +-- Invalid polygon: insufficient points - should error +SELECT geometry::Parse('POLYGON((0 0, 1 1))'); +go + +SELECT geography::Parse('POLYGON((0 0, 1 1))'); +go + +-- Invalid WKT string - should error +SELECT geometry::Parse('hello'); +go + +SELECT geography::Parse('hello'); +go + +-- Large coordinate values +SELECT geometry::Parse('POINT(999999999 999999999)').STAsText(); +go + +SELECT geography::Parse('POINT(999999999 999999999)').STAsText(); +go + +-- Boundary coordinate values +SELECT geometry::Parse('POINT(-180 -90)').STAsText(); +go + +SELECT geography::Parse('POINT(-180 -90)').STAsText(); +go + +-- LINESTRING EMPTY +SELECT geometry::Parse('LINESTRING EMPTY').STAsText(); +go + +-- Case insensitivity for LINESTRING +SELECT geometry::Parse('lineString(0 0, 1 1)').STAsText(); +go + +SELECT geography::Parse('LINESTRING EMPTY').STAsText(); +go + +SELECT geography::Parse('lineString(0 0, 1 1)').STAsText(); +go + +-- UNION with Parse +SELECT geometry::Parse('POINT(1 2)').STAsText() AS geom +UNION +SELECT geometry::Parse('POINT(3 4)').STAsText() +UNION +SELECT geometry::Parse('NULL').STAsText(); +ORDER BY geom DESC; +go + +-- GROUP BY with spatial type +SELECT GeomColumn.STGeometryType() AS GeomType, + COUNT(*) AS Count +FROM TestGeospatialParse_GeomTemp3 +GROUP BY GeomColumn.STGeometryType() +ORDER BY GeomType; +go + +-- Window function with Parse +SELECT ID, + geometry::Parse('POINT(0 0)').STDistance(GeomColumn) AS Distance, + ROW_NUMBER() OVER (ORDER BY geometry::Parse('POINT(0 0)').STDistance(GeomColumn)) AS RowNum +FROM TestGeospatialParse_GeomTemp3; +go + +-- CAST result to VARCHAR +SELECT CAST(geometry::Parse('POINT(1 2)').STAsText() AS VARCHAR(100)) AS Result; +go + +-- Empty string - should error +SELECT geometry::Parse(''); +go + +-- hierarchyid::Parse +select hierarchyid::Parse('/1/3/2/'); +go + +-- hierarchyid::Parse with variable +DECLARE @node hierarchyid; +SET @node = hierarchyid::Parse('/1/3/2/'); +SELECT @node AS NodeValue; +go + +-- CTE with multiple geometry types +WITH ParseCTE AS ( + SELECT 1 AS ID, geometry::Parse('POINT(1 2)').STAsText() AS GeomText + UNION ALL + SELECT 2, geometry::Parse('LINESTRING(0 0, 1 1)').STAsText() + UNION ALL + SELECT 3, geometry::Parse('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))').STAsText() +) +SELECT ID, GeomText FROM ParseCTE ORDER BY ID; +go + +-- CTE with geography types +WITH GeogCTE AS ( + SELECT 1 AS ID, geography::Parse('POINT(-122.349 47.651)').STAsText() AS GeogText + UNION ALL + SELECT 2, geography::Parse('LINESTRING(-122.36 47.65, -122.34 47.66)').STAsText() +) +SELECT ID, GeogText FROM GeogCTE ORDER BY ID; +go + +-- Window function with STDimension +SELECT *, ROW_NUMBER() OVER (ORDER BY Dimension) AS RowNum FROM ( + SELECT 1 AS ID, geometry::Parse('POINT(1 2)').STDimension() AS Dimension + UNION ALL + SELECT 2, geometry::Parse('LINESTRING(0 0, 1 1)').STDimension() + UNION ALL + SELECT 3, geometry::Parse('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))').STDimension() +) AS Results; +go + +-- Schema-qualified Parse +SELECT sys.geometry::Parse('POINT(1 2)').STAsText() AS Result; +go + +-- Invalid geometry type - should error +SELECT geometry::Parse('INVALID(1 2)'); +go + +-- GROUP BY with STDimension +SELECT Dimension, COUNT(*) AS Count FROM ( + SELECT geometry::Parse('POINT(1 2)').STDimension() AS Dimension + UNION ALL + SELECT geometry::Parse('POINT(3 4)').STDimension() + UNION ALL + SELECT geometry::Parse('LINESTRING(0 0, 1 1)').STDimension() + UNION ALL + SELECT geometry::Parse('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))').STDimension() +) AS Results +GROUP BY Dimension +ORDER BY Dimension; +go + +-- Parse returning geometry object (no STAsText) +SELECT geometry::Parse('POINT(1 2 3 4)'); +go + +SELECT geometry::Parse('LINESTRING(0 0, 1 1)'); +go + +SELECT geometry::Parse('POLYGON((0 0, 0 10, 10 10, 10 0, 0 0))'); +go + +SELECT geometry::Parse('POINT(999999999 999999999)'); +go + +-- Z coordinate (elevation) +SELECT geometry::Parse('POINT Z(1 2 3)'); +go + +-- M coordinate (measure) +SELECT geometry::Parse('POINT M(1 2 4)'); +go + +-- M coordinate (measure) +SELECT geometry::Parse('POLYGON M((0 0 0, 0 10 0, 10 10 0, 10 0 0, 0 0 0))'); +go + +-- geography with XYZM +SELECT geography::Parse('POINT(1 2 3 4)'); +go + +SELECT geometry::Parse('LINESTRING Z(0 0 0, 1 1 1, 2 2 2)'); +go + +SELECT geography::Parse('LINESTRING Z(0 0 0, 1 1 1)'); +go + +SELECT geography::Parse('POINT Z(1 2 3)'); +go + +SELECT geography::Parse('LINESTRING Z(0 0 0, 1 1 1)'); +go + +SELECT geography::Parse('POLYGON Z((0 0 0, 0 1 0, 1 1 0, 1 0 0, 0 0 0))'); +go + +SELECT geography::Parse('point z(1 2 3)'); +go + +SELECT geography::Parse('POINT ZM(1 2 3 4)'); +go + +SELECT geography::Parse('LINESTRING ZM(0 0 0 0, 1 1 1 1)'); +go + +SELECT geography::Parse('point zm(1 2 3 4)'); +go + +SELECT geography::Parse('POINT(1 2 3 4)'); +go + +SELECT geography::Parse('LINESTRING(0 0, 1 1)'); +go + +SELECT geography::Parse('POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))'); +go + +SELECT geography::Parse('POINT M(1 2 4)'); +go + +SELECT geography::Parse('LINESTRING M(0 0 0, 1 1 1)'); +go + +SELECT geography::Parse('POLYGON M((0 0 0, 0 1 0, 1 1 0, 1 0 0, 0 0 0))'); +go + +SELECT geography::Parse('point m(1 2 4)'); +go + +SELECT geography::Parse('POINT(-122.349 47.651)'); +go + +--STGeometryType() USE TestGeospatialMethods3_DB; go @@ -483,4 +913,4 @@ go -- SRID 999999 SELECT geometry::STGeomFromText('POINT(1 2)', 999999).STGeometryType(); -go \ No newline at end of file +go diff --git a/test/JDBC/singledb_jdbc_schedule b/test/JDBC/singledb_jdbc_schedule index 77e2d8e7ce9..5b6dec42db0 100644 --- a/test/JDBC/singledb_jdbc_schedule +++ b/test/JDBC/singledb_jdbc_schedule @@ -29,3 +29,6 @@ ignore#!#user_token-dep-vu-verify ignore#!#proc_ownership_chaining-vu-prepare ignore#!#proc_ownership_chaining-vu-verify ignore#!#proc_ownership_chaining-vu-cleanup +ignore#!#Test-spatial-functions-3-vu-prepare +ignore#!#Test-spatial-functions-3-vu-verify +ignore#!#Test-spatial-functions-3-vu-cleanup diff --git a/test/python/expected/upgrade_validation/expected_dependency.out b/test/python/expected/upgrade_validation/expected_dependency.out index 17ee8459b0b..472bb29b751 100644 --- a/test/python/expected/upgrade_validation/expected_dependency.out +++ b/test/python/expected/upgrade_validation/expected_dependency.out @@ -454,6 +454,7 @@ Function sys.geography(sys.bbf_varbinary) Function sys.geography(sys.bpchar) Function sys.geography(sys.geography,integer,boolean) Function sys.geography(text,integer,boolean) +Function sys.geography__parse(sys.nvarchar) Function sys.geography__stflipcoordinates(sys.geography) Function sys.geographyastextbp_helper(sys.geography,integer,boolean) Function sys.geographyastextvar_helper(sys.geography) @@ -465,6 +466,7 @@ Function sys.geometry(sys.bbf_varbinary) Function sys.geometry(sys.bpchar) Function sys.geometry(sys.geometry,integer,boolean) Function sys.geometry(text,integer,boolean) +Function sys.geometry__parse(sys.nvarchar) Function sys.geometry__point(double precision,double precision,integer) Function sys.geomfromtext_helper(text,integer) Function sys.geompoint_helper(double precision,double precision,integer)