-
Notifications
You must be signed in to change notification settings - Fork 2.8k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Server: Don't throw validation error while creating remote relationship joining singular type with array type #5603
Changes from 6 commits
bf2de78
87b1b57
22b4b28
8f2a780
32766d2
0a34d58
a3704b4
a34913f
d4e2955
22d563c
95b0808
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -65,7 +65,7 @@ validateErrorToText (toList -> errs) = | |
TableFieldNonexistent table fieldName -> | ||
"field with name " <> fieldName <<> " not found in table " <>> table | ||
ExpectedTypeButGot expTy actualTy -> | ||
"expected type " <> getBaseTy expTy <<> " but got " <>> getBaseTy actualTy | ||
"expected type " <> G.showGT expTy <<> " but got " <>> G.showGT actualTy | ||
InvalidType ty err -> | ||
"type " <> getBaseTy ty <<> err | ||
InvalidVariable var _ -> | ||
|
@@ -363,12 +363,12 @@ validateType permittedVariables value expectedGType types = | |
Just fieldInfo -> | ||
bindValidation | ||
(columnInfoToNamedType fieldInfo) | ||
(\actualNamedType -> assertType (G.toGT actualNamedType) expectedGType) | ||
G.VInt {} -> assertType (G.toGT $ mkScalarTy PGInteger) expectedGType | ||
G.VFloat {} -> assertType (G.toGT $ mkScalarTy PGFloat) expectedGType | ||
G.VBoolean {} -> assertType (G.toGT $ mkScalarTy PGBoolean) expectedGType | ||
(\actualNamedType -> isTypeCoercible (G.toGT actualNamedType) expectedGType) | ||
G.VInt {} -> isTypeCoercible (G.toGT $ mkScalarTy PGInteger) expectedGType | ||
G.VFloat {} -> isTypeCoercible (G.toGT $ mkScalarTy PGFloat) expectedGType | ||
G.VBoolean {} -> isTypeCoercible (G.toGT $ mkScalarTy PGBoolean) expectedGType | ||
G.VNull -> Failure (pure NullNotAllowedHere) | ||
G.VString {} -> assertType (G.toGT $ mkScalarTy PGText) expectedGType | ||
G.VString {} -> isTypeCoercible (G.toGT $ mkScalarTy PGText) expectedGType | ||
G.VEnum _ -> Failure (pure UnsupportedEnum) | ||
G.VList (G.unListValue -> values) -> do | ||
case values of | ||
|
@@ -405,19 +405,25 @@ validateType permittedVariables value expectedGType types = | |
(G.toGT $ G.NamedType name) | ||
"not an input object type")) | ||
|
||
assertType :: G.GType -> G.GType -> Validation (NonEmpty ValidationError) () | ||
assertType actualType expectedType = do | ||
-- check if both are list types or both are named types | ||
(when | ||
(isListType' actualType /= isListType' expectedType) | ||
(Failure (pure $ ExpectedTypeButGot expectedType actualType))) | ||
-- if list type then check over unwrapped type, else check base types | ||
if isListType' actualType | ||
then assertType (unwrapTy actualType) (unwrapTy expectedType) | ||
else (when | ||
(getBaseTy actualType /= getBaseTy expectedType) | ||
(Failure (pure $ ExpectedTypeButGot expectedType actualType))) | ||
pure () | ||
isTypeCoercible :: G.GType -> G.GType -> Validation (NonEmpty ValidationError) () | ||
isTypeCoercible actualType expectedType = | ||
-- The GraphQL spec says that, a singleton type can be coerced into an array | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I think technically "singleton" type is called |
||
-- type. Which means that if the 'actualType' is a singleton type, like | ||
-- 'Int' we should be able to join this with a remote node, which expects an | ||
-- input argument of type '[Int]' | ||
-- http://spec.graphql.org/June2018/#sec-Type-System.List | ||
let (actualBaseType, actualNestingLevel) = getBaseTyWithNestedLevelsCount actualType | ||
(expectedBaseType, expectedNestingLevel) = getBaseTyWithNestedLevelsCount expectedType | ||
in | ||
if actualBaseType == expectedBaseType | ||
then if (actualNestingLevel == expectedNestingLevel || actualNestingLevel == 0) | ||
-- The check of 'actualNestedCount == 0' is the case of coercing a singleton type | ||
-- into an array type | ||
then pure () | ||
else Failure (pure $ ExpectedTypeButGot expectedType actualType) | ||
-- we cannot coerce two types with different nesting levels, | ||
-- for example, we cannot coerce [Int] to [[Int]] | ||
else Failure (pure $ ExpectedTypeButGot expectedType actualType) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we simplify this code by using MultiwayIf if | actualBaseType /= expectedBaseType -> raiseValidationError
| actualNestingLevel /= expectedNestingLevel && actualNestingLevel /= 0 -> raiseValidationError
| otherwise -> pure ()
where
raiseValidationError = Failure $ pure $ ExpectedTypeButGot expectedType actualType Of course with appropriate comments. |
||
|
||
assertListType :: G.GType -> Validation (NonEmpty ValidationError) () | ||
assertListType actualType = | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,26 @@ | ||
description: Simple Remote relationship with singleton input value type joining to an expected array input type | ||
url: /v1/graphql | ||
status: 200 | ||
response: | ||
data: | ||
profiles: | ||
- id: 1 | ||
remoteUsers: | ||
- user_id: 1 | ||
userMessages: | ||
- id: 1 | ||
msg: "You win!" | ||
query: | ||
query: | | ||
query { | ||
profiles(where:{ id: { _eq: 1}}) { | ||
id | ||
remoteUsers { | ||
user_id | ||
userMessages { | ||
id | ||
msg | ||
} | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,25 @@ | ||
type: bulk | ||
args: | ||
- type: create_remote_relationship | ||
args: | ||
name: remoteUsers | ||
table: profiles | ||
hasura_fields: | ||
- id | ||
remote_schema: my-remote-schema | ||
remote_field: | ||
users: | ||
arguments: | ||
user_ids: "$id" | ||
|
||
- type: create_remote_relationship | ||
args: | ||
name: remoteUsersMultipleIds | ||
table: profiles | ||
hasura_fields: | ||
- id | ||
remote_schema: my-remote-schema | ||
remote_field: | ||
users: | ||
arguments: | ||
user_ids: ["$id"] | ||
tirumaraiselvan marked this conversation as resolved.
Show resolved
Hide resolved
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Does this really close 5133? I don't see any mention of list types there..
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, it does. The issue doesn't mention anything about the list type, because the error message thrown is incorrect. Ideally, the error message should have been
Error remote relationship: cannot validate remote relationship because expected type \"[Int]\" but got \"Int\"
instead of
Error remote relationship: cannot validate remote relationship because expected type \"Int\" but got \"Int\"
The reason the list notation is omitted from the error message because of this line
This PR solves that issue.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This error message can occur in another case too, while joining an
[Int]
type to aInt
type, where the validation is justified but the error message will be the sameError remote relationship: cannot validate remote relationship because expected type \"Int\" but got \"Int\"
which is not very helpful.
I'll fix the error message.