mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-14 08:02:15 +03:00
server: support remote relationship with ID scalar types (#92)
Co-authored-by: Karthikeyan Chinnakonda <karthikeyan@hasura.io> GITHUB_PR_NUMBER: 6227 GITHUB_PR_URL: https://github.com/hasura/graphql-engine/pull/6227 Co-authored-by: Karthikeyan Chinnakonda <karthikeyan@hasura.io> GitOrigin-RevId: 666ec37d570e46482e0f27db2c97c9e3f9c1f4d3
This commit is contained in:
parent
2acad94fb1
commit
5ca8cd23a0
@ -61,6 +61,7 @@ This release contains the [PDV refactor (#4111)](https://github.com/hasura/graph
|
||||
- server: Configurable websocket keep-alive interval. Add `--websocket-keepalive` command-line flag and `HASURA_GRAPHQL_WEBSOCKET_KEEPALIVE` env variable (fix #3539)
|
||||
- server: validate remote schema queries (fixes #4143)
|
||||
- server: introduce optional custom table name in table configuration to track the table according to the custom name. The `set_table_custom_fields` API has been deprecated, A new API `set_table_customization` has been added to set the configuration. (#3811)
|
||||
- server: support joining Int or String scalar types to ID scalar type in remote relationship
|
||||
- console: allow user to cascade Postgres dependencies when dropping Postgres objects (close #5109) (#5248)
|
||||
- console: mark inconsistent remote schemas in the UI (close #5093) (#5181)
|
||||
- console: remove ONLY as default for ALTER TABLE in column alter operations (close #5512) #5706
|
||||
|
@ -42,6 +42,7 @@ data ValidationError
|
||||
| UnsupportedMultipleElementLists
|
||||
| UnsupportedEnum
|
||||
| InvalidGraphQLName !Text
|
||||
| IDTypeJoin !G.Name
|
||||
|
||||
errorToText :: ValidationError -> Text
|
||||
errorToText = \case
|
||||
@ -77,6 +78,8 @@ errorToText = \case
|
||||
"enum value is not supported"
|
||||
InvalidGraphQLName t ->
|
||||
t <<> " is not a valid GraphQL identifier"
|
||||
IDTypeJoin typeName ->
|
||||
"Only ID, Int, uuid or String scalar types can be joined to the ID type, but recieved " <>> typeName
|
||||
|
||||
-- | Validate a remote relationship given a context.
|
||||
validateRemoteRelationship
|
||||
@ -281,10 +284,10 @@ renameNamedType rename =
|
||||
G.unsafeMkName . rename . G.unName
|
||||
|
||||
-- | Convert a field name to a variable name.
|
||||
pgColumnToVariable :: (MonadError ValidationError m) => PGCol -> m G.Name
|
||||
pgColumnToVariable :: MonadError ValidationError m => PGCol -> m G.Name
|
||||
pgColumnToVariable pgCol =
|
||||
let pgColText = getPGColTxt pgCol
|
||||
in maybe (throwError $ InvalidGraphQLName pgColText) pure $ G.mkName pgColText
|
||||
in onNothing (G.mkName pgColText) (throwError $ InvalidGraphQLName pgColText)
|
||||
|
||||
-- | Lookup the field in the schema.
|
||||
lookupField
|
||||
@ -342,17 +345,17 @@ validateType permittedVariables value expectedGType schemaDocument =
|
||||
namedType <- columnInfoToNamedType fieldInfo
|
||||
isTypeCoercible (mkGraphQLType namedType) expectedGType
|
||||
G.VInt {} -> do
|
||||
intScalarGType <- mkGraphQLType <$> mkScalarTy PGInteger
|
||||
intScalarGType <- mkGraphQLType <$> getPGScalarTypeName PGInteger
|
||||
isTypeCoercible intScalarGType expectedGType
|
||||
G.VFloat {} -> do
|
||||
floatScalarGType <- mkGraphQLType <$> mkScalarTy PGFloat
|
||||
floatScalarGType <- mkGraphQLType <$> getPGScalarTypeName PGFloat
|
||||
isTypeCoercible floatScalarGType expectedGType
|
||||
G.VBoolean {} -> do
|
||||
boolScalarGType <- mkGraphQLType <$> mkScalarTy PGBoolean
|
||||
boolScalarGType <- mkGraphQLType <$> getPGScalarTypeName PGBoolean
|
||||
isTypeCoercible boolScalarGType expectedGType
|
||||
G.VNull -> throwError NullNotAllowedHere
|
||||
G.VString {} -> do
|
||||
stringScalarGType <- mkGraphQLType <$> mkScalarTy PGText
|
||||
stringScalarGType <- mkGraphQLType <$> getPGScalarTypeName PGText
|
||||
isTypeCoercible stringScalarGType expectedGType
|
||||
G.VEnum _ -> throwError UnsupportedEnum
|
||||
G.VList values -> do
|
||||
@ -389,12 +392,6 @@ validateType permittedVariables value expectedGType schemaDocument =
|
||||
mkGraphQLType =
|
||||
G.TypeNamed (G.Nullability False)
|
||||
|
||||
mkScalarTy scalarType = do
|
||||
eitherScalar <- runExceptT $ mkScalarTypeName scalarType
|
||||
case eitherScalar of
|
||||
Left _ -> throwError $ InvalidGraphQLName $ toSQLTxt scalarType
|
||||
Right s -> pure s
|
||||
|
||||
isTypeCoercible
|
||||
:: (MonadError ValidationError m)
|
||||
=> G.GType
|
||||
@ -409,7 +406,16 @@ isTypeCoercible actualType expectedType =
|
||||
let (actualBaseType, actualNestingLevel) = getBaseTyWithNestedLevelsCount actualType
|
||||
(expectedBaseType, expectedNestingLevel) = getBaseTyWithNestedLevelsCount expectedType
|
||||
in
|
||||
if | actualBaseType /= expectedBaseType -> raiseValidationError
|
||||
if | expectedBaseType == $$(G.litName "ID") ->
|
||||
bool (throwError $ IDTypeJoin actualBaseType)
|
||||
(pure ())
|
||||
-- Check under `Input Coercion` https://spec.graphql.org/June2018/#sec-ID
|
||||
-- We can also include the `ID` type in the below list but it will be
|
||||
-- extraneous because at the time of writing this, we don't generate
|
||||
-- the `ID` type in the DB schema
|
||||
(G.unName actualBaseType `elem`
|
||||
["ID", "Int", "String", "bigint", "smallint" , "uuid"])
|
||||
| actualBaseType /= expectedBaseType -> raiseValidationError
|
||||
-- we cannot coerce two types with different nesting levels,
|
||||
-- for example, we cannot coerce [Int] to [[Int]]
|
||||
| (actualNestingLevel == expectedNestingLevel || actualNestingLevel == 0) -> pure ()
|
||||
@ -417,6 +423,11 @@ isTypeCoercible actualType expectedType =
|
||||
where
|
||||
raiseValidationError = throwError $ ExpectedTypeButGot expectedType actualType
|
||||
|
||||
getPGScalarTypeName :: MonadError ValidationError m => PGScalarType -> m G.Name
|
||||
getPGScalarTypeName scalarType =
|
||||
runExceptT (mkScalarTypeName scalarType) >>=
|
||||
flip onLeft (\ _ -> throwError $ InvalidGraphQLName $ toSQLTxt scalarType)
|
||||
|
||||
assertListType :: (MonadError ValidationError m) => G.GType -> m ()
|
||||
assertListType actualType =
|
||||
unless (G.isListType actualType)
|
||||
@ -429,9 +440,5 @@ columnInfoToNamedType
|
||||
-> m G.Name
|
||||
columnInfoToNamedType pci =
|
||||
case pgiType pci of
|
||||
PGColumnScalar scalarType -> do
|
||||
eitherScalar <- runExceptT $ mkScalarTypeName scalarType
|
||||
case eitherScalar of
|
||||
Left _ -> throwError $ InvalidGraphQLName $ toSQLTxt scalarType
|
||||
Right s -> pure s
|
||||
PGColumnScalar scalarType -> getPGScalarTypeName scalarType
|
||||
_ -> throwError UnsupportedEnum
|
||||
|
@ -74,12 +74,12 @@ const typeDefs = gql`
|
||||
type Query {
|
||||
hello: String
|
||||
messages(where: MessageWhereInpObj, includes: IncludeInpObj): [Message]
|
||||
user(user_id: Int!): User
|
||||
users(user_ids: [Int]!): [User]
|
||||
user(user_id: ID!): User
|
||||
users(user_ids: [ID]!): [User]
|
||||
message(id: Int!) : Message
|
||||
communications(id: Int): [Communication]
|
||||
search(id: Int!): SearchResult
|
||||
getOccupation(name: String!): Occupation!
|
||||
getOccupation(name: ID!): Occupation!
|
||||
}
|
||||
`;
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user