Merge branch 'master' into master

This commit is contained in:
Atharva Kulkarni 2023-11-17 17:30:57 +05:30 committed by GitHub
commit 8ebb048de5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
23 changed files with 152 additions and 24 deletions

View File

@ -30,7 +30,7 @@ services:
MONGO_INITDB_ROOT_USERNAME: mongouser
MONGO_INITDB_ROOT_PASSWORD: mongopassword
hasura:
image: hasura/graphql-engine:v2.35.0
image: hasura/graphql-engine:v2.35.1
restart: always
ports:
- 8080:8080
@ -60,7 +60,7 @@ services:
postgres:
condition: service_healthy
mongo-data-connector:
image: hasura/mongo-data-connector:v2.32.0
image: hasura/mongo-data-connector:v2.35.1
ports:
- 3000:3000
volumes:

View File

@ -255,12 +255,16 @@ function maybe_launch_hasura_container() {
--env HASURA_GRAPHQL_SERVER_PORT="$HASURA_GRAPHQL_SERVER_PORT" \
--env HASURA_GRAPHQL_ADMIN_SECRET \
--env HASURA_GRAPHQL_EE_LICENSE_KEY \
--env HASURA_GRAPHQL_EVENTS_FETCH_INTERVAL=0 \
--env HASURA_GRAPHQL_SCHEMA_SYNC_POLL_INTERVAL=0 \
$DOCKER_NETWORK_HOST_MODE \
"$REQUESTED_HASURA_DOCKER_IMAGE" \
graphql-engine serve \
+RTS -T $HASURA_RTS -RTS
# ^^^ We run with `+RTS -T` to expose the /dev/rts_stats endpoint for
# ^^^ - We run with `+RTS -T` to expose the /dev/rts_stats endpoint for
# inspecting memory usage stats
# - We disable some unneeded (currently) polling to try to eliminate
# some sources of non-determinism
else
echo_pretty "We'll benchmark the hasura instance at port $HASURA_GRAPHQL_SERVER_PORT"
fi

View File

@ -280,6 +280,7 @@ serveOptions =
soEnableTelemetry = Init.TelemetryDisabled,
soStringifyNum = Options.Don'tStringifyNumbers,
soDangerousBooleanCollapse = Options.Don'tDangerouslyCollapseBooleans,
soBackwardsCompatibleNullInNonNullableVariables = Options.Don'tAllowNullInNonNullableVariables,
soRemoteNullForwardingPolicy = Options.RemoteForwardAccurately,
soEnabledAPIs = testSuiteEnabledApis,
soLiveQueryOpts = ES.mkSubscriptionsOptions Nothing Nothing,

View File

@ -266,7 +266,7 @@ buildAppContextRule ::
buildAppContextRule = proc (ServeOptions {..}, env, _keys, checkFeatureFlag) -> do
schemaSampledFeatureFlags <- arrM (liftIO . sampleFeatureFlags) -< checkFeatureFlag
authMode <- buildAuthMode -< (soAdminSecret, soAuthHook, soJwtSecret, soUnAuthRole)
let sqlGenCtx = initSQLGenCtx soExperimentalFeatures soStringifyNum soDangerousBooleanCollapse soRemoteNullForwardingPolicy
let sqlGenCtx = initSQLGenCtx soExperimentalFeatures soStringifyNum soDangerousBooleanCollapse soBackwardsCompatibleNullInNonNullableVariables soRemoteNullForwardingPolicy
responseInternalErrorsConfig <- buildResponseInternalErrorsConfig -< (soAdminInternalErrors, soDevMode)
eventEngineCtx <- buildEventEngineCtx -< (soEventsHttpPoolSize, soEventsFetchInterval, soEventsFetchBatchSize)
returnA
@ -329,8 +329,14 @@ buildAppContextRule = proc (ServeOptions {..}, env, _keys, checkFeatureFlag) ->
--------------------------------------------------------------------------------
-- subsets
initSQLGenCtx :: HashSet ExperimentalFeature -> Options.StringifyNumbers -> Options.DangerouslyCollapseBooleans -> Options.RemoteNullForwardingPolicy -> SQLGenCtx
initSQLGenCtx experimentalFeatures stringifyNum dangerousBooleanCollapse remoteNullForwardingPolicy =
initSQLGenCtx ::
HashSet ExperimentalFeature ->
Options.StringifyNumbers ->
Options.DangerouslyCollapseBooleans ->
Options.BackwardsCompatibleNullInNonNullableVariables ->
Options.RemoteNullForwardingPolicy ->
SQLGenCtx
initSQLGenCtx experimentalFeatures stringifyNum dangerousBooleanCollapse nullInNonNullableVariables remoteNullForwardingPolicy =
let optimizePermissionFilters
| EFOptimizePermissionFilters `elem` experimentalFeatures = Options.OptimizePermissionFilters
| otherwise = Options.Don'tOptimizePermissionFilters
@ -338,7 +344,7 @@ initSQLGenCtx experimentalFeatures stringifyNum dangerousBooleanCollapse remoteN
bigqueryStringNumericInput
| EFBigQueryStringNumericInput `elem` experimentalFeatures = Options.EnableBigQueryStringNumericInput
| otherwise = Options.DisableBigQueryStringNumericInput
in SQLGenCtx stringifyNum dangerousBooleanCollapse remoteNullForwardingPolicy optimizePermissionFilters bigqueryStringNumericInput
in SQLGenCtx stringifyNum dangerousBooleanCollapse nullInNonNullableVariables remoteNullForwardingPolicy optimizePermissionFilters bigqueryStringNumericInput
buildCacheStaticConfig :: AppEnv -> CacheStaticConfig
buildCacheStaticConfig AppEnv {..} =

View File

@ -390,6 +390,7 @@ getResolvedExecPlan
tracesPropagator
prometheusMetrics
gCtx
sqlGenCtx
userInfo
reqHeaders
directives
@ -426,6 +427,7 @@ getResolvedExecPlan
G.TypedOperationDefinition G.OperationTypeSubscription _ varDefs directives inlinedSelSet -> Tracing.newSpan "Resolve subscription execution plan" $ do
(normalizedDirectives, normalizedSelectionSet) <-
ER.resolveVariables
(nullInNonNullableVariables sqlGenCtx)
varDefs
(fromMaybe mempty (_grVariables reqUnparsed))
directives

View File

@ -103,7 +103,7 @@ convertMutationSelectionSet
tracesPropagator
prometheusMetrics
gqlContext
SQLGenCtx {stringifyNum}
SQLGenCtx {stringifyNum, nullInNonNullableVariables}
userInfo
reqHeaders
directives
@ -117,7 +117,7 @@ convertMutationSelectionSet
onNothing (gqlMutationParser gqlContext)
$ throw400 ValidationFailed "no mutations exist"
(resolvedDirectives, resolvedSelSet) <- resolveVariables varDefs (fromMaybe HashMap.empty (GH._grVariables gqlUnparsed)) directives fields
(resolvedDirectives, resolvedSelSet) <- resolveVariables nullInNonNullableVariables varDefs (fromMaybe HashMap.empty (GH._grVariables gqlUnparsed)) directives fields
-- Parse the GraphQL query into the RQL AST
(unpreparedQueries :: RootFieldMap (MutationRootField UnpreparedValue)) <-
Tracing.newSpan "Parse mutation IR" $ liftEither $ mutationParser resolvedSelSet

View File

@ -32,7 +32,9 @@ import Hasura.RQL.IR
import Hasura.RQL.IR.ModelInformation
import Hasura.RQL.Types.Action
import Hasura.RQL.Types.Backend
import Hasura.RQL.Types.Common
import Hasura.RQL.Types.GraphqlSchemaIntrospection
import Hasura.RQL.Types.Schema.Options as Options
import Hasura.RemoteSchema.Metadata.Base (RemoteSchemaName (..))
import Hasura.SQL.AnyBackend qualified as AB
import Hasura.Server.Prometheus (PrometheusMetrics (..))
@ -46,6 +48,7 @@ import Network.HTTP.Types qualified as HTTP
parseGraphQLQuery ::
(MonadError QErr m) =>
Options.BackwardsCompatibleNullInNonNullableVariables ->
GQLContext ->
[G.VariableDefinition] ->
Maybe (HashMap G.Name J.Value) ->
@ -56,8 +59,8 @@ parseGraphQLQuery ::
[G.Directive Variable],
G.SelectionSet G.NoFragments Variable
)
parseGraphQLQuery gqlContext varDefs varValsM directives fields = do
(resolvedDirectives, resolvedSelSet) <- resolveVariables varDefs (fromMaybe HashMap.empty varValsM) directives fields
parseGraphQLQuery nullInNonNullableVariables gqlContext varDefs varValsM directives fields = do
(resolvedDirectives, resolvedSelSet) <- resolveVariables nullInNonNullableVariables varDefs (fromMaybe HashMap.empty varValsM) directives fields
parsedQuery <- liftEither $ gqlQueryParser gqlContext resolvedSelSet
pure (parsedQuery, resolvedDirectives, resolvedSelSet)
@ -77,6 +80,7 @@ convertQuerySelSet ::
Tracing.HttpPropagator ->
PrometheusMetrics ->
GQLContext ->
SQLGenCtx ->
UserInfo ->
HTTP.RequestHeaders ->
[G.Directive G.Name] ->
@ -94,6 +98,7 @@ convertQuerySelSet
tracingPropagator
prometheusMetrics
gqlContext
SQLGenCtx {nullInNonNullableVariables}
userInfo
reqHeaders
directives
@ -105,7 +110,7 @@ convertQuerySelSet
maybeOperationName = do
-- 1. Parse the GraphQL query into the 'RootFieldMap' and a 'SelectionSet'
(unpreparedQueries, normalizedDirectives, normalizedSelectionSet) <-
Tracing.newSpan "Parse query IR" $ parseGraphQLQuery gqlContext varDefs (GH._grVariables gqlUnparsed) directives fields
Tracing.newSpan "Parse query IR" $ parseGraphQLQuery nullInNonNullableVariables gqlContext varDefs (GH._grVariables gqlUnparsed) directives fields
-- 2. Parse directives on the query
dirMap <- toQErr $ runParse (parseDirectives customDirectives (G.DLExecutable G.EDLQUERY) normalizedDirectives)

