mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-15 09:22:43 +03:00
parent
e375c61e4a
commit
7ff1c8829a
@ -361,6 +361,42 @@ Checking for ``null`` values :
|
||||
|
||||
- ``_is_null`` (takes true/false as values)
|
||||
|
||||
PostGIS related operators on GEOMETRY columns :
|
||||
|
||||
.. list-table::
|
||||
:header-rows: 1
|
||||
|
||||
* - Operator
|
||||
- PostGIS equivalent
|
||||
* - ``_st_contains``
|
||||
- ``ST_Contains``
|
||||
* - ``_st_crosses``
|
||||
- ``ST_Crosses``
|
||||
* - ``_st_equals``
|
||||
- ``ST_Equals``
|
||||
* - ``_st_intersects``
|
||||
- ``ST_Intersects``
|
||||
* - ``_st_overlaps``
|
||||
- ``ST_Overlaps``
|
||||
* - ``_st_touches``
|
||||
- ``ST_Touches``
|
||||
* - ``_st_within``
|
||||
- ``ST_Within``
|
||||
* - ``_st_d_within``
|
||||
- ``ST_DWithin``
|
||||
|
||||
(For more details on what these operators do, refer to `PostGIS docs <http://postgis.net/workshops/postgis-intro/spatial_relationships.html>`__.)
|
||||
|
||||
.. Note::
|
||||
1. All operators take a json representation of ``geometry/geography`` values. Also see :doc:`here <../queries/query-filters>` for more query examples on these operators
|
||||
2. Input value for ``_st_d_within`` operator is an object:-
|
||||
|
||||
.. parsed-literal::
|
||||
|
||||
{
|
||||
field-name : {_st_d_within: {distance: Float, from: Value} }
|
||||
}
|
||||
|
||||
|
||||
.. _OrderByExp:
|
||||
|
||||
|
@ -473,6 +473,136 @@ Fetch a list of authors whose names begin with A or C (``similar`` is case-sensi
|
||||
}
|
||||
}
|
||||
|
||||
PostGIS topology operators
|
||||
--------------------------
|
||||
The ``_st_contains``, ``_st_crosses``, ``_st_equals``, ``_st_intersects``, ``_st_overlaps``,
|
||||
``_st_touches``, ``_st_within`` and ``_st_d_within`` operators are used to filter ``geometry`` like columns.
|
||||
For more details on what these operators do, refer to `PostGIS docs <http://postgis.net/workshops/postgis-intro/spatial_relationships.html>`__.
|
||||
|
||||
Use ``json`` (`GeoJSON <https://tools.ietf.org/html/rfc7946>`_) representation of ``geometry`` values in ``variables`` as shown in the following examples
|
||||
|
||||
|
||||
Example: _st_within
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
Fetch a list of geometry values which are within the given ``polygon`` value
|
||||
|
||||
.. graphiql::
|
||||
:view_only:
|
||||
:query:
|
||||
query geom_table($polygon: geometry){
|
||||
geom_table(where: {geom_col: {_st_within: $polygon}}){
|
||||
id
|
||||
geom_col
|
||||
}
|
||||
}
|
||||
:response:
|
||||
{
|
||||
"data": {
|
||||
"geom_table": [
|
||||
{
|
||||
"id": 1,
|
||||
"geom_col": {
|
||||
"type": "Point",
|
||||
"coordinates": [
|
||||
1,
|
||||
2
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Variables for above query:-
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"polygon": {
|
||||
"type": "Polygon",
|
||||
"coordinates": [
|
||||
[
|
||||
[
|
||||
0,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
2
|
||||
],
|
||||
[
|
||||
2,
|
||||
2
|
||||
],
|
||||
[
|
||||
2,
|
||||
0
|
||||
],
|
||||
[
|
||||
0,
|
||||
0
|
||||
]
|
||||
]
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Example: _st_d_within
|
||||
^^^^^^^^^^^^^^^^^^^^^
|
||||
Fetch a list of geometry values which are 3 units from given ``point`` value
|
||||
|
||||
.. graphiql::
|
||||
:view_only:
|
||||
:query:
|
||||
query geom_table($point: geometry){
|
||||
geom_table(where: {geom_col: {_st_d_within: {distance: 3, from: $point}}}){
|
||||
id
|
||||
geom_col
|
||||
}
|
||||
}
|
||||
:response:
|
||||
{
|
||||
"data": {
|
||||
"geom_table": [
|
||||
{
|
||||
"id": 1,
|
||||
"geom_col": {
|
||||
"type": "Point",
|
||||
"coordinates": [
|
||||
1,
|
||||
2
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"id": 2,
|
||||
"geom_col": {
|
||||
"type": "Point",
|
||||
"coordinates": [
|
||||
3,
|
||||
0
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
Variables for above query:-
|
||||
|
||||
.. code-block:: json
|
||||
|
||||
{
|
||||
"point": {
|
||||
"type": "Point",
|
||||
"coordinates": [
|
||||
0,
|
||||
0
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Filter or check for null values
|
||||
-------------------------------
|
||||
Checking for null values can be achieved using the ``_is_null`` operator.
|
||||
|
@ -161,6 +161,17 @@ mkCompExpTy :: PGColType -> G.NamedType
|
||||
mkCompExpTy =
|
||||
G.NamedType . mkCompExpName
|
||||
|
||||
{-
|
||||
input st_d_within_input {
|
||||
distance: Float!
|
||||
from: geometry!
|
||||
}
|
||||
-}
|
||||
|
||||
stDWithinInpTy :: G.NamedType
|
||||
stDWithinInpTy = G.NamedType "st_d_within_input"
|
||||
|
||||
|
||||
--- | make compare expression input type
|
||||
mkCompExpInp :: PGColType -> InpObjTyInfo
|
||||
mkCompExpInp colTy =
|
||||
@ -169,6 +180,7 @@ mkCompExpInp colTy =
|
||||
, map (mk $ G.toLT colScalarTy) listOps
|
||||
, bool [] (map (mk $ mkScalarTy PGText) stringOps) isStringTy
|
||||
, bool [] (map jsonbOpToInpVal jsonbOps) isJsonbTy
|
||||
, bool [] (stDWithinOpInpVal : map geomOpToInpVal geomOps) isGeometryTy
|
||||
, [InpValInfo Nothing "_is_null" $ G.TypeNamed (G.Nullability True) $ G.NamedType "Boolean"]
|
||||
]) HasuraType
|
||||
where
|
||||
@ -195,6 +207,7 @@ mkCompExpInp colTy =
|
||||
[ "_like", "_nlike", "_ilike", "_nilike"
|
||||
, "_similar", "_nsimilar"
|
||||
]
|
||||
|
||||
isJsonbTy = case colTy of
|
||||
PGJSONB -> True
|
||||
_ -> False
|
||||
@ -222,6 +235,43 @@ mkCompExpInp colTy =
|
||||
)
|
||||
]
|
||||
|
||||
-- Geometry related ops
|
||||
stDWithinOpInpVal =
|
||||
InpValInfo (Just stDWithinDesc) "_st_d_within" $ G.toGT stDWithinInpTy
|
||||
stDWithinDesc =
|
||||
"is the column within a distance from a geometry value"
|
||||
|
||||
isGeometryTy = case colTy of
|
||||
PGGeometry -> True
|
||||
_ -> False
|
||||
|
||||
geomOpToInpVal (op, desc) =
|
||||
InpValInfo (Just desc) op $ G.toGT $ mkScalarTy PGGeometry
|
||||
geomOps =
|
||||
[
|
||||
( "_st_contains"
|
||||
, "does the column contain the given geometry value"
|
||||
)
|
||||
, ( "_st_crosses"
|
||||
, "does the column crosses the given geometry value"
|
||||
)
|
||||
, ( "_st_equals"
|
||||
, "is the column equal to given geometry value. Directionality is ignored"
|
||||
)
|
||||
, ( "_st_intersects"
|
||||
, "does the column spatially intersect the given geometry value"
|
||||
)
|
||||
, ( "_st_overlaps"
|
||||
, "does the column 'spatially overlap' (intersect but not completely contain) the given geometry value"
|
||||
)
|
||||
, ( "_st_touches"
|
||||
, "does the column have atleast one point in common with the given geometry value"
|
||||
)
|
||||
, ( "_st_within"
|
||||
, "is the column contained in the given geometry value"
|
||||
)
|
||||
]
|
||||
|
||||
ordByTy :: G.NamedType
|
||||
ordByTy = G.NamedType "order_by"
|
||||
|
||||
@ -263,8 +313,6 @@ mkGCtx (TyAgg tyInfos fldInfos ordByEnums) (RootFlds flds) insCtxMap =
|
||||
let queryRoot = mkHsraObjTyInfo (Just "query root")
|
||||
(G.NamedType "query_root") $
|
||||
mapFromL _fiName (schemaFld:typeFld:qFlds)
|
||||
colTys = Set.toList $ Set.fromList $ map pgiType $
|
||||
lefts $ Map.elems fldInfos
|
||||
scalarTys = map (TIScalar . mkHsraScalarTyInfo) colTys
|
||||
compTys = map (TIInpObj . mkCompExpInp) colTys
|
||||
ordByEnumTyM = bool (Just ordByEnumTy) Nothing $ null qFlds
|
||||
@ -273,12 +321,15 @@ mkGCtx (TyAgg tyInfos fldInfos ordByEnums) (RootFlds flds) insCtxMap =
|
||||
, TIObj <$> mutRootM
|
||||
, TIObj <$> subRootM
|
||||
, TIEnum <$> ordByEnumTyM
|
||||
, TIInpObj <$> stDWithinInpM
|
||||
] <>
|
||||
scalarTys <> compTys <> defaultTypes
|
||||
-- for now subscription root is query root
|
||||
in GCtx allTys fldInfos ordByEnums queryRoot mutRootM subRootM
|
||||
(Map.map fst flds) insCtxMap
|
||||
where
|
||||
colTys = Set.toList $ Set.fromList $ map pgiType $
|
||||
lefts $ Map.elems fldInfos
|
||||
mkMutRoot =
|
||||
mkHsraObjTyInfo (Just "mutation root") (G.NamedType "mutation_root") .
|
||||
mapFromL _fiName
|
||||
@ -298,5 +349,12 @@ mkGCtx (TyAgg tyInfos fldInfos ordByEnums) (RootFlds flds) insCtxMap =
|
||||
$ G.toGT $ G.toNT $ G.NamedType "String"
|
||||
]
|
||||
|
||||
stDWithinInpM = bool Nothing (Just stDWithinInp) (PGGeometry `elem` colTys)
|
||||
stDWithinInp =
|
||||
mkHsraInpTyInfo Nothing stDWithinInpTy $ fromInpValL
|
||||
[ InpValInfo Nothing "from" $ G.toGT $ G.toNT $ mkScalarTy PGGeometry
|
||||
, InpValInfo Nothing "distance" $ G.toNT $ G.toNT $ mkScalarTy PGFloat
|
||||
]
|
||||
|
||||
emptyGCtx :: GCtx
|
||||
emptyGCtx = mkGCtx mempty mempty mempty
|
||||
|
@ -27,7 +27,6 @@ import qualified Hasura.GraphQL.Transport.HTTP.Protocol as GH
|
||||
import qualified Hasura.GraphQL.Validate as GV
|
||||
import qualified Hasura.GraphQL.Validate.Types as VT
|
||||
import qualified Hasura.RQL.DML.Select as RS
|
||||
import qualified Hasura.SQL.DML as S
|
||||
|
||||
data GQLExplain
|
||||
= GQLExplain
|
||||
@ -89,8 +88,8 @@ explainField userInfo gCtx fld =
|
||||
return $ FieldPlan fName (Just selectSQL) $ Just planLines
|
||||
where
|
||||
fName = _fName fld
|
||||
txtConverter (ty, val) =
|
||||
return $ S.annotateExp (txtEncoder val) ty
|
||||
txtConverter = return . uncurry toTxtValue
|
||||
|
||||
opCtxMap = _gOpCtxMap gCtx
|
||||
fldMap = _gFields gCtx
|
||||
orderByCtx = _gOrdByCtx gCtx
|
||||
|
@ -55,6 +55,16 @@ parseOpExps annVal = do
|
||||
"_has_keys_any" -> fmap AHasKeysAny <$> parseMany asPGColText v
|
||||
"_has_keys_all" -> fmap AHasKeysAll <$> parseMany asPGColText v
|
||||
|
||||
-- geometry type related operators
|
||||
"_st_contains" -> fmap ASTContains <$> asPGColValM v
|
||||
"_st_crosses" -> fmap ASTCrosses <$> asPGColValM v
|
||||
"_st_equals" -> fmap ASTEquals <$> asPGColValM v
|
||||
"_st_intersects" -> fmap ASTIntersects <$> asPGColValM v
|
||||
"_st_overlaps" -> fmap ASTOverlaps <$> asPGColValM v
|
||||
"_st_touches" -> fmap ASTTouches <$> asPGColValM v
|
||||
"_st_within" -> fmap ASTWithin <$> asPGColValM v
|
||||
"_st_d_within" -> asObjectM v >>= mapM parseAsSTDWithinObj
|
||||
|
||||
_ ->
|
||||
throw500
|
||||
$ "unexpected operator found in opexp of "
|
||||
@ -70,6 +80,14 @@ parseOpExps annVal = do
|
||||
AGScalar _ _ -> throw500 "boolean value is expected"
|
||||
_ -> tyMismatch "pgvalue" v
|
||||
|
||||
parseAsSTDWithinObj obj = do
|
||||
distanceVal <- onNothing (OMap.lookup "distance" obj) $
|
||||
throw500 "expected \"distance\" input field in st_d_within_input ty"
|
||||
distSQL <- uncurry toTxtValue <$> asPGColVal distanceVal
|
||||
fromVal <- onNothing (OMap.lookup "from" obj) $
|
||||
throw500 "expected \"from\" input field in st_d_within_input ty"
|
||||
ASTDWithin distSQL <$> asPGColVal fromVal
|
||||
|
||||
parseAsEqOp
|
||||
:: (MonadError QErr m)
|
||||
=> AnnGValue -> m [OpExp]
|
||||
|
@ -276,6 +276,16 @@ mkColCompExp qual lhsCol = \case
|
||||
AHasKey val -> S.BECompare S.SHasKey lhs val
|
||||
AHasKeysAny keys -> S.BECompare S.SHasKeysAny lhs $ toTextArray keys
|
||||
AHasKeysAll keys -> S.BECompare S.SHasKeysAll lhs $ toTextArray keys
|
||||
|
||||
ASTContains val -> mkGeomOpBe "ST_Contains" val
|
||||
ASTCrosses val -> mkGeomOpBe "ST_Crosses" val
|
||||
ASTDWithin r val -> applySQLFn "ST_DWithin" [lhs, val, r]
|
||||
ASTEquals val -> mkGeomOpBe "ST_Equals" val
|
||||
ASTIntersects val -> mkGeomOpBe "ST_Intersects" val
|
||||
ASTOverlaps val -> mkGeomOpBe "ST_Overlaps" val
|
||||
ASTTouches val -> mkGeomOpBe "ST_Touches" val
|
||||
ASTWithin val -> mkGeomOpBe "ST_Within" val
|
||||
|
||||
ANISNULL -> S.BENull lhs
|
||||
ANISNOTNULL -> S.BENotNull lhs
|
||||
CEQ rhsCol -> S.BECompare S.SEQ lhs $ mkQCol rhsCol
|
||||
@ -291,6 +301,10 @@ mkColCompExp qual lhsCol = \case
|
||||
toTextArray arr =
|
||||
S.SETyAnn (S.SEArray $ map (txtEncoder . PGValText) arr) S.textArrType
|
||||
|
||||
mkGeomOpBe fn v = applySQLFn fn [lhs, v]
|
||||
|
||||
applySQLFn f exps = S.BEExp $ S.SEFnApp f exps Nothing
|
||||
|
||||
handleEmptyIn [] = S.BELit False
|
||||
handleEmptyIn vals = S.BEIN lhs vals
|
||||
|
||||
|
@ -117,6 +117,15 @@ data OpExpG a
|
||||
| AHasKeysAny [Text]
|
||||
| AHasKeysAll [Text]
|
||||
|
||||
| ASTContains !a
|
||||
| ASTCrosses !a
|
||||
| ASTDWithin !S.SQLExp !a
|
||||
| ASTEquals !a
|
||||
| ASTIntersects !a
|
||||
| ASTOverlaps !a
|
||||
| ASTTouches !a
|
||||
| ASTWithin !a
|
||||
|
||||
| ANISNULL -- IS NULL
|
||||
| ANISNOTNULL -- IS NOT NULL
|
||||
|
||||
@ -157,6 +166,15 @@ opExpToJPair f = \case
|
||||
AHasKeysAny a -> ("_has_keys_any", toJSON a)
|
||||
AHasKeysAll a -> ("_has_keys_all", toJSON a)
|
||||
|
||||
ASTContains a -> ("_st_contains", f a)
|
||||
ASTCrosses a -> ("_st_crosses", f a)
|
||||
ASTDWithin _ a -> ("_st_d_within", f a)
|
||||
ASTEquals a -> ("_st_equals", f a)
|
||||
ASTIntersects a -> ("_st_intersects", f a)
|
||||
ASTOverlaps a -> ("_st_overlaps", f a)
|
||||
ASTTouches a -> ("_st_touches", f a)
|
||||
ASTWithin a -> ("_st_within", f a)
|
||||
|
||||
ANISNULL -> ("_is_null", toJSON True)
|
||||
ANISNOTNULL -> ("_is_null", toJSON False)
|
||||
|
||||
|
@ -460,6 +460,7 @@ data BoolExp
|
||||
| BENotNull !SQLExp
|
||||
| BEExists !Select
|
||||
| BEIN !SQLExp ![SQLExp]
|
||||
| BEExp !SQLExp
|
||||
deriving (Show, Eq)
|
||||
|
||||
-- removes extraneous 'AND true's
|
||||
@ -507,6 +508,8 @@ instance ToSQL BoolExp where
|
||||
-- special case to handle lhs IN (exp1, exp2)
|
||||
toSQL (BEIN vl exps) =
|
||||
paren (toSQL vl) <-> toSQL SIN <-> paren (", " <+> exps)
|
||||
-- Any SQL expression which evaluates to bool value
|
||||
toSQL (BEExp e) = paren $ toSQL e
|
||||
|
||||
data BinOp = AndOp
|
||||
| OrOp
|
||||
|
@ -120,6 +120,7 @@ uBoolExp = restoringIdens . \case
|
||||
S.BENotNull e -> S.BENotNull <$> uSqlExp e
|
||||
S.BEExists sel -> S.BEExists <$> uSelect sel
|
||||
S.BEIN left exps -> S.BEIN <$> uSqlExp left <*> mapM uSqlExp exps
|
||||
S.BEExp e -> S.BEExp <$> uSqlExp e
|
||||
|
||||
uOrderBy :: S.OrderByExp -> Uniq S.OrderByExp
|
||||
uOrderBy (S.OrderByExp ordByItems) =
|
||||
|
@ -188,11 +188,29 @@ iresToEither (ISuccess a) = return a
|
||||
pgValFromJVal :: (FromJSON a) => Value -> Either String a
|
||||
pgValFromJVal = iresToEither . ifromJSON
|
||||
|
||||
applyGeomFromGeoJson :: S.SQLExp -> S.SQLExp
|
||||
applyGeomFromGeoJson v =
|
||||
S.SEFnApp "ST_GeomFromGeoJSON" [v] Nothing
|
||||
|
||||
isGeoTy :: PGColType -> Bool
|
||||
isGeoTy = \case
|
||||
PGGeometry -> True
|
||||
PGGeography -> True
|
||||
_ -> False
|
||||
|
||||
toPrepParam :: Int -> PGColType -> S.SQLExp
|
||||
toPrepParam i pct =
|
||||
if pct == PGGeometry || pct == PGGeography
|
||||
then S.SEFnApp "ST_GeomFromGeoJSON" [S.SEPrep i] Nothing
|
||||
else S.SEPrep i
|
||||
toPrepParam i =
|
||||
bool prepVal (applyGeomFromGeoJson prepVal) . isGeoTy
|
||||
where
|
||||
prepVal = S.SEPrep i
|
||||
|
||||
toTxtValue :: PGColType -> PGColValue -> S.SQLExp
|
||||
toTxtValue ty val =
|
||||
S.annotateExp txtVal ty
|
||||
where
|
||||
txtVal = withGeoVal $ txtEncoder val
|
||||
withGeoVal v =
|
||||
bool v (applyGeomFromGeoJson v) $ isGeoTy ty
|
||||
|
||||
pgColValueToInt :: PGColValue -> Maybe Int
|
||||
pgColValueToInt (PGValInteger i) = Just $ fromIntegral i
|
||||
|
@ -0,0 +1,99 @@
|
||||
description: Query data from geom_table using postgis ops in bool exp and line value as input argument
|
||||
url: /v1alpha1/graphql
|
||||
status: 200
|
||||
response:
|
||||
data:
|
||||
st_crosses: []
|
||||
st_touches:
|
||||
- id: 1
|
||||
type: point
|
||||
geom_col:
|
||||
type: Point
|
||||
coordinates:
|
||||
- 1
|
||||
- 2
|
||||
- id: 2
|
||||
type: linestring
|
||||
geom_col:
|
||||
type: LineString
|
||||
coordinates:
|
||||
- - 0
|
||||
- 0
|
||||
- - 0.5
|
||||
- 1
|
||||
- - 1
|
||||
- 2
|
||||
- - 1.5
|
||||
- 3
|
||||
st_disjoint:
|
||||
- id: 3
|
||||
type: linestring
|
||||
geom_col:
|
||||
type: LineString
|
||||
coordinates:
|
||||
- - 1
|
||||
- 0
|
||||
- - 0.5
|
||||
- 0.5
|
||||
- - 0
|
||||
- 1
|
||||
- id: 4
|
||||
type: polygon
|
||||
geom_col:
|
||||
type: Polygon
|
||||
coordinates:
|
||||
- - - 0
|
||||
- 0
|
||||
- - 0
|
||||
- 1
|
||||
- - 1
|
||||
- 1
|
||||
- - 1
|
||||
- 0
|
||||
- - 0
|
||||
- 0
|
||||
- id: 5
|
||||
type: polygon
|
||||
geom_col:
|
||||
type: Polygon
|
||||
coordinates:
|
||||
- - - 2
|
||||
- 0
|
||||
- - 2
|
||||
- 1
|
||||
- - 3
|
||||
- 1
|
||||
- - 3
|
||||
- 0
|
||||
- - 2
|
||||
- 0
|
||||
|
||||
query:
|
||||
variables:
|
||||
line:
|
||||
type: LineString
|
||||
coordinates:
|
||||
- - -1
|
||||
- 0
|
||||
- - 0
|
||||
- 1.5
|
||||
- - 1
|
||||
- 2
|
||||
query: |
|
||||
query geom_table($line:geometry){
|
||||
st_crosses: geom_table(where: {geom_col: {_st_crosses: $line}}){
|
||||
id
|
||||
type
|
||||
geom_col
|
||||
}
|
||||
st_touches: geom_table(where: {geom_col: {_st_touches: $line}}){
|
||||
id
|
||||
type
|
||||
geom_col
|
||||
}
|
||||
st_disjoint: geom_table(where: {_not: {geom_col: {_st_intersects: $line}}}){
|
||||
id
|
||||
type
|
||||
geom_col
|
||||
}
|
||||
}
|
@ -0,0 +1,55 @@
|
||||
description: Query data from geom_table using postgis ops in bool exp and point value as input argument
|
||||
url: /v1alpha1/graphql
|
||||
status: 200
|
||||
response:
|
||||
data:
|
||||
st_contains:
|
||||
- id: 1
|
||||
type: point
|
||||
geom_col:
|
||||
type: Point
|
||||
coordinates:
|
||||
- 1
|
||||
- 2
|
||||
- id: 2
|
||||
type: linestring
|
||||
geom_col:
|
||||
type: LineString
|
||||
coordinates:
|
||||
- - 0
|
||||
- 0
|
||||
- - 0.5
|
||||
- 1
|
||||
- - 1
|
||||
- 2
|
||||
- - 1.5
|
||||
- 3
|
||||
st_equals:
|
||||
- id: 1
|
||||
type: point
|
||||
geom_col:
|
||||
type: Point
|
||||
coordinates:
|
||||
- 1
|
||||
- 2
|
||||
|
||||
query:
|
||||
variables:
|
||||
point:
|
||||
type: Point
|
||||
coordinates:
|
||||
- 1
|
||||
- 2
|
||||
query: |
|
||||
query geom_table($point: geometry){
|
||||
st_contains: geom_table(where: {geom_col: {_st_contains: $point}}){
|
||||
id
|
||||
type
|
||||
geom_col
|
||||
}
|
||||
st_equals: geom_table(where: {geom_col: {_st_equals: $point}}){
|
||||
id
|
||||
type
|
||||
geom_col
|
||||
}
|
||||
}
|
@ -0,0 +1,146 @@
|
||||
description: Query data from geom_table using postgis ops in bool exp and polygon value as input argument
|
||||
url: /v1alpha1/graphql
|
||||
status: 200
|
||||
response:
|
||||
data:
|
||||
st_d_within_2:
|
||||
- id: 1
|
||||
geom_col:
|
||||
type: Point
|
||||
coordinates:
|
||||
- 1
|
||||
- 2
|
||||
- id: 2
|
||||
geom_col:
|
||||
type: LineString
|
||||
coordinates:
|
||||
- - 0
|
||||
- 0
|
||||
- - 0.5
|
||||
- 1
|
||||
- - 1
|
||||
- 2
|
||||
- - 1.5
|
||||
- 3
|
||||
- id: 3
|
||||
geom_col:
|
||||
type: LineString
|
||||
coordinates:
|
||||
- - 1
|
||||
- 0
|
||||
- - 0.5
|
||||
- 0.5
|
||||
- - 0
|
||||
- 1
|
||||
- id: 4
|
||||
geom_col:
|
||||
type: Polygon
|
||||
coordinates:
|
||||
- - - 0
|
||||
- 0
|
||||
- - 0
|
||||
- 1
|
||||
- - 1
|
||||
- 1
|
||||
- - 1
|
||||
- 0
|
||||
- - 0
|
||||
- 0
|
||||
- id: 5
|
||||
geom_col:
|
||||
type: Polygon
|
||||
coordinates:
|
||||
- - - 2
|
||||
- 0
|
||||
- - 2
|
||||
- 1
|
||||
- - 3
|
||||
- 1
|
||||
- - 3
|
||||
- 0
|
||||
- - 2
|
||||
- 0
|
||||
st_d_within_3:
|
||||
- id: 1
|
||||
geom_col:
|
||||
type: Point
|
||||
coordinates:
|
||||
- 1
|
||||
- 2
|
||||
- id: 2
|
||||
geom_col:
|
||||
type: LineString
|
||||
coordinates:
|
||||
- - 0
|
||||
- 0
|
||||
- - 0.5
|
||||
- 1
|
||||
- - 1
|
||||
- 2
|
||||
- - 1.5
|
||||
- 3
|
||||
- id: 3
|
||||
geom_col:
|
||||
type: LineString
|
||||
coordinates:
|
||||
- - 1
|
||||
- 0
|
||||
- - 0.5
|
||||
- 0.5
|
||||
- - 0
|
||||
- 1
|
||||
- id: 4
|
||||
geom_col:
|
||||
type: Polygon
|
||||
coordinates:
|
||||
- - - 0
|
||||
- 0
|
||||
- - 0
|
||||
- 1
|
||||
- - 1
|
||||
- 1
|
||||
- - 1
|
||||
- 0
|
||||
- - 0
|
||||
- 0
|
||||
- id: 5
|
||||
geom_col:
|
||||
type: Polygon
|
||||
coordinates:
|
||||
- - - 2
|
||||
- 0
|
||||
- - 2
|
||||
- 1
|
||||
- - 3
|
||||
- 1
|
||||
- - 3
|
||||
- 0
|
||||
- - 2
|
||||
- 0
|
||||
|
||||
query:
|
||||
variables:
|
||||
polygon:
|
||||
type: Polygon
|
||||
coordinates:
|
||||
- - - 2
|
||||
- 0
|
||||
- - 2
|
||||
- 1
|
||||
- - 3
|
||||
- 1
|
||||
- - 3
|
||||
- 0
|
||||
- - 2
|
||||
- 0
|
||||
query: |
|
||||
query geom_table($polygon: geometry){
|
||||
st_d_within_2: geom_table(where: {geom_col: {_st_d_within: {distance: 2 from: $polygon}}}){
|
||||
id
|
||||
geom_col
|
||||
}
|
||||
st_d_within_3: geom_table(where: {geom_col: {_st_d_within: {distance: 3 from: $polygon}}}){
|
||||
id
|
||||
geom_col
|
||||
}
|
||||
}
|
@ -0,0 +1,39 @@
|
||||
type: bulk
|
||||
args:
|
||||
- type: run_sql
|
||||
args:
|
||||
sql: |
|
||||
CREATE EXTENSION IF NOT EXISTS postgis;
|
||||
|
||||
- type: run_sql
|
||||
args:
|
||||
sql: |
|
||||
CREATE EXTENSION IF NOT EXISTS postgis_topology;
|
||||
|
||||
#Create table
|
||||
- type: run_sql
|
||||
args:
|
||||
sql: |
|
||||
CREATE TABLE geom_table(
|
||||
id SERIAL PRIMARY KEY,
|
||||
type TEXT NOT NULL,
|
||||
geom_col geometry NOT NULL
|
||||
);
|
||||
- type: track_table
|
||||
args:
|
||||
name: geom_table
|
||||
schema: public
|
||||
|
||||
#Insert data
|
||||
- type: run_sql
|
||||
args:
|
||||
sql: |
|
||||
INSERT INTO geom_table (type, geom_col)
|
||||
VALUES
|
||||
('point', ST_GeomFromText('POINT(1 2)')),
|
||||
('linestring', ST_GeomFromText('LINESTRING(0 0, 0.5 1, 1 2, 1.5 3)')),
|
||||
('linestring', ST_GeomFromText('LINESTRING(1 0, 0.5 0.5, 0 1)')),
|
||||
('polygon', ST_GeomFromText('POLYGON((0 0, 0 1, 1 1, 1 0, 0 0))')),
|
||||
('polygon', ST_GeomFromText('POLYGON((2 0, 2 1, 3 1, 3 0, 2 0))'))
|
||||
;
|
||||
|
@ -0,0 +1,6 @@
|
||||
type: bulk
|
||||
args:
|
||||
- type: run_sql
|
||||
args:
|
||||
sql: |
|
||||
DROP TABLE geom_table;
|
@ -263,6 +263,20 @@ class TestGraphQLQueryBoolExpJsonB(DefaultTestSelectQueries):
|
||||
def dir(cls):
|
||||
return 'queries/graphql_query/boolexp/jsonb'
|
||||
|
||||
class TestGraphQLQueryBoolExpPostGIS(DefaultTestSelectQueries):
|
||||
|
||||
def test_query_using_point(self, hge_ctx):
|
||||
check_query_f(hge_ctx, self.dir() + '/query_using_point.yaml')
|
||||
|
||||
def test_query_using_line(self, hge_ctx):
|
||||
check_query_f(hge_ctx, self.dir() + '/query_using_line.yaml')
|
||||
|
||||
def test_query_using_polygon(self, hge_ctx):
|
||||
check_query_f(hge_ctx, self.dir() + '/query_using_polygon.yaml')
|
||||
|
||||
@classmethod
|
||||
def dir(cls):
|
||||
return 'queries/graphql_query/boolexp/postgis'
|
||||
|
||||
class TestGraphQLQueryOrderBy(DefaultTestSelectQueries):
|
||||
def test_articles_order_by_without_id(self, hge_ctx):
|
||||
|
Loading…
Reference in New Issue
Block a user