server/mssql: better support for spatial data operators (fixes #789)

GitOrigin-RevId: b3d59a5c351e747370b82d086fe13d5d8d178d05
This commit is contained in:
Abby Sassel 2021-03-24 13:43:40 +00:00 committed by hasura-bot
parent ce37e7b1f1
commit 9f0bcabf23
22 changed files with 619 additions and 50 deletions

View File

@ -3,12 +3,51 @@
## Next release
(Add entries here in the order of: server, console, cli, docs, others)
### Support geometry and geography spatial data comparison operators in MS SQL Server
Comparison operators on spatial data types, geometry and geography, are now supported in MS SQL Server. The following operators are supported:
- STEquals
- STIntersects
- STTouches
- STOverlaps
- STCrosses
- STWithin
- STContains
**Example query:** Select values equal to a given geography instance
```
query {
spatial_types_geog(
where: {
point: { _st_equals: "POINT(3 4)" }
}
) {
point
}
}
```
**Example query:** Select values that spatially contain a given geometry instance
```
query {
spatial_types_geom(
where: {
compoundcurve: { _st_contains: "POINT(0.5 0)" }
}
) {
compoundcurve
}
}
```
## v2.0.0-alpha.6
- server: fix action output type schema generation (fix #6631)
- server/mssql: `mssql_add_source` can now take connection strings from environment variables
- server: support `IN`, `NIN`, `LIKE` and `NLIKE` operators in MSSQL
- server: support `IN`, `NIN`, `LIKE` and `NLIKE` operators in MS SQL Server
- server: remove the restriction of supporting only base type function arguments. The type of an argument with a table type is now `<tablename>_scalar` to avoid conflicts with the object type `<tablename>`.
- server: fix inherited_roles issue when some of the underlying roles don't have permissions configured (fixes #6672)
- server: fix action custom types failing to parse when mutually recursive

View File

@ -39,37 +39,53 @@ parseBoolExpOperations rhsParser _fields columnInfo value =
parseOperation :: ColumnType 'MSSQL -> (Text, J.Value) -> m (OpExpG 'MSSQL v)
parseOperation columnType (opStr, val) = withPathK opStr $
case opStr of
"_eq" -> parseEq
"$eq" -> parseEq
"_eq" -> parseEq
"$eq" -> parseEq
"_neq" -> parseNeq
"$neq" -> parseNeq
"_neq" -> parseNeq
"$neq" -> parseNeq
"$in" -> parseIn
"_in" -> parseIn
"$in" -> parseIn
"_in" -> parseIn
"$nin" -> parseNin
"_nin" -> parseNin
"$nin" -> parseNin
"_nin" -> parseNin
"_gt" -> parseGt
"$gt" -> parseGt
"_gt" -> parseGt
"$gt" -> parseGt
"_lt" -> parseLt
"$lt" -> parseLt
"_lt" -> parseLt
"$lt" -> parseLt
"_gte" -> parseGte
"$gte" -> parseGte
"_gte" -> parseGte
"$gte" -> parseGte
"_lte" -> parseLte
"$lte" -> parseLte
"_lte" -> parseLte
"$lte" -> parseLte
"$like" -> parseLike
"_like" -> parseLike
"$like" -> parseLike
"_like" -> parseLike
"$nlike" -> parseNlike
"_nlike" -> parseNlike
"$nlike" -> parseNlike
"_nlike" -> parseNlike
x -> throw400 UnexpectedPayload $ "Unknown operator : " <> x
"_st_contains" -> parseGeometryOrGeographyOp ASTContains
"$st_contains" -> parseGeometryOrGeographyOp ASTContains
"_st_equals" -> parseGeometryOrGeographyOp ASTEquals
"$st_equals" -> parseGeometryOrGeographyOp ASTEquals
"_st_intersects" -> parseGeometryOrGeographyOp ASTIntersects
"$st_intersects" -> parseGeometryOrGeographyOp ASTIntersects
"_st_overlaps" -> parseGeometryOrGeographyOp ASTOverlaps
"$st_overlaps" -> parseGeometryOrGeographyOp ASTOverlaps
"_st_within" -> parseGeometryOrGeographyOp ASTWithin
"$st_within" -> parseGeometryOrGeographyOp ASTWithin
"_st_crosses" -> parseGeometryOp ASTCrosses
"$st_crosses" -> parseGeometryOp ASTCrosses
"_st_touches" -> parseGeometryOp ASTTouches
"$st_touches" -> parseGeometryOp ASTTouches
x -> throw400 UnexpectedPayload $ "Unknown operator : " <> x
where
colTy = pgiType columnInfo
@ -88,6 +104,12 @@ parseBoolExpOperations rhsParser _fields columnInfo value =
parseLike = guardType stringTypes >> ALIKE <$> parseOne
parseNlike = guardType stringTypes >> ANLIKE <$> parseOne
parseGeometryOp f =
guardType [GeometryType] >> f <$> parseOneNoSess colTy val
parseGeometryOrGeographyOp f =
guardType geoTypes >> f <$> parseOneNoSess colTy val
parseOneNoSess ty = rhsParser (CollectableTypeScalar ty)
guardType validTys = unless (isScalarColumnWhere (`elem` validTys) colTy) $
throwError $ buildMsg colTy validTys

View File

@ -818,6 +818,22 @@ fromOpExpG expression op =
IR.ANIN val -> pure (OpExpression TSQL.NIN expression val)
IR.ALIKE val -> pure (OpExpression TSQL.LIKE expression val)
IR.ANLIKE val -> pure (OpExpression TSQL.NLIKE expression val)
IR.ASTContains val -> pure (TSQL.STOpExpression TSQL.STContains expression val)
IR.ASTCrosses val -> pure (TSQL.STOpExpression TSQL.STCrosses expression val)
IR.ASTEquals val -> pure (TSQL.STOpExpression TSQL.STEquals expression val)
IR.ASTIntersects val -> pure (TSQL.STOpExpression TSQL.STIntersects expression val)
IR.ASTOverlaps val -> pure (TSQL.STOpExpression TSQL.STOverlaps expression val)
IR.ASTTouches val -> pure (TSQL.STOpExpression TSQL.STTouches expression val)
IR.ASTWithin val -> pure (TSQL.STOpExpression TSQL.STWithin expression val)
-- https://docs.microsoft.com/en-us/sql/relational-databases/hierarchical-data-sql-server
IR.AAncestor _ -> refute (pure (UnsupportedOpExpG op))
IR.AAncestorAny _ -> refute (pure (UnsupportedOpExpG op))
IR.ADescendant _ -> refute (pure (UnsupportedOpExpG op))
IR.ADescendantAny _ -> refute (pure (UnsupportedOpExpG op))
IR.AMatches _ -> refute (pure (UnsupportedOpExpG op))
IR.AMatchesAny _ -> refute (pure (UnsupportedOpExpG op))
IR.AMatchesFulltext _ -> refute (pure (UnsupportedOpExpG op))
-- No equivalent operators in SQL Server for the following
-- https://docs.microsoft.com/en-us/sql/t-sql/functions/json-functions-transact-sql
IR.AContains _val -> refute (pure (UnsupportedOpExpG op))
IR.AContainedIn _val -> refute (pure (UnsupportedOpExpG op))
@ -831,35 +847,19 @@ fromOpExpG expression op =
IR.AIREGEX _val -> refute (pure (UnsupportedOpExpG op))
IR.ANREGEX _val -> refute (pure (UnsupportedOpExpG op))
IR.ANIREGEX _val -> refute (pure (UnsupportedOpExpG op))
-- https://docs.microsoft.com/en-us/sql/relational-databases/hierarchical-data-sql-server
IR.AAncestor _ -> refute (pure (UnsupportedOpExpG op))
IR.AAncestorAny _ -> refute (pure (UnsupportedOpExpG op))
IR.ADescendant _ -> refute (pure (UnsupportedOpExpG op))
IR.ADescendantAny _ -> refute (pure (UnsupportedOpExpG op))
IR.AMatches _ -> refute (pure (UnsupportedOpExpG op))
IR.AMatchesAny _ -> refute (pure (UnsupportedOpExpG op))
IR.AMatchesFulltext _ -> refute (pure (UnsupportedOpExpG op))
-- As of March 2021, only geometry/geography casts are supported
IR.ACast _casts -> refute (pure (UnsupportedOpExpG op)) -- mkCastsExp casts
-- https://docs.microsoft.com/en-us/sql/relational-databases/spatial/spatial-data-sql-server
IR.ASTContains _val -> refute (pure (UnsupportedOpExpG op)) -- mkGeomOpBe "ST_Contains" val
IR.ASTCrosses _val -> refute (pure (UnsupportedOpExpG op)) -- mkGeomOpBe "ST_Crosses" val
IR.ASTEquals _val -> refute (pure (UnsupportedOpExpG op)) -- mkGeomOpBe "ST_Equals" val
IR.ASTIntersects _val -> refute (pure (UnsupportedOpExpG op)) -- mkGeomOpBe "ST_Intersects" val
IR.ASTOverlaps _val -> refute (pure (UnsupportedOpExpG op)) -- mkGeomOpBe "ST_Overlaps" val
IR.ASTTouches _val -> refute (pure (UnsupportedOpExpG op)) -- mkGeomOpBe "ST_Touches" val
IR.ASTWithin _val -> refute (pure (UnsupportedOpExpG op)) -- mkGeomOpBe "ST_Within" val
IR.ASTDWithinGeom {} -> refute (pure (UnsupportedOpExpG op)) -- applySQLFn "ST_DWithin" [lhs, val, r]
IR.ASTDWithinGeog {} -> refute (pure (UnsupportedOpExpG op)) -- applySQLFn "ST_DWithin" [lhs, val, r, sph]
IR.ASTIntersectsRast _val -> refute (pure (UnsupportedOpExpG op)) -- applySTIntersects [lhs, val]
IR.ASTIntersectsNbandGeom {} -> refute (pure (UnsupportedOpExpG op)) -- applySTIntersects [lhs, nband, geommin]
IR.ASTIntersectsGeomNband {} -> refute (pure (UnsupportedOpExpG op)) -- applySTIntersects [lhs, geommin, withSQLNull mNband]
IR.CEQ _rhsCol -> refute (pure (UnsupportedOpExpG op)) -- S.BECompare S.SEQ lhs $ mkQCol rhsCol
IR.CNE _rhsCol -> refute (pure (UnsupportedOpExpG op)) -- S.BECompare S.SNE lhs $ mkQCol rhsCol
IR.CGT _rhsCol -> refute (pure (UnsupportedOpExpG op)) -- S.BECompare S.SGT lhs $ mkQCol rhsCol
IR.CLT _rhsCol -> refute (pure (UnsupportedOpExpG op)) -- S.BECompare S.SLT lhs $ mkQCol rhsCol
IR.CGTE _rhsCol -> refute (pure (UnsupportedOpExpG op)) -- S.BECompare S.SGTE lhs $ mkQCol rhsCol
IR.CLTE _rhsCol -> refute (pure (UnsupportedOpExpG op)) -- S.BECompare S.SLTE lhs $ mkQCol rhsCol
IR.ACast _casts -> refute (pure (UnsupportedOpExpG op))
IR.ASTDWithinGeom {} -> refute (pure (UnsupportedOpExpG op))
IR.ASTDWithinGeog {} -> refute (pure (UnsupportedOpExpG op))
IR.ASTIntersectsRast _val -> refute (pure (UnsupportedOpExpG op))
IR.ASTIntersectsNbandGeom {} -> refute (pure (UnsupportedOpExpG op))
IR.ASTIntersectsGeomNband {} -> refute (pure (UnsupportedOpExpG op))
IR.CEQ _rhsCol -> refute (pure (UnsupportedOpExpG op))
IR.CNE _rhsCol -> refute (pure (UnsupportedOpExpG op))
IR.CGT _rhsCol -> refute (pure (UnsupportedOpExpG op))
IR.CLT _rhsCol -> refute (pure (UnsupportedOpExpG op))
IR.CGTE _rhsCol -> refute (pure (UnsupportedOpExpG op))
IR.CLTE _rhsCol -> refute (pure (UnsupportedOpExpG op))
nullableBoolEquality :: Expression -> Expression -> Expression
nullableBoolEquality x y =

View File

@ -323,6 +323,35 @@ msComparisonExps = P.memoize 'comparisonExps \columnType -> do
(Just "does the column NOT match the given pattern")
(ANLIKE . mkParameter <$> typedParser)
]
-- Ops for Geometry/Geography types
, guard (isScalarColumnWhere (`elem` MSSQL.geoTypes) columnType) *>
[ P.fieldOptional $$(G.litName "_st_contains")
(Just "does the column contain the given value")
(ASTContains . mkParameter <$> typedParser)
, P.fieldOptional $$(G.litName "_st_equals")
(Just "is the column equal to given value (directionality is ignored)")
(ASTEquals . mkParameter <$> typedParser)
, P.fieldOptional $$(G.litName "_st_intersects")
(Just "does the column spatially intersect the given value")
(ASTIntersects . mkParameter <$> typedParser)
, P.fieldOptional $$(G.litName "_st_overlaps")
(Just "does the column 'spatially overlap' (intersect but not completely contain) the given value")
(ASTOverlaps . mkParameter <$> typedParser)
, P.fieldOptional $$(G.litName "_st_within")
(Just "is the column contained in the given value")
(ASTWithin . mkParameter <$> typedParser)
]
-- Ops for Geometry types
, guard (isScalarColumnWhere (MSSQL.GeometryType ==) columnType) *>
[ P.fieldOptional $$(G.litName "_st_crosses")
(Just "does the column cross the given geometry value")
(ASTCrosses . mkParameter <$> typedParser)
, P.fieldOptional $$(G.litName "_st_touches")
(Just "does the column have at least one point in common with the given geometry value")
(ASTTouches . mkParameter <$> typedParser)
]
]
where
mkListLiteral :: [ColumnValue 'MSSQL] -> UnpreparedValue 'MSSQL

View File

@ -102,6 +102,10 @@ fromExpression =
fromExpression x <+>
") " <+> fromOp op <+> " (" <+> fromExpression y <+> ")"
ListExpression xs -> SepByPrinter ", " $ fromExpression <$> xs
STOpExpression op e str ->
"(" <+> fromExpression e <+> ")." <+>
fromString (show op) <+>
"(" <+> fromExpression str <+> ") = 1"
fromOp :: Op -> Printer
fromOp =

View File

@ -69,6 +69,7 @@ $(fmap concat $ for [ ''Where
, ''FieldName
, ''JsonPath
, ''Op
, ''SpatialOp
, ''Projection
, ''From
, ''OpenJson

View File

@ -165,6 +165,7 @@ data Expression
-- string.
| OpExpression Op Expression Expression
| ListExpression [Expression]
| STOpExpression SpatialOp Expression Expression
data JsonPath
= RootPath
@ -231,6 +232,16 @@ data Op
| NLIKE
| NIN
-- | Supported operations for spatial data types
data SpatialOp
= STEquals
| STContains
| STCrosses
| STIntersects
| STOverlaps
| STWithin
| STTouches
-- | Column name of some database table -- this differs to FieldName
-- that is used for referring to things within a query.
newtype ColumnName = ColumnName { columnNameText :: Text }
@ -376,3 +387,6 @@ stringTypes =
, WvarcharType
, WtextType
]
geoTypes :: [ScalarType]
geoTypes = [GeometryType, GeographyType]

View File

@ -0,0 +1,100 @@
type: bulk
args:
- type: mssql_run_sql
args:
source: mssql
sql: |
CREATE TABLE spatial_types_geom (
point geometry,
linestring geometry,
circularstring geometry,
compoundcurve geometry,
polygon geometry,
curvepolygon geometry,
multipoint geometry,
multilinestring geometry,
multipolygon geometry,
geometrycollection geometry
);
INSERT INTO
spatial_types_geom(
point,
linestring,
circularstring,
compoundcurve,
polygon,
curvepolygon,
multipoint,
multilinestring,
multipolygon,
geometrycollection
)
VALUES
(
geometry :: Parse('POINT(3 4 7 2.5)').MakeValid(),
geometry :: Parse('LINESTRING(1 1,2 3,4 8, -6 3)').MakeValid(),
geometry :: Parse('CIRCULARSTRING(1 1, 2 0, 2 0, 2 0, 1 1)').MakeValid(),
geometry :: Parse(
'COMPOUNDCURVE(CIRCULARSTRING(1 0, 0 1, -1 0), (-1 0, 2 0))'
).MakeValid(),
geometry :: Parse('POLYGON((1 1, 1 1, 1 1, 1 1))').MakeValid(),
geometry :: Parse(
'CURVEPOLYGON (COMPOUNDCURVE (CIRCULARSTRING (-122.200928 47.454094, -122.810669 47.00648, -122.942505 46.687131, -121.14624 45.786679, -119.119263 46.183634), (-119.119263 46.183634, -119.273071 47.107523), CIRCULARSTRING (-119.273071 47.107523, -120.640869 47.569114, -122.200928 47.454094)))'
).MakeValid(),
geometry :: Parse('MULTIPOINT((2 3), (7 8 9.5))').MakeValid(),
geometry :: Parse(
'MULTILINESTRING((1 1, 3 3, 5 5),(3 3, 5 5, 7 7))'
).MakeValid(),
geometry :: Parse(
'MULTIPOLYGON(((-120.533 46.566, -118.283 46.1, -122.3 47.45, -120.533 46.566)),((2 2, 2 -2, -2 -2, -2 2, 2 2)),((1 1, 3 1, 3 3, 1 3, 1 1)))'
).MakeValid(),
geometry :: Parse(
'GEOMETRYCOLLECTION(LINESTRING(1 1, 3 5),POLYGON((-1 -1, -1 -5, -5 -5, -5 -1, -1 -1)))'
).MakeValid()
);
CREATE TABLE spatial_types_geog (
point geography,
linestring geography,
circularstring geography,
compoundcurve geography,
polygon geography,
curvepolygon geography,
multipoint geography,
multilinestring geography,
multipolygon geography
);
INSERT INTO
spatial_types_geog(
point,
linestring,
circularstring,
compoundcurve,
polygon,
curvepolygon,
multipoint,
multilinestring,
multipolygon
)
VALUES
(
geography :: Parse('POINT(3 4 7 2.5)').MakeValid(),
geography :: Parse('LINESTRING(1 1,2 3,4 8, -6 3)').MakeValid(),
geography :: Parse('CIRCULARSTRING(1 1, 2 0, 2 0, 2 0, 1 1)').MakeValid(),
geography :: Parse(
'COMPOUNDCURVE(CIRCULARSTRING(1 0, 0 1, -1 0), (-1 0, 2 0))'
).MakeValid(),
geography :: Parse('POLYGON((1 1, 1 1, 1 1, 1 1))').MakeValid(),
geography :: Parse(
'CURVEPOLYGON (COMPOUNDCURVE (CIRCULARSTRING (-122.200928 47.454094, -122.810669 47.00648, -122.942505 46.687131, -121.14624 45.786679, -119.119263 46.183634), (-119.119263 46.183634, -119.273071 47.107523), CIRCULARSTRING (-119.273071 47.107523, -120.640869 47.569114, -122.200928 47.454094)))'
).MakeValid(),
geography :: Parse('MULTIPOINT((2 3), (7 8 9.5))').MakeValid(),
geography :: Parse(
'MULTILINESTRING((1 1, 3 3, 5 5),(3 3, 5 5, 7 7))'
).MakeValid(),
geography :: Parse(
'MULTIPOLYGON(((-120.533 46.566, -118.283 46.1, -122.3 47.45, -120.533 46.566)),((2 2, 2 -2, -2 -2, -2 2, 2 2)),((1 1, 3 1, 3 3, 1 3, 1 1)))'
).MakeValid()
)

View File

@ -0,0 +1,13 @@
type: bulk
args:
- type: mssql_run_sql
args:
source: mssql
sql: |
drop table spatial_types_geom
- type: mssql_run_sql
args:
source: mssql
sql: |
drop table spatial_types_geog

View File

@ -0,0 +1,20 @@
description: Query data from spatial_types_geom table
url: /v1/graphql
status: 200
response:
data:
spatial_types_geom:
- linestring: LINESTRING (1 1, 2 3, 4 8, -6 3)
query:
query: |
query {
spatial_types_geom(
where: {
linestring: {
_st_crosses: "LINESTRING(1.5 1, 0 2.5)"
}
}
) {
linestring
}
}

View File

@ -0,0 +1,93 @@
description: GraphQL query to test different data types of SQL Server
url: /v1/graphql
status: 200
response:
data:
spatial_types_geom:
- point: POINT (3 4)
linestring: LINESTRING (1 1, 2 3, 4 8, -6 3)
circularstring: LINESTRING (1.0000000000000036 1, 2 3.5527136788005009E-15)
compoundcurve: COMPOUNDCURVE (CIRCULARSTRING (1 0, 0 1, -1 0), (-1 0, 2 0))
polygon: POINT (1 1)
curvepolygon:
CURVEPOLYGON (COMPOUNDCURVE (CIRCULARSTRING (-122.200928 47.454094,
-122.810669 47.00648, -122.942505 46.687131, -121.14624 45.786679, -119.119263
46.183634), (-119.119263 46.183634, -119.273071 47.107523), CIRCULARSTRING
(-119.273071 47.107523, -120.640869 47.569114, -122.200928 47.454094)))
multipoint: MULTIPOINT ((2 3), (7 8))
multilinestring:
LINESTRING (7.0000000000000071 7.0000000000000071, 4.9999999999999929
4.9999999999999929, 3.0000000000000213 3.0000000000000213, 1.0000000000000284
1.0000000000000284)
multipolygon:
MULTIPOLYGON (((-118.28299999999973 46.099999999999994, -122.29999999999953
47.450000000000074, -120.53299999999965 46.566000000000059, -118.28299999999973
46.099999999999994)), ((2.0000000000000213 1.0000000000001386, 3.0000000000000284
1.0000000000001386, 3.0000000000000284 3.0000000000002416, 1.0000000000000142
3.0000000000002416, 1.0000000000000142 2.000000000000103, 2.0000000000000213
2.000000000000103, 2.0000000000000213 1.0000000000001386)), ((-2.0000000000000142
-1.9999999999997549, 2.0000000000000213 -1.9999999999997549, 2.0000000000000213
1.0000000000001386, 1.0000000000000142 1.0000000000001386, 1.0000000000000142
2.000000000000103, -2.0000000000000142 2.000000000000103, -2.0000000000000142
-1.9999999999997549)))
geometrycollection:
GEOMETRYCOLLECTION (LINESTRING (1 1, 3 5), POLYGON ((-1
-1, -1 -5, -5 -5, -5 -1, -1 -1)))
spatial_types_geog:
- point: POINT (3 4)
linestring: LINESTRING (1 1, 2 3, 4 8, -6 3)
circularstring:
LINESTRING (0.99999999999996858 1.0000000000001434, 2.0000000000000311
-1.4370884402691508E-13)
compoundcurve: COMPOUNDCURVE (CIRCULARSTRING (1 0, 0 1, -1 0), (-1 0, 2 0))
polygon: POINT (1 0.99999999999999978)
curvepolygon:
CURVEPOLYGON (COMPOUNDCURVE (CIRCULARSTRING (-122.200928 47.454094,
-122.810669 47.00648, -122.942505 46.687131, -121.14624 45.786679, -119.119263
46.183634), (-119.119263 46.183634, -119.273071 47.107523), CIRCULARSTRING
(-119.273071 47.107523, -120.640869 47.569114, -122.200928 47.454094)))
multipoint: MULTIPOINT ((2 3), (7 8))
multilinestring:
LINESTRING (6.9999999999998526 6.99999999999996, 5.0000000000001332
5.0000000000000506, 2.9999999999999662 2.9999999999999454, 1.0000000000000222
0.99999999999995925)
multipolygon:
MULTIPOLYGON (((1.0000000000001976 2.9999999999999387, 1.0000000000000258
2.0009135502171214, 2.0000000000001763 1.9999999999999043, 2.00000000000012
1.00015229710434, 3.0000000000000724 1.0000000000000069, 2.9999999999998894
2.999999999999873, 1.0000000000001976 2.9999999999999387)), ((2.00000000000012
1.00015229710434, 0.99999999999985156 1.0000000000002536, 1.0000000000000258
2.0009135502171214, -1.9999999999998943 2.000000000000087, -2.0000000000000604
-1.9999999999998446, 1.9999999999999543 -2.0000000000001057, 2.00000000000012
1.00015229710434)), ((-118.2829999999997 46.099999999999874, -122.29999999999957
47.449999999999896, -120.53299999999994 46.566000000000038, -118.2829999999997
46.099999999999874)))
query:
query: |
query {
spatial_types_geom {
point
linestring
circularstring
compoundcurve
polygon
curvepolygon
multipoint
multilinestring
multipolygon
geometrycollection
}
spatial_types_geog {
point
linestring
circularstring
compoundcurve
polygon
curvepolygon
multipoint
multilinestring
multipolygon
}
}

View File

@ -0,0 +1,32 @@
description: Query data from spatial_types_geo* tables
url: /v1/graphql
status: 200
response:
data:
spatial_types_geog:
- multipoint: MULTIPOINT ((2 3), (7 8))
spatial_types_geom:
- compoundcurve: COMPOUNDCURVE (CIRCULARSTRING (1 0, 0 1, -1 0), (-1 0, 2 0))
query:
query: |
query {
spatial_types_geog(
where: {
multipoint: {
_st_contains: "POINT(2 3)"
}
}
) {
multipoint
}
spatial_types_geom(
where: {
compoundcurve: {
_st_contains: "POINT(0.5 0)"
}
}
) {
compoundcurve
}
}

View File

@ -0,0 +1,25 @@
description: Query data from spatial_types_geo* tables
url: /v1/graphql
status: 200
response:
data:
spatial_types_geog:
- point: POINT (3 4)
spatial_types_geom:
- geometrycollection: GEOMETRYCOLLECTION (LINESTRING (1 1, 3 5), POLYGON ((-1 -1, -1 -5, -5 -5, -5 -1, -1 -1)))
query:
query: |
query {
spatial_types_geog(where: { point: { _st_equals: "POINT(3 4)" } }) {
point
}
spatial_types_geom(
where: {
geometrycollection: {
_st_equals: "GEOMETRYCOLLECTION(LINESTRING(1 1, 3 5),POLYGON((-1 -1, -1 -5, -5 -5, -5 -1, -1 -1)))"
}
}
) {
geometrycollection
}
}

View File

@ -0,0 +1,25 @@
description: Query data from spatial_types_geo* tables
url: /v1/graphql
status: 200
response:
data:
spatial_types_geog:
- polygon: POINT (1 0.99999999999999978)
spatial_types_geom:
- linestring: LINESTRING (1 1, 2 3, 4 8, -6 3)
query:
query: |
query {
spatial_types_geog(where: { polygon: { _st_intersects: "LINESTRING(1 1, 0 1)" } }) {
polygon
}
spatial_types_geom(
where: {
linestring: {
_st_intersects: "POINT(1 1)"
}
}
) {
linestring
}
}

View File

@ -0,0 +1,46 @@
description: Query data from spatial_types_geo* tables
url: /v1/graphql
status: 200
response:
data:
spatial_types_geom:
- multipolygon:
MULTIPOLYGON (((-118.28299999999973 46.099999999999994, -122.29999999999953
47.450000000000074, -120.53299999999965 46.566000000000059, -118.28299999999973
46.099999999999994)), ((2.0000000000000213 1.0000000000001386, 3.0000000000000284
1.0000000000001386, 3.0000000000000284 3.0000000000002416, 1.0000000000000142
3.0000000000002416, 1.0000000000000142 2.000000000000103, 2.0000000000000213
2.000000000000103, 2.0000000000000213 1.0000000000001386)), ((-2.0000000000000142
-1.9999999999997549, 2.0000000000000213 -1.9999999999997549, 2.0000000000000213
1.0000000000001386, 1.0000000000000142 1.0000000000001386, 1.0000000000000142
2.000000000000103, -2.0000000000000142 2.000000000000103, -2.0000000000000142
-1.9999999999997549)))
spatial_types_geog:
- curvepolygon:
CURVEPOLYGON (COMPOUNDCURVE (CIRCULARSTRING (-122.200928 47.454094,
-122.810669 47.00648, -122.942505 46.687131, -121.14624 45.786679, -119.119263
46.183634), (-119.119263 46.183634, -119.273071 47.107523), CIRCULARSTRING
(-119.273071 47.107523, -120.640869 47.569114, -122.200928 47.454094)))
query:
query: |
query {
spatial_types_geom(
where: {
multipolygon: {
_st_overlaps: "CURVEPOLYGON (COMPOUNDCURVE (CIRCULARSTRING (-122.200928 47.454094, -122.810669 47.00648, -122.942505 46.687131, -121.14624 45.786679, -119.119263 46.183634), (-119.119263 46.183634, -119.273071 47.107523), CIRCULARSTRING (-119.273071 47.107523, -120.640869 47.569114, -122.200928 47.454094)))"
}
}
) {
multipolygon
}
spatial_types_geog(
where: {
curvepolygon: {
_st_overlaps: "POLYGON((-120.533 46.566, -118.283 46.1, -122.3 47.45, -120.533 46.566))"
}
}
) {
curvepolygon
}
}

View File

@ -0,0 +1,20 @@
description: Query data from spatial_types_geom table
url: /v1/graphql
status: 200
response:
data:
spatial_types_geom:
- point: POINT (3 4)
query:
query: |
query {
spatial_types_geom(
where: {
point: {
_st_touches: "POLYGON ((3 4, 2 5, 5 5, 5 2, 3 4))"
}
}
) {
point
}
}

View File

@ -0,0 +1,32 @@
description: Query data from spatial_types_geo* tables
url: /v1/graphql
status: 200
response:
data:
spatial_types_geom:
- point: POINT (3 4)
spatial_types_geog:
- multipoint: MULTIPOINT ((2 3), (7 8))
query:
query: |
query {
spatial_types_geom(
where: {
point: {
_st_within: "POLYGON ((2 2, 2 5, 5 5, 5 2, 2 2))"
}
}
) {
point
}
spatial_types_geog(
where: {
multipoint: {
_st_within: "POLYGON ((0 0, 10 10, 10 10, 10 0, 0 0))"
}
}
) {
multipoint
}
}

View File

@ -0,0 +1,3 @@
# TODO: https://github.com/hasura/graphql-engine-mono/issues/941
type: bulk
args: []

View File

@ -0,0 +1,13 @@
type: bulk
args:
- type: mssql_track_table
args:
source: mssql
table:
name: spatial_types_geom
- type: mssql_track_table
args:
source: mssql
table:
name: spatial_types_geog

View File

@ -0,0 +1,3 @@
# TODO: https://github.com/hasura/graphql-engine-mono/issues/941
type: bulk
args: []

View File

@ -0,0 +1,2 @@
type: bulk
args: []

View File

@ -954,3 +954,36 @@ class TestGraphQLQueryBoolExpLtree:
@classmethod
def dir(cls):
return 'queries/graphql_query/boolexp/ltree'
@pytest.mark.parametrize("transport", ['http', 'websocket'])
@pytest.mark.parametrize("backend", ['mssql'])
@usefixtures('per_class_tests_db_state', 'per_backend_tests')
class TestGraphQLQueryBoolExpSpatialMSSQL:
@pytest.mark.skip_server_upgrade_test
def test_select_spatial_mssql_types(self, hge_ctx, transport):
check_query_f(hge_ctx, self.dir() + '/select_query_spatial_types_mssql.yaml', transport)
def test_select_spatial_mssql_types_where_st_equals(self, hge_ctx, transport):
check_query_f(hge_ctx, self.dir() + '/select_query_spatial_types_where_st_equals_mssql.yaml', transport)
def test_select_spatial_mssql_types_where_st_contains(self, hge_ctx, transport):
check_query_f(hge_ctx, self.dir() + '/select_query_spatial_types_where_st_contains_mssql.yaml', transport)
def test_select_spatial_mssql_types_where_st_crosses(self, hge_ctx, transport):
check_query_f(hge_ctx, self.dir() + '/select_query_geom_where_st_crosses_mssql.yaml', transport)
def test_select_spatial_mssql_types_where_st_intersects(self, hge_ctx, transport):
check_query_f(hge_ctx, self.dir() + '/select_query_spatial_types_where_st_intersects_mssql.yaml', transport)
def test_select_spatial_mssql_types_where_st_overlaps(self, hge_ctx, transport):
check_query_f(hge_ctx, self.dir() + '/select_query_spatial_types_where_st_overlaps_mssql.yaml', transport)
def test_select_spatial_mssql_types_where_st_within(self, hge_ctx, transport):
check_query_f(hge_ctx, self.dir() + '/select_query_spatial_types_where_st_within_mssql.yaml', transport)
def test_select_spatial_mssql_types_where_st_touches(self, hge_ctx, transport):
check_query_f(hge_ctx, self.dir() + '/select_query_spatial_types_where_st_touches_mssql.yaml', transport)
@classmethod
def dir(cls):
return 'queries/graphql_query/boolexp/spatial'