server: fix bug when executing a custom function with a row type argument

GitOrigin-RevId: d3a1fa8c9f6b420f4c88eb60c92019c8d0fdc58d
This commit is contained in:
Karthikeyan Chinnakonda 2021-05-06 14:48:57 +05:30 committed by hasura-bot
parent 3fad5f6678
commit d7ccf81526
5 changed files with 93 additions and 64 deletions

View File

@ -6,6 +6,7 @@
(Add entries below in the order of: server, console, cli, docs, others) (Add entries below in the order of: server, console, cli, docs, others)
- server: fix query execution of custom function containing a composite argument type
- server: fix a bug in query validation that would cause some queries using default variable values to be rejected (fix #6867) - server: fix a bug in query validation that would cause some queries using default variable values to be rejected (fix #6867)
- server: custom URI schemes are now supported in CORS config (fix #5818) (#5940) - server: custom URI schemes are now supported in CORS config (fix #5818) (#5940)
- console: read-only modify page for mssql - console: read-only modify page for mssql

View File

@ -285,6 +285,7 @@ data PGScalarType
| PGLquery | PGLquery
| PGLtxtquery | PGLtxtquery
| PGUnknown !Text | PGUnknown !Text
| PGCompositeScalar !Text
deriving (Show, Eq, Ord, Generic, Data) deriving (Show, Eq, Ord, Generic, Data)
instance NFData PGScalarType instance NFData PGScalarType
instance Hashable PGScalarType instance Hashable PGScalarType
@ -292,34 +293,35 @@ instance Cacheable PGScalarType
instance ToSQL PGScalarType where instance ToSQL PGScalarType where
toSQL = \case toSQL = \case
PGSmallInt -> "smallint" PGSmallInt -> "smallint"
PGInteger -> "integer" PGInteger -> "integer"
PGBigInt -> "bigint" PGBigInt -> "bigint"
PGSerial -> "serial" PGSerial -> "serial"
PGBigSerial -> "bigserial" PGBigSerial -> "bigserial"
PGFloat -> "real" PGFloat -> "real"
PGDouble -> "float8" PGDouble -> "float8"
PGNumeric -> "numeric" PGNumeric -> "numeric"
PGMoney -> "money" PGMoney -> "money"
PGBoolean -> "boolean" PGBoolean -> "boolean"
PGChar -> "bpchar" PGChar -> "bpchar"
PGVarchar -> "varchar" PGVarchar -> "varchar"
PGText -> "text" PGText -> "text"
PGCitext -> "citext" PGCitext -> "citext"
PGDate -> "date" PGDate -> "date"
PGTimeStamp -> "timestamp" PGTimeStamp -> "timestamp"
PGTimeStampTZ -> "timestamptz" PGTimeStampTZ -> "timestamptz"
PGTimeTZ -> "timetz" PGTimeTZ -> "timetz"
PGJSON -> "json" PGJSON -> "json"
PGJSONB -> "jsonb" PGJSONB -> "jsonb"
PGGeometry -> "geometry" PGGeometry -> "geometry"
PGGeography -> "geography" PGGeography -> "geography"
PGRaster -> "raster" PGRaster -> "raster"
PGUUID -> "uuid" PGUUID -> "uuid"
PGLtree -> "ltree" PGLtree -> "ltree"
PGLquery -> "lquery" PGLquery -> "lquery"
PGLtxtquery -> "ltxtquery" PGLtxtquery -> "ltxtquery"
PGUnknown t -> TB.text t PGUnknown t -> TB.text t
PGCompositeScalar t -> TB.text t
instance ToJSON PGScalarType where instance ToJSON PGScalarType where
toJSON = String . toSQLTxt toJSON = String . toSQLTxt
@ -509,12 +511,7 @@ typeToTable (QualifiedPGType sch n _) =
mkFunctionArgScalarType :: QualifiedPGType -> PGScalarType mkFunctionArgScalarType :: QualifiedPGType -> PGScalarType
mkFunctionArgScalarType (QualifiedPGType _schema name type') = mkFunctionArgScalarType (QualifiedPGType _schema name type') =
case type' of case type' of
-- When the function argument is a row type argument -- The suffix `_scalar` is added in
-- then it's possible that there can be an object type -- the @mkScalarTypeName@ function.
-- with the table name depending upon whether the table PGKindComposite -> PGCompositeScalar $ toTxt name
-- is tracked or not. As a result, we get a conflict between
-- both these types (scalar and object type with same name).
-- To avoid this, we suffix the table name with `_scalar`
-- and create a new scalar type
PGKindComposite -> PGUnknown $ toTxt name <> "_scalar"
_ -> name _ -> name

View File

@ -202,6 +202,8 @@ parsePGValue ty val = case (ty, val) of
PGLtxtquery -> PGValLtxtquery <$> parseJSON val PGLtxtquery -> PGValLtxtquery <$> parseJSON val
PGUnknown tyName -> PGUnknown tyName ->
fail $ "A string is expected for type: " ++ T.unpack tyName fail $ "A string is expected for type: " ++ T.unpack tyName
PGCompositeScalar tyName ->
fail $ "A string is expected for type: " ++ T.unpack tyName
txtEncodedVal :: PGScalarValue -> TxtEncodedVal txtEncodedVal :: PGScalarValue -> TxtEncodedVal
txtEncodedVal = \case txtEncodedVal = \case
@ -243,34 +245,35 @@ txtEncodedVal = \case
pgTypeOid :: PGScalarType -> PQ.Oid pgTypeOid :: PGScalarType -> PQ.Oid
pgTypeOid = \case pgTypeOid = \case
PGSmallInt -> PTI.int2 PGSmallInt -> PTI.int2
PGInteger -> PTI.int4 PGInteger -> PTI.int4
PGBigInt -> PTI.int8 PGBigInt -> PTI.int8
PGSerial -> PTI.int4 PGSerial -> PTI.int4
PGBigSerial -> PTI.int8 PGBigSerial -> PTI.int8
PGFloat -> PTI.float4 PGFloat -> PTI.float4
PGDouble -> PTI.float8 PGDouble -> PTI.float8
PGNumeric -> PTI.numeric PGNumeric -> PTI.numeric
PGMoney -> PTI.numeric PGMoney -> PTI.numeric
PGBoolean -> PTI.bool PGBoolean -> PTI.bool
PGChar -> PTI.char PGChar -> PTI.char
PGVarchar -> PTI.varchar PGVarchar -> PTI.varchar
PGText -> PTI.text PGText -> PTI.text
PGCitext -> PTI.text -- Explict type cast to citext needed, See also Note [Type casting prepared params] PGCitext -> PTI.text -- Explict type cast to citext needed, See also Note [Type casting prepared params]
PGDate -> PTI.date PGDate -> PTI.date
PGTimeStamp -> PTI.timestamp PGTimeStamp -> PTI.timestamp
PGTimeStampTZ -> PTI.timestamptz PGTimeStampTZ -> PTI.timestamptz
PGTimeTZ -> PTI.timetz PGTimeTZ -> PTI.timetz
PGJSON -> PTI.json PGJSON -> PTI.json
PGJSONB -> PTI.jsonb PGJSONB -> PTI.jsonb
PGGeometry -> PTI.text -- we are using the ST_GeomFromGeoJSON($i) instead of $i PGGeometry -> PTI.text -- we are using the ST_GeomFromGeoJSON($i) instead of $i
PGGeography -> PTI.text PGGeography -> PTI.text
PGRaster -> PTI.text -- we are using the ST_RastFromHexWKB($i) instead of $i PGRaster -> PTI.text -- we are using the ST_RastFromHexWKB($i) instead of $i
PGUUID -> PTI.uuid PGUUID -> PTI.uuid
PGLtree -> PTI.text PGLtree -> PTI.text
PGLquery -> PTI.text PGLquery -> PTI.text
PGLtxtquery -> PTI.text PGLtxtquery -> PTI.text
(PGUnknown _) -> PTI.auto (PGUnknown _) -> PTI.auto
PGCompositeScalar _ -> PTI.auto
binEncoder :: PGScalarValue -> Q.PrepArg binEncoder :: PGScalarValue -> Q.PrepArg
binEncoder = \case binEncoder = \case

View File

@ -392,6 +392,17 @@ mkScalarTypeName PG.PGBoolean = pure boolScalar
mkScalarTypeName PG.PGFloat = pure floatScalar mkScalarTypeName PG.PGFloat = pure floatScalar
mkScalarTypeName PG.PGText = pure stringScalar mkScalarTypeName PG.PGText = pure stringScalar
mkScalarTypeName PG.PGVarchar = pure stringScalar mkScalarTypeName PG.PGVarchar = pure stringScalar
mkScalarTypeName (PG.PGCompositeScalar compositeScalarType) =
-- When the function argument is a row type argument
-- then it's possible that there can be an object type
-- with the table name depending upon whether the table
-- is tracked or not. As a result, we get a conflict between
-- both these types (scalar and object type with same name).
-- To avoid this, we suffix the table name with `_scalar`
-- and create a new scalar type
(<> $$(G.litName "_scalar")) <$> G.mkName compositeScalarType `onNothing` throw400 ValidationFailed
("cannot use SQL type " <> compositeScalarType <<> " in the GraphQL schema because its name is not a "
<> "valid GraphQL identifier")
mkScalarTypeName scalarType = G.mkName (toSQLTxt scalarType) `onNothing` throw400 ValidationFailed mkScalarTypeName scalarType = G.mkName (toSQLTxt scalarType) `onNothing` throw400 ValidationFailed
("cannot use SQL type " <> scalarType <<> " in the GraphQL schema because its name is not a " ("cannot use SQL type " <> scalarType <<> " in the GraphQL schema because its name is not a "
<> "valid GraphQL identifier") <> "valid GraphQL identifier")

View File

@ -38,3 +38,20 @@
kind kind
} }
} }
- description: Execute the tracked function with a composite row type argument
url: /v1/graphql
status: 200
query:
query: |
query {
search_post_by_test (args: {t: "(1, hasura,311cf381-71e7-449b-bac5-86cd6deafd5b)"}) {
title
content
}
}
response:
data:
search_post_by_test:
- title: post by hasura
content: content for post