View File

@ -5,6 +5,7 @@ module Hasura.GraphQL.Execute.Resolve
)
where
import Data.Aeson qualified as J
import Data.HashMap.Strict.Extended qualified as HashMap
import Data.HashSet qualified as HS
import Data.List qualified as L
@ -15,11 +16,13 @@ import Hasura.GraphQL.Parser.Names
import Hasura.GraphQL.Parser.Variable
import Hasura.GraphQL.Transport.HTTP.Protocol qualified as GH
import Hasura.Prelude
import Hasura.RQL.Types.Schema.Options qualified as Options
import Language.GraphQL.Draft.Syntax qualified as G
resolveVariables ::
forall m fragments.
(MonadError QErr m, Traversable fragments) =>
Options.BackwardsCompatibleNullInNonNullableVariables ->
[G.VariableDefinition] ->
GH.VariableValues ->
[G.Directive G.Name] ->
@ -28,7 +31,7 @@ resolveVariables ::
( [G.Directive Variable],
G.SelectionSet fragments Variable
)
resolveVariables definitions jsonValues directives selSet = do
resolveVariables nullInNonNullableVariables definitions jsonValues directives selSet = do
variablesByName <- HashMap.groupOnNE getName <$> traverse buildVariable definitions
uniqueVariables <- flip
HashMap.traverseWithKey
@ -83,7 +86,21 @@ resolveVariables definitions jsonValues directives selSet = do
let defaultValue = fromMaybe G.VNull _vdDefaultValue
isOptional = isJust _vdDefaultValue || G.isNullable _vdType
value <- case HashMap.lookup _vdName jsonValues of
Just jsonValue -> pure $ Just $ JSONValue jsonValue
Just jsonValue ->
-- If variable type is non-nullalbe , then raise exception if 'null' is provided
if not (G.isNullable _vdType)
-- `HASURA_GRAPHQL_BACKWARDS_COMPAT_NULL_IN_NONNULLABLE_VARIABLES` option set to `false`
&& nullInNonNullableVariables
== Options.Don'tAllowNullInNonNullableVariables
-- A 'null' value provided
&& jsonValue
== J.Null
then -- raise validation exception
throw400 ValidationFailed
$ "null value found for non-nullable type: "
<>> G.showGT _vdType
else pure $ Just $ JSONValue jsonValue
Nothing
-- If the variable value was not provided, and the variable has no
-- default value, then don't store a value for the variable.

