From d8832c0f339702b6c2006589740e88528f94d4c2 Mon Sep 17 00:00:00 2001 From: Gopalverma062 Date: Sun, 1 Mar 2026 11:55:17 +0530 Subject: [PATCH] Implemetation of parse geography and geometry datatype (#4518) Implemented Parse function support for GeoSpatial TSQL data types that was previously unsupported in Babelfish. The Parse function has been added for both geometry and geography data types. Changes include: Implemented geometry::Parse() and geography::Parse() functions by utilizing PostGIS parsing capabilities with necessary adjustments to ensure TSQL compatibility. Added Parse function definitions to the TSQL parser to recognize these new static methods. Ensured proper syntax handling for Parse function, including NVARCHAR parameter types and return values. Examples: DECLARE @geomText NVARCHAR(MAX); SET @geomText = 'POINT(1.0 2.0)'; SELECT geometry::Parse(@geomText).STAsText() AS ParsedGeometry; GO ParsedGeometry -------------- POINT(1 2) DECLARE @geogText NVARCHAR(MAX); SET @geogText = 'LINESTRING(0 0, 1 1, 2 2)'; SELECT geography::Parse(@geogText).STAsText() AS ParsedGeography; GO ParsedGeography --------------- LINESTRING(0 0,1 1,2 2) Task: BABEL-6310 Signed-off by: Gopalgv gopalgv@amazon.com --- contrib/babelfishpg_common/sql/geography.sql | 13 + contrib/babelfishpg_common/sql/geometry.sql | 13 + .../upgrades/spatial_types--6.0.0--6.1.0.sql | 30 +- contrib/babelfishpg_tsql/antlr/TSqlParser.g4 | 2 +- .../Test-spatial-functions-3-vu-cleanup.out | 19 + .../Test-spatial-functions-3-vu-prepare.out | 139 +++ .../Test-spatial-functions-3-vu-verify.out | 907 ++++++++++++++++++ .../Test-spatial-functions-3-vu-cleanup.txt | 21 +- .../Test-spatial-functions-3-vu-prepare.txt | 55 ++ .../Test-spatial-functions-3-vu-verify.sql | 432 ++++++++- test/JDBC/singledb_jdbc_schedule | 3 + .../expected_dependency.out | 2 + 12 files changed, 1631 insertions(+), 5 deletions(-) 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)