View File

@ -31,6 +31,7 @@ import Hasura.Prelude
import Hasura.QueryTags
import Hasura.RQL.IR
import Hasura.RQL.Types.Roles (adminRoleName)
import Hasura.RQL.Types.Schema.Options qualified as Options
import Hasura.RQL.Types.SchemaCache
import Hasura.SQL.AnyBackend qualified as AB
import Hasura.Session (UserAdminSecret (..), UserInfo, UserRoleBuild (..), mkSessionVariablesText, mkUserInfo)
@ -93,12 +94,13 @@ explainGQLQuery ::
MonadQueryTags m,
MonadTrace m
) =>
Options.BackwardsCompatibleNullInNonNullableVariables ->
SchemaCache ->
Maybe (CredentialCache AgentLicenseKey) ->
[HTTP.Header] ->
GQLExplain ->
m EncJSON
explainGQLQuery sc agentLicenseKey reqHeaders (GQLExplain query userVarsRaw maybeIsRelay) = do
explainGQLQuery nullInNonNullableVariables sc agentLicenseKey reqHeaders (GQLExplain query userVarsRaw maybeIsRelay) = do
-- NOTE!: we will be executing what follows as though admin role. See e.g. notes in explainField:
userInfo <-
mkUserInfo
@ -111,7 +113,7 @@ explainGQLQuery sc agentLicenseKey reqHeaders (GQLExplain query userVarsRaw mayb
case queryParts of
G.TypedOperationDefinition G.OperationTypeQuery _ varDefs directives inlinedSelSet -> do
(unpreparedQueries, _, _) <-
E.parseGraphQLQuery graphQLContext varDefs (GH._grVariables query) directives inlinedSelSet
E.parseGraphQLQuery nullInNonNullableVariables graphQLContext varDefs (GH._grVariables query) directives inlinedSelSet
-- TODO: validate directives here
encJFromList
<$> for (InsOrdHashMap.toList unpreparedQueries) (uncurry (explainQueryField agentLicenseKey userInfo reqHeaders (_unOperationName <$> _grOperationName query)))
@ -120,6 +122,7 @@ explainGQLQuery sc agentLicenseKey reqHeaders (GQLExplain query userVarsRaw mayb
G.TypedOperationDefinition G.OperationTypeSubscription _ varDefs directives inlinedSelSet -> do
(_normalizedDirectives, normalizedSelectionSet) <-
ER.resolveVariables
nullInNonNullableVariables
varDefs
(fromMaybe mempty (GH._grVariables query))
directives

View File

@ -253,7 +253,7 @@ buildSchemaOptions ::
HashSet ExperimentalFeature ->
SchemaOptions
buildSchemaOptions
( SQLGenCtx stringifyNum dangerousBooleanCollapse remoteNullForwardingPolicy optimizePermissionFilters bigqueryStringNumericInput,
( SQLGenCtx stringifyNum dangerousBooleanCollapse _nullInNonNullableVariables remoteNullForwardingPolicy optimizePermissionFilters bigqueryStringNumericInput,
functionPermsCtx
)
expFeatures =

View File

@ -419,8 +419,8 @@ websocketConnectionReaper getLatestConfig getSchemaCache ws@(WSServer _ userConf
-- The bigqueryStringNumericInput of SQLGenCtx is built from the experimentalFeature, hence no need to check for this field
-- in experimentalFeatures again.
hasBigqueryStringNumericInputChanged = bigqueryStringNumericInput currSqlGenCtx /= bigqueryStringNumericInput prevSqlGenCtx
hasHideAggregationPredicatesChanged = (EFHideAggregationPredicates `elem` currExperimentalFeatures) && (EFHideAggregationPredicates `elem` prevExperimentalFeatures)
hasHideStreamFieldsChanged = (EFHideStreamFields `elem` currExperimentalFeatures) && (EFHideStreamFields `elem` prevExperimentalFeatures)
hasHideAggregationPredicatesChanged = (EFHideAggregationPredicates `elem` currExperimentalFeatures) /= (EFHideAggregationPredicates `elem` prevExperimentalFeatures)
hasHideStreamFieldsChanged = (EFHideStreamFields `elem` currExperimentalFeatures) /= (EFHideStreamFields `elem` prevExperimentalFeatures)
hasDefaultNamingCaseChanged = hasNamingConventionChanged (prevExperimentalFeatures, prevDefaultNamingCase) (currExperimentalFeatures, currDefaultNamingCase)
if
-- if CORS policy has changed, close all connections

View File

@ -301,6 +301,7 @@ isSystemDefined = unSystemDefined
data SQLGenCtx = SQLGenCtx
{ stringifyNum :: Options.StringifyNumbers,
dangerousBooleanCollapse :: Options.DangerouslyCollapseBooleans,
nullInNonNullableVariables :: Options.BackwardsCompatibleNullInNonNullableVariables,
remoteNullForwardingPolicy :: Options.RemoteNullForwardingPolicy,
optimizePermissionFilters :: Options.OptimizePermissionFilters,
bigqueryStringNumericInput :: Options.BigQueryStringNumericInput

View File

@ -4,6 +4,7 @@ module Hasura.RQL.Types.Schema.Options
( SchemaOptions (..),
StringifyNumbers (..),
DangerouslyCollapseBooleans (..),
BackwardsCompatibleNullInNonNullableVariables (..),
RemoteNullForwardingPolicy (..),
InferFunctionPermissions (..),
RemoteSchemaPermissions (..),
@ -89,6 +90,27 @@ instance ToJSON DangerouslyCollapseBooleans where
DangerouslyCollapseBooleans -> Bool True
Don'tDangerouslyCollapseBooleans -> Bool False
-- | Should `null` values allowed for variables whose type is declared
-- as non-nullable in a GraphQL query.
-- Until version 2.34.0 (except 2.11.11), `null` value is validated for
-- non-nullable variables. It is being fixed, to keep backwards compatible
-- this option is introduced.
data BackwardsCompatibleNullInNonNullableVariables
= AllowNullInNonNullableVariables
| Don'tAllowNullInNonNullableVariables
deriving (Eq, Show)
instance FromJSON BackwardsCompatibleNullInNonNullableVariables where
parseJSON =
withBool "BackwardsCompatibleNullInNonNullableVariables"
$ pure
. bool Don'tAllowNullInNonNullableVariables AllowNullInNonNullableVariables
instance ToJSON BackwardsCompatibleNullInNonNullableVariables where
toJSON = \case
AllowNullInNonNullableVariables -> Bool True
Don'tAllowNullInNonNullableVariables -> Bool False
data RemoteNullForwardingPolicy
= RemoteForwardAccurately
| RemoteOnlyForwardNonNull

View File

@ -79,6 +79,7 @@ import Hasura.RQL.DDL.EventTrigger (MonadEventLogCleanup)
import Hasura.RQL.DDL.Schema
import Hasura.RQL.DDL.Schema.Cache.Config
import Hasura.RQL.Types.BackendType
import Hasura.RQL.Types.Common (SQLGenCtx (nullInNonNullableVariables))
import Hasura.RQL.Types.Endpoint as EP
import Hasura.RQL.Types.OpenTelemetry (getOtelTracesPropagator)
import Hasura.RQL.Types.Roles (adminRoleName, roleNameToTxt)
@ -648,7 +649,8 @@ gqlExplainHandler query = do
schemaCache <- asks hcSchemaCache
reqHeaders <- asks hcReqHeaders
licenseKeyCache <- asks hcLicenseKeyCache
res <- GE.explainGQLQuery (lastBuiltSchemaCache schemaCache) licenseKeyCache reqHeaders query
nullInNonNullableVariables <- asks (nullInNonNullableVariables . acSQLGenCtx . hcAppContext)
res <- GE.explainGQLQuery nullInNonNullableVariables (lastBuiltSchemaCache schemaCache) licenseKeyCache reqHeaders query
return $ HttpResponse res []
v1Alpha1PGDumpHandler :: (MonadIO m, MonadError QErr m, MonadReader HandlerCtx m) => PGD.PGDumpReqBody -> m APIResp

View File

@ -169,6 +169,7 @@ mkServeOptions sor@ServeOptionsRaw {..} = do
Options.Don'tStringifyNumbers -> withOptionDefault Nothing stringifyNumOption
stringifyNums -> pure stringifyNums
soDangerousBooleanCollapse <- withOptionDefault rsoDangerousBooleanCollapse dangerousBooleanCollapseOption
soBackwardsCompatibleNullInNonNullableVariables <- withOptionDefault rsoBackwardsCompatibleNullInNonNullableVariables backwardsCompatibleNullInNonNullableVariablesOption
soRemoteNullForwardingPolicy <- withOptionDefault rsoRemoteNullForwardingPolicy remoteNullForwardingPolicyOption
soEnabledAPIs <- withOptionDefault rsoEnabledAPIs enabledAPIsOption
soLiveQueryOpts <- do

View File

@ -31,6 +31,7 @@ module Hasura.Server.Init.Arg.Command.Serve
wsReadCookieOption,
stringifyNumOption,
dangerousBooleanCollapseOption,
backwardsCompatibleNullInNonNullableVariablesOption,
remoteNullForwardingPolicyOption,
enabledAPIsOption,
mxRefetchDelayOption,
@ -124,6 +125,7 @@ serveCommandParser =
<*> parseWsReadCookie
<*> parseStringifyNum
<*> parseDangerousBooleanCollapse
<*> parseBackwardsCompatibleNullInNonNullableVariables
<*> parseRemoteNullForwardingPolicy
<*> parseEnabledAPIs
<*> parseMxRefetchDelay
@ -638,6 +640,26 @@ dangerousBooleanCollapseOption =
<> " [DEPRECATED, WILL BE REMOVED SOON] (default: false)"
}
parseBackwardsCompatibleNullInNonNullableVariables :: Opt.Parser (Maybe Options.BackwardsCompatibleNullInNonNullableVariables)
parseBackwardsCompatibleNullInNonNullableVariables =
Opt.optional
$ Opt.option
(Opt.eitherReader Env.fromEnv)
( Opt.long "null-in-nonnullable-variables"
<> Opt.help (Config._helpMessage backwardsCompatibleNullInNonNullableVariablesOption)
)
backwardsCompatibleNullInNonNullableVariablesOption :: Config.Option Options.BackwardsCompatibleNullInNonNullableVariables
backwardsCompatibleNullInNonNullableVariablesOption =
Config.Option
{ Config._default = Options.Don'tAllowNullInNonNullableVariables,
Config._envVar = "HASURA_GRAPHQL_BACKWARDS_COMPAT_NULL_IN_NONNULLABLE_VARIABLES",
Config._helpMessage =
"Emulate unexpected behavior of allowing 'null' values for non-nullable variables"
<> " exists before v2.34.0."
<> " [DEPRECATED, WILL BE REMOVED SOON] (default: false)"
}
parseRemoteNullForwardingPolicy :: Opt.Parser (Maybe Options.RemoteNullForwardingPolicy)
parseRemoteNullForwardingPolicy =
fmap (bool Nothing (Just Options.RemoteOnlyForwardNonNull))

View File

@ -290,6 +290,7 @@ data ServeOptionsRaw impl = ServeOptionsRaw
rsoWsReadCookie :: WsReadCookieStatus,
rsoStringifyNum :: Schema.Options.StringifyNumbers,
rsoDangerousBooleanCollapse :: Maybe Schema.Options.DangerouslyCollapseBooleans,
rsoBackwardsCompatibleNullInNonNullableVariables :: Maybe Schema.Options.BackwardsCompatibleNullInNonNullableVariables,
rsoRemoteNullForwardingPolicy :: Maybe Schema.Options.RemoteNullForwardingPolicy,
rsoEnabledAPIs :: Maybe (HashSet API),
rsoMxRefetchInt :: Maybe Subscription.Options.RefetchInterval,
@ -596,6 +597,7 @@ data ServeOptions impl = ServeOptions
soEnableTelemetry :: TelemetryStatus,
soStringifyNum :: Schema.Options.StringifyNumbers,
soDangerousBooleanCollapse :: Schema.Options.DangerouslyCollapseBooleans,
soBackwardsCompatibleNullInNonNullableVariables :: Schema.Options.BackwardsCompatibleNullInNonNullableVariables,
soRemoteNullForwardingPolicy :: Schema.Options.RemoteNullForwardingPolicy,
soEnabledAPIs :: HashSet API,
soLiveQueryOpts :: Subscription.Options.LiveQueriesOptions,

View File

@ -253,6 +253,9 @@ instance FromEnv Options.RemoteSchemaPermissions where
instance FromEnv Options.DangerouslyCollapseBooleans where
fromEnv = fmap (bool Options.Don'tDangerouslyCollapseBooleans Options.DangerouslyCollapseBooleans) . fromEnv @Bool
instance FromEnv Options.BackwardsCompatibleNullInNonNullableVariables where
fromEnv = fmap (bool Options.Don'tAllowNullInNonNullableVariables Options.AllowNullInNonNullableVariables) . fromEnv @Bool
instance FromEnv Options.RemoteNullForwardingPolicy where
fromEnv = fmap (bool Options.RemoteForwardAccurately Options.RemoteOnlyForwardNonNull) . fromEnv @Bool

View File

@ -160,7 +160,7 @@ runQueryParser ::
HashMap.HashMap G.Name J.Value ->
any
runQueryParser parser (varDefs, selSet) vars = runIdentity . runError $ do
(_, resolvedSelSet) <- resolveVariables varDefs vars [] selSet
(_, resolvedSelSet) <- resolveVariables Options.Don'tAllowNullInNonNullableVariables varDefs vars [] selSet
field <- case resolvedSelSet of
[G.SelectionField f] -> pure f
_ -> error "expecting only one field in the query"

View File

@ -64,6 +64,7 @@ emptyServeOptionsRaw =
rsoWsReadCookie = UUT.WsReadCookieDisabled,
rsoStringifyNum = Options.Don'tStringifyNumbers,
rsoDangerousBooleanCollapse = Nothing,
rsoBackwardsCompatibleNullInNonNullableVariables = Nothing,
rsoRemoteNullForwardingPolicy = Nothing,
rsoEnabledAPIs = Nothing,
rsoMxRefetchInt = Nothing,
@ -627,6 +628,37 @@ mkServeOptionsSpec =
fmap UUT.soDangerousBooleanCollapse result `Hspec.shouldBe` Right Options.Don'tDangerouslyCollapseBooleans
Hspec.describe "soBackwardsCompatibleNullInNonNullableVariables" $ do
Hspec.it "Default == False" $ do
let -- Given
rawServeOptions = emptyServeOptionsRaw
-- When
env = []
-- Then
result = UUT.runWithEnv env (UUT.mkServeOptions @Hasura rawServeOptions)
fmap UUT.soBackwardsCompatibleNullInNonNullableVariables result `Hspec.shouldBe` Right (UUT._default UUT.backwardsCompatibleNullInNonNullableVariablesOption)
Hspec.it "Env > Nothing" $ do
let -- Given
rawServeOptions = emptyServeOptionsRaw
-- When
env = [(UUT._envVar UUT.backwardsCompatibleNullInNonNullableVariablesOption, "true")]
-- Then
result = UUT.runWithEnv env (UUT.mkServeOptions @Hasura rawServeOptions)
fmap UUT.soBackwardsCompatibleNullInNonNullableVariables result `Hspec.shouldBe` Right Options.AllowNullInNonNullableVariables
Hspec.it "Arg > Env" $ do
let -- Given
rawServeOptions = emptyServeOptionsRaw {UUT.rsoBackwardsCompatibleNullInNonNullableVariables = Just Options.Don'tAllowNullInNonNullableVariables}
-- When
env = [(UUT._envVar UUT.dangerousBooleanCollapseOption, "true")]
-- Then
result = UUT.runWithEnv env (UUT.mkServeOptions @Hasura rawServeOptions)
fmap UUT.soBackwardsCompatibleNullInNonNullableVariables result `Hspec.shouldBe` Right Options.Don'tAllowNullInNonNullableVariables
Hspec.describe "soEnabledAPIs" $ do
Hspec.it "Default == metadata,graphql,pgdump,config" $ do
let -- Given

View File

@ -62,6 +62,7 @@ serveOptions =
soEnableTelemetry = Init.TelemetryDisabled,
soStringifyNum = Options.Don'tStringifyNumbers,
soDangerousBooleanCollapse = Options.Don'tDangerouslyCollapseBooleans,
soBackwardsCompatibleNullInNonNullableVariables = Options.Don'tAllowNullInNonNullableVariables,
soRemoteNullForwardingPolicy = Options.RemoteForwardAccurately,
soEnabledAPIs = testSuiteEnabledApis,
soLiveQueryOpts = ES.mkSubscriptionsOptions Nothing Nothing,

View File

@ -106,6 +106,7 @@ main = do
SQLGenCtx
Options.Don'tStringifyNumbers
Options.Don'tDangerouslyCollapseBooleans
Options.Don'tAllowNullInNonNullableVariables
Options.RemoteForwardAccurately
Options.Don'tOptimizePermissionFilters
Options.EnableBigQueryStringNumericInput

View File

@ -19,8 +19,11 @@
url: /v1/graphql
status: 200
response:
data:
author: []
errors:
- extensions:
code: validation-failed
path: $
message: 'null value found for non-nullable type: "Int!"'
query:
variables:
limit: null
@ -45,7 +48,7 @@
variables:
author_id: null
query: |
mutation update_author($author_id: Int!) {
mutation update_author($author_id: Int) {
update_author(where: {id: {_eq: $author_id}}, _set: {name: ""}) {
returning {
id