server: transform enum with upper for graphql-default

PR-URL: https://github.com/hasura/graphql-engine-mono/pull/5032
GitOrigin-RevId: 206a673f4bd59700436f6160feeb7df415f637ad
This commit is contained in:
paritosh-08 2022-07-19 12:25:42 +05:30 committed by hasura-bot
parent 9e9dff763b
commit d66abcefab
42 changed files with 338 additions and 108 deletions

View File

@ -204,7 +204,7 @@ Please submit any feedback you may have for this feature at https://github.com/h
- server: fix prefix/suffix behaviour for `graphql-default` naming convention (fixes #8544)
- server: fix namespace visibility during introspection (fix #8434)
- server: Create missing SQL triggers, if any, while reloading metadata and startup.
- server: fix name transformation bug in `graphql-default` naming convention (fixes #8640 partially)
- server: fix name/enum transformation bugs in `graphql-default` naming convention (fixes #8640)
- server: changes to the Rest Endpoints OpenAPI specification:
- the nullability of items in the output is now always correctly reported
- scalars other than UUID are more consistently inlined

View File

@ -224,7 +224,8 @@ fromSelectRows parentSelectFromEntity annSelectG = do
{ _asnFields = fields,
_asnFrom = from,
_asnPerm = perm,
_asnArgs = args
_asnArgs = args,
_asnNamingConvention = _tCase
} = annSelectG
Ir.TablePerm {_tpLimit = mPermLimit, _tpFilter = permFilter} = perm
permissionBasedTop =
@ -518,7 +519,8 @@ fromSelectAggregate minnerJoinFields annSelectG = do
{ _asnFields = fields,
_asnFrom = from,
_asnPerm = perm,
_asnArgs = args
_asnArgs = args,
_asnNamingConvention = _tCase
} = annSelectG
Ir.TablePerm {_tpLimit = mPermLimit, _tpFilter = permFilter} = perm
permissionBasedTop =

View File

@ -439,7 +439,8 @@ bqComputedField sourceName ComputedFieldInfo {..} tableName tableInfo = runMaybe
IR._asnFrom = IR.FromFunction (_cffName _cfiFunction) functionArgs' Nothing,
IR._asnPerm = tablePermissionsInfo returnTablePermissions,
IR._asnArgs = args,
IR._asnStrfyNum = stringifyNumbers
IR._asnStrfyNum = stringifyNumbers,
IR._asnNamingConvention = Nothing
}
BigQuery.ReturnTableSchema returnFields -> do
-- Check if the computed field is available in the select permission
@ -465,7 +466,8 @@ bqComputedField sourceName ComputedFieldInfo {..} tableName tableInfo = runMaybe
IR._asnFrom = IR.FromFunction (_cffName _cfiFunction) functionArgs' Nothing,
IR._asnPerm = IR.noTablePermissions,
IR._asnArgs = IR.noSelectArgs,
IR._asnStrfyNum = stringifyNumbers
IR._asnStrfyNum = stringifyNumbers,
IR._asnNamingConvention = Nothing
}
where
fieldDescription :: Maybe G.Description

View File

@ -12,7 +12,7 @@ import Hasura.RQL.Types.Column qualified as IR
import Hasura.SQL.Backend
fromDelete :: IR.AnnDel 'MSSQL -> FromIr Delete
fromDelete (IR.AnnDel table (permFilter, whereClause) _ allColumns) = do
fromDelete (IR.AnnDel table (permFilter, whereClause) _ allColumns _) = do
tableAlias <- generateAlias (TableTemplate (tableName table))
runReaderT
( do

View File

@ -50,7 +50,7 @@ mkMutationOutputSelect stringifyNum withAlias = \case
IR.Fields (IR.AnnFieldG 'MSSQL Void Expression) ->
FromIr Select
mkSelect jsonAggSelect annFields = do
let annSelect = IR.AnnSelectG annFields (IR.FromIdentifier $ IR.FIIdentifier withAlias) IR.noTablePermissions IR.noSelectArgs stringifyNum
let annSelect = IR.AnnSelectG annFields (IR.FromIdentifier $ IR.FIIdentifier withAlias) IR.noTablePermissions IR.noSelectArgs stringifyNum Nothing
fromSelect jsonAggSelect annSelect
-- SELECT COUNT(*) AS "count" FROM [with_alias]

View File

@ -234,7 +234,8 @@ fromSelectRows annSelectG = do
{ _asnFields = fields,
_asnFrom = from,
_asnPerm = perm,
_asnArgs = args
_asnArgs = args,
_asnNamingConvention = _tCase
} = annSelectG
IR.TablePerm {_tpLimit = mPermLimit, _tpFilter = permFilter} = perm
permissionBasedTop =
@ -329,7 +330,8 @@ fromSelectAggregate
{ _asnFields = (zip [0 ..] -> fields),
_asnFrom = from,
_asnPerm = IR.TablePerm {_tpLimit = (maybe NoTop Top -> permissionBasedTop), _tpFilter = permFilter},
_asnArgs = args
_asnArgs = args,
_asnNamingConvention = _tCase
} =
do
selectFrom <- case from of

View File

@ -20,7 +20,7 @@ import Hasura.RQL.Types.Column qualified as IR
import Hasura.SQL.Backend
fromUpdate :: IR.AnnotatedUpdate 'MSSQL -> FromIr Update
fromUpdate (IR.AnnotatedUpdateG table (permFilter, whereClause) _ backendUpdate _ allColumns) = do
fromUpdate (IR.AnnotatedUpdateG table (permFilter, whereClause) _ backendUpdate _ allColumns _tCase) = do
tableAlias <- generateAlias (TableTemplate (tableName table))
runReaderT
( do

View File

@ -545,7 +545,8 @@ fromSelectAggregate mparentRelationship annSelectG = do
_asnFrom = from,
_asnPerm = perm,
_asnArgs = args,
_asnStrfyNum = _num
_asnStrfyNum = _num,
_asnNamingConvention = _tCase
} = annSelectG
IR.TablePerm {_tpLimit = mPermLimit, _tpFilter = permFilter} = perm
@ -731,7 +732,8 @@ fromSelectRows annSelectG = do
{ _asnFields = fields,
_asnFrom = from,
_asnPerm = perm,
_asnArgs = args
_asnArgs = args,
_asnNamingConvention = _tCase
} = annSelectG
IR.TablePerm {_tpLimit = mPermLimit, _tpFilter = permFilter} = perm

View File

@ -688,7 +688,7 @@ mkTriggerFunctionQ triggerName (QualifiedObject schema table) allCols op (Subscr
mkRowExp $ map (\col -> toExtractor (mkQId opVar strfyNum col) col) columns
mkQId opVar strfyNum colInfo =
toJSONableExp strfyNum (ciType colInfo) False $
toJSONableExp strfyNum (ciType colInfo) False Nothing $
SEQIdentifier $ QIdentifier (opToQual opVar) $ toIdentifier $ ciColumn colInfo
-- Generate the SQL expression

View File

@ -29,6 +29,7 @@ import Hasura.Backends.Postgres.Translate.Select (PostgresAnnotatedFieldJSON)
import Hasura.Backends.Postgres.Types.Insert
import Hasura.Base.Error
import Hasura.EncJSON
import Hasura.GraphQL.Schema.NamingCase (NamingCase)
import Hasura.GraphQL.Schema.Options qualified as Options
import Hasura.Prelude
import Hasura.QueryTags
@ -56,13 +57,14 @@ convertToSQLTransaction ::
UserInfo ->
Seq.Seq Q.PrepArg ->
Options.StringifyNumbers ->
Maybe NamingCase ->
m EncJSON
convertToSQLTransaction (IR.AnnotatedInsert fieldName isSingle annIns mutationOutput) userInfo planVars stringifyNum =
convertToSQLTransaction (IR.AnnotatedInsert fieldName isSingle annIns mutationOutput _tCase) userInfo planVars stringifyNum tCase =
if null $ IR._aiInsertObject annIns
then pure $ IR.buildEmptyMutResp mutationOutput
else
withPaths ["selectionSet", fieldName, "args", suffix] $
insertMultipleObjects annIns mempty userInfo mutationOutput planVars stringifyNum
insertMultipleObjects annIns mempty userInfo mutationOutput planVars stringifyNum tCase
where
withPaths p x = foldr ($) x $ withPathK <$> p
suffix = bool "objects" "object" isSingle
@ -82,8 +84,9 @@ insertMultipleObjects ::
IR.MutationOutput ('Postgres pgKind) ->
Seq.Seq Q.PrepArg ->
Options.StringifyNumbers ->
Maybe NamingCase ->
m EncJSON
insertMultipleObjects multiObjIns additionalColumns userInfo mutationOutput planVars stringifyNum =
insertMultipleObjects multiObjIns additionalColumns userInfo mutationOutput planVars stringifyNum tCase =
bool withoutRelsInsert withRelsInsert anyRelsToInsert
where
IR.AnnotatedInsertData insObjs table checkCondition columnInfos presetRow (BackendInsert conflictClause) = multiObjIns
@ -108,12 +111,12 @@ insertMultipleObjects multiObjIns additionalColumns userInfo mutationOutput plan
rowCount = tshow . length $ IR._aiInsertObject multiObjIns
Tracing.trace ("Insert (" <> rowCount <> ") " <> qualifiedObjectToText table) do
Tracing.attachMetadata [("count", rowCount)]
PGE.execInsertQuery stringifyNum userInfo (insertQuery, planVars)
PGE.execInsertQuery stringifyNum tCase userInfo (insertQuery, planVars)
withRelsInsert = do
insertRequests <- indexedForM insObjs \obj -> do
let singleObj = IR.AnnotatedInsertData (IR.Single obj) table checkCondition columnInfos presetRow (BackendInsert conflictClause)
insertObject singleObj additionalColumns userInfo planVars stringifyNum
insertObject singleObj additionalColumns userInfo planVars stringifyNum tCase
let affectedRows = sum $ map fst insertRequests
columnValues = mapMaybe snd insertRequests
selectExpr <- PGT.mkSelectExpFromColumnValues table columnInfos columnValues
@ -124,6 +127,7 @@ insertMultipleObjects multiObjIns additionalColumns userInfo mutationOutput plan
(PGT.MCSelectValues selectExpr)
mutationOutput
stringifyNum
tCase
[]
insertObject ::
@ -140,12 +144,13 @@ insertObject ::
UserInfo ->
Seq.Seq Q.PrepArg ->
Options.StringifyNumbers ->
Maybe NamingCase ->
m (Int, Maybe (ColumnValues ('Postgres pgKind) TxtEncodedVal))
insertObject singleObjIns additionalColumns userInfo planVars stringifyNum = Tracing.trace ("Insert " <> qualifiedObjectToText table) do
insertObject singleObjIns additionalColumns userInfo planVars stringifyNum tCase = Tracing.trace ("Insert " <> qualifiedObjectToText table) do
validateInsert (Map.keys columns) (map IR._riRelationInfo objectRels) (Map.keys additionalColumns)
-- insert all object relations and fetch this insert dependent column values
objInsRes <- forM beforeInsert $ insertObjRel planVars userInfo stringifyNum
objInsRes <- forM beforeInsert $ insertObjRel planVars userInfo stringifyNum tCase
-- prepare final insert columns
let objRelAffRows = sum $ map fst objInsRes
@ -156,7 +161,7 @@ insertObject singleObjIns additionalColumns userInfo planVars stringifyNum = Tra
PGE.MutateResp affRows colVals <-
liftTx $
PGE.mutateAndFetchCols @pgKind table allColumns (PGT.MCCheckConstraint cte, planVars) stringifyNum
PGE.mutateAndFetchCols @pgKind table allColumns (PGT.MCCheckConstraint cte, planVars) stringifyNum tCase
colValM <- asSingleObject colVals
arrRelAffRows <- bool (withArrRels colValM) (return 0) $ null allAfterInsertRels
@ -195,7 +200,7 @@ insertObject singleObjIns additionalColumns userInfo planVars stringifyNum = Tra
afterInsertDepColsWithVal <- fetchFromColVals colVal afterInsertDepCols
arrInsARows <-
forM allAfterInsertRels $
insertArrRel afterInsertDepColsWithVal userInfo planVars stringifyNum
insertArrRel afterInsertDepColsWithVal userInfo planVars stringifyNum tCase
return $ sum arrInsARows
asSingleObject ::
@ -223,11 +228,12 @@ insertObjRel ::
Seq.Seq Q.PrepArg ->
UserInfo ->
Options.StringifyNumbers ->
Maybe NamingCase ->
IR.ObjectRelationInsert ('Postgres pgKind) PG.SQLExp ->
m (Int, [(PGCol, PG.SQLExp)])
insertObjRel planVars userInfo stringifyNum objRelIns =
insertObjRel planVars userInfo stringifyNum tCase objRelIns =
withPathK (relNameToTxt relName) $ do
(affRows, colValM) <- withPathK "data" $ insertObject singleObjIns mempty userInfo planVars stringifyNum
(affRows, colValM) <- withPathK "data" $ insertObject singleObjIns mempty userInfo planVars stringifyNum tCase
colVal <- onNothing colValM $ throw400 NotSupported errMsg
retColsWithVals <- fetchFromColVals colVal rColInfos
let columns = flip mapMaybe (Map.toList mapCols) \(column, target) -> do
@ -259,9 +265,10 @@ insertArrRel ::
UserInfo ->
Seq.Seq Q.PrepArg ->
Options.StringifyNumbers ->
Maybe NamingCase ->
IR.ArrayRelationInsert ('Postgres pgKind) PG.SQLExp ->
m Int
insertArrRel resCols userInfo planVars stringifyNum arrRelIns =
insertArrRel resCols userInfo planVars stringifyNum tCase arrRelIns =
withPathK (relNameToTxt $ riName relInfo) $ do
let additionalColumns = Map.fromList $
flip mapMaybe resCols \(column, value) -> do
@ -269,7 +276,7 @@ insertArrRel resCols userInfo planVars stringifyNum arrRelIns =
Just (target, value)
resBS <-
withPathK "data" $
insertMultipleObjects multiObjIns additionalColumns userInfo mutOutput planVars stringifyNum
insertMultipleObjects multiObjIns additionalColumns userInfo mutOutput planVars stringifyNum tCase
resObj <- decodeEncJSON resBS
onNothing (Map.lookup ("affected_rows" :: Text) resObj) $
throw500 "affected_rows not returned in array rel insert"

View File

@ -31,6 +31,7 @@ import Hasura.Backends.Postgres.Translate.Select
import Hasura.Backends.Postgres.Translate.Update
import Hasura.Base.Error
import Hasura.EncJSON
import Hasura.GraphQL.Schema.NamingCase (NamingCase)
import Hasura.GraphQL.Schema.Options qualified as Options
import Hasura.Prelude
import Hasura.QueryTags
@ -68,7 +69,8 @@ data Mutation (b :: BackendType) = Mutation
_mQuery :: !(MutationCTE, DS.Seq Q.PrepArg),
_mOutput :: !(MutationOutput b),
_mCols :: ![ColumnInfo b],
_mStrfyNum :: !Options.StringifyNumbers
_mStrfyNum :: !Options.StringifyNumbers,
_mNamingConvention :: !(Maybe NamingCase)
}
mkMutation ::
@ -78,9 +80,10 @@ mkMutation ::
MutationOutput ('Postgres pgKind) ->
[ColumnInfo ('Postgres pgKind)] ->
Options.StringifyNumbers ->
Maybe NamingCase ->
Mutation ('Postgres pgKind)
mkMutation _userInfo table query output allCols strfyNum =
Mutation table query output allCols strfyNum
mkMutation _userInfo table query output allCols strfyNum tCase =
Mutation table query output allCols strfyNum tCase
runMutation ::
( MonadTx m,
@ -102,8 +105,8 @@ mutateAndReturn ::
) =>
Mutation ('Postgres pgKind) ->
m EncJSON
mutateAndReturn (Mutation qt (cte, p) mutationOutput allCols strfyNum) =
executeMutationOutputQuery qt allCols Nothing cte mutationOutput strfyNum (toList p)
mutateAndReturn (Mutation qt (cte, p) mutationOutput allCols strfyNum tCase) =
executeMutationOutputQuery qt allCols Nothing cte mutationOutput strfyNum tCase (toList p)
execUpdateQuery ::
forall pgKind m.
@ -113,10 +116,11 @@ execUpdateQuery ::
MonadReader QueryTagsComment m
) =>
Options.StringifyNumbers ->
Maybe NamingCase ->
UserInfo ->
(AnnotatedUpdate ('Postgres pgKind), DS.Seq Q.PrepArg) ->
m EncJSON
execUpdateQuery strfyNum userInfo (u, p) =
execUpdateQuery strfyNum tCase userInfo (u, p) =
case updateCTE of
Update singleUpdate -> runCTE singleUpdate
MultiUpdate ctes -> encJFromList <$> traverse runCTE ctes
@ -127,7 +131,7 @@ execUpdateQuery strfyNum userInfo (u, p) =
runCTE :: S.TopLevelCTE -> m EncJSON
runCTE cte =
runMutation
(mkMutation userInfo (_auTable u) (MCCheckConstraint cte, p) (_auOutput u) (_auAllCols u) strfyNum)
(mkMutation userInfo (_auTable u) (MCCheckConstraint cte, p) (_auOutput u) (_auAllCols u) strfyNum tCase)
execDeleteQuery ::
forall pgKind m.
@ -137,12 +141,13 @@ execDeleteQuery ::
MonadReader QueryTagsComment m
) =>
Options.StringifyNumbers ->
Maybe NamingCase ->
UserInfo ->
(AnnDel ('Postgres pgKind), DS.Seq Q.PrepArg) ->
m EncJSON
execDeleteQuery strfyNum userInfo (u, p) =
execDeleteQuery strfyNum tCase userInfo (u, p) =
runMutation
(mkMutation userInfo (_adTable u) (MCDelete delete, p) (_adOutput u) (_adAllCols u) strfyNum)
(mkMutation userInfo (_adTable u) (MCDelete delete, p) (_adOutput u) (_adAllCols u) strfyNum tCase)
where
delete = mkDelete u
@ -153,12 +158,13 @@ execInsertQuery ::
MonadReader QueryTagsComment m
) =>
Options.StringifyNumbers ->
Maybe NamingCase ->
UserInfo ->
(InsertQueryP1 ('Postgres pgKind), DS.Seq Q.PrepArg) ->
m EncJSON
execInsertQuery strfyNum userInfo (u, p) =
execInsertQuery strfyNum tCase userInfo (u, p) =
runMutation
(mkMutation userInfo (iqp1Table u) (MCCheckConstraint insertCTE, p) (iqp1Output u) (iqp1AllCols u) strfyNum)
(mkMutation userInfo (iqp1Table u) (MCCheckConstraint insertCTE, p) (iqp1Output u) (iqp1AllCols u) strfyNum tCase)
where
insertCTE = mkInsertCTE u
@ -185,9 +191,9 @@ mutateAndSel ::
) =>
Mutation ('Postgres pgKind) ->
m EncJSON
mutateAndSel (Mutation qt q mutationOutput allCols strfyNum) = do
mutateAndSel (Mutation qt q mutationOutput allCols strfyNum tCase) = do
-- Perform mutation and fetch unique columns
MutateResp _ columnVals <- liftTx $ mutateAndFetchCols qt allCols q strfyNum
MutateResp _ columnVals <- liftTx $ mutateAndFetchCols qt allCols q strfyNum tCase
select <- mkSelectExpFromColumnValues qt allCols columnVals
-- Perform select query and fetch returning fields
executeMutationOutputQuery
@ -197,6 +203,7 @@ mutateAndSel (Mutation qt q mutationOutput allCols strfyNum) = do
(MCSelectValues select)
mutationOutput
strfyNum
tCase
[]
withCheckPermission :: (MonadError QErr m) => m (a, Bool) -> m a
@ -220,14 +227,15 @@ executeMutationOutputQuery ::
MutationCTE ->
MutationOutput ('Postgres pgKind) ->
Options.StringifyNumbers ->
Maybe NamingCase ->
-- | Prepared params
[Q.PrepArg] ->
m EncJSON
executeMutationOutputQuery qt allCols preCalAffRows cte mutOutput strfyNum prepArgs = do
executeMutationOutputQuery qt allCols preCalAffRows cte mutOutput strfyNum tCase prepArgs = do
queryTags <- ask
let queryTx :: Q.FromRes a => m a
queryTx = do
let selectWith = mkMutationOutputExp qt allCols preCalAffRows cte mutOutput strfyNum
let selectWith = mkMutationOutputExp qt allCols preCalAffRows cte mutOutput strfyNum tCase
query = Q.fromBuilder $ toSQL selectWith
queryWithQueryTags = query {Q.getQueryText = (Q.getQueryText query) <> (_unQueryTagsComment queryTags)}
-- See Note [Prepared statements in Mutations]
@ -244,8 +252,9 @@ mutateAndFetchCols ::
[ColumnInfo ('Postgres pgKind)] ->
(MutationCTE, DS.Seq Q.PrepArg) ->
Options.StringifyNumbers ->
Maybe NamingCase ->
Q.TxE QErr (MutateResp ('Postgres pgKind) TxtEncodedVal)
mutateAndFetchCols qt cols (cte, p) strfyNum = do
mutateAndFetchCols qt cols (cte, p) strfyNum tCase = do
let mutationTx :: Q.FromRes a => Q.TxE QErr a
mutationTx =
-- See Note [Prepared statements in Mutations]
@ -288,4 +297,4 @@ mutateAndFetchCols qt cols (cte, p) strfyNum = do
colSel =
S.SESelect $
mkSQLSelect JASMultipleRows $
AnnSelectG selFlds tabFrom tabPerm noSelectArgs strfyNum
AnnSelectG selFlds tabFrom tabPerm noSelectArgs strfyNum tCase

View File

@ -202,7 +202,7 @@ convertDelete ::
convertDelete userInfo deleteOperation stringifyNum = do
queryTags <- ask
preparedDelete <- traverse (prepareWithoutPlan userInfo) deleteOperation
pure $ flip runReaderT queryTags $ PGE.execDeleteQuery stringifyNum userInfo (preparedDelete, Seq.empty)
pure $ flip runReaderT queryTags $ PGE.execDeleteQuery stringifyNum (_adNamingConvention deleteOperation) userInfo (preparedDelete, Seq.empty)
convertUpdate ::
forall pgKind m.
@ -223,7 +223,7 @@ convertUpdate userInfo updateOperation stringifyNum = do
else
pure $
flip runReaderT queryTags $
PGE.execUpdateQuery stringifyNum userInfo (preparedUpdate, Seq.empty)
PGE.execUpdateQuery stringifyNum (_auNamingConvention updateOperation) userInfo (preparedUpdate, Seq.empty)
convertInsert ::
forall pgKind m.
@ -239,7 +239,7 @@ convertInsert ::
convertInsert userInfo insertOperation stringifyNum = do
queryTags <- ask
preparedInsert <- traverse (prepareWithoutPlan userInfo) insertOperation
pure $ flip runReaderT queryTags $ convertToSQLTransaction preparedInsert userInfo Seq.empty stringifyNum
pure $ flip runReaderT queryTags $ convertToSQLTransaction preparedInsert userInfo Seq.empty stringifyNum (_aiNamingConvention insertOperation)
-- | A pared-down version of 'Query.convertQuerySelSet', for use in execution of
-- special case of SQL function mutations (see 'MDBFunction').

View File

@ -290,7 +290,7 @@ updateTableMany scenario sourceInfo tableInfo gqlName = runMaybeT do
let argsParser = liftA2 (,) updates (pure annBoolExpTrue)
pure $
P.subselection updateName updateDesc argsParser selection
<&> SU.mkUpdateObject tableName columns updatePerms . fmap MOutMultirowFields
<&> SU.mkUpdateObject tableName columns updatePerms (Just tCase) . fmap MOutMultirowFields
where
tableName = tableInfoName tableInfo
defaultUpdateDesc = "update multiples rows of table: " <>> tableName

View File

@ -51,6 +51,7 @@ module Hasura.Backends.Postgres.SQL.DML
applyJsonBuildArray,
applyJsonBuildObj,
applyRowToJson,
applyUppercase,
boolTypeAnn,
buildUpsertSetExp,
columnDefaultValue,
@ -618,6 +619,10 @@ applyRowToJson :: [Extractor] -> SQLExp
applyRowToJson extrs =
SEFnApp "row_to_json" [mkRowExp extrs] Nothing
applyUppercase :: SQLExp -> SQLExp
applyUppercase arg =
SEFnApp "upper" [arg] Nothing
mkExtr :: (IsIdentifier a) => a -> Extractor
mkExtr t = Extractor (mkSIdenExp t) Nothing

View File

@ -12,6 +12,7 @@ module Hasura.Backends.Postgres.Schema.Select
where
import Control.Lens hiding (index)
import Data.Has (getter)
import Data.HashMap.Strict.Extended qualified as Map
import Data.Sequence qualified as Seq
import Data.Text.Extended
@ -61,6 +62,7 @@ selectFunction ::
Maybe G.Description ->
m (Maybe (FieldParser n (SelectExp ('Postgres pgKind))))
selectFunction sourceInfo fi@FunctionInfo {..} description = runMaybeT do
tCase <- asks getter
tableInfo <- lift $ askTableInfo sourceInfo _fiReturnType
selectPermissions <- MaybeT $ tableSelectPermissions tableInfo
selectionSetParser <- MaybeT $ returnFunctionParser sourceInfo tableInfo
@ -78,7 +80,8 @@ selectFunction sourceInfo fi@FunctionInfo {..} description = runMaybeT do
IR._asnFrom = IR.FromFunction _fiSQLName funcArgs Nothing,
IR._asnPerm = tablePermissionsInfo selectPermissions,
IR._asnArgs = tableArgs',
IR._asnStrfyNum = stringifyNumbers
IR._asnStrfyNum = stringifyNumbers,
IR._asnNamingConvention = Just tCase
}
where
returnFunctionParser =
@ -98,6 +101,7 @@ selectFunctionAggregate ::
Maybe G.Description ->
m (Maybe (FieldParser n (AggSelectExp ('Postgres pgKind))))
selectFunctionAggregate sourceInfo fi@FunctionInfo {..} description = runMaybeT do
tCase <- asks getter
targetTableInfo <- askTableInfo sourceInfo _fiReturnType
selectPermissions <- MaybeT $ tableSelectPermissions targetTableInfo
guard $ spiAllowAgg selectPermissions
@ -130,7 +134,8 @@ selectFunctionAggregate sourceInfo fi@FunctionInfo {..} description = runMaybeT
IR._asnFrom = IR.FromFunction _fiSQLName funcArgs Nothing,
IR._asnPerm = tablePermissionsInfo selectPermissions,
IR._asnArgs = tableArgs',
IR._asnStrfyNum = stringifyNumbers
IR._asnStrfyNum = stringifyNumbers,
IR._asnNamingConvention = Just tCase
}
selectFunctionConnection ::
@ -148,6 +153,7 @@ selectFunctionConnection ::
PrimaryKeyColumns ('Postgres pgKind) ->
m (Maybe (FieldParser n (ConnectionSelectExp ('Postgres pgKind))))
selectFunctionConnection sourceInfo fi@FunctionInfo {..} description pkeyColumns = runMaybeT do
tCase <- asks getter
returnTableInfo <- lift $ askTableInfo sourceInfo _fiReturnType
selectPermissions <- MaybeT $ tableSelectPermissions returnTableInfo
xRelayInfo <- hoistMaybe $ relayExtension @('Postgres pgKind)
@ -173,7 +179,8 @@ selectFunctionConnection sourceInfo fi@FunctionInfo {..} description pkeyColumns
IR._asnFrom = IR.FromFunction _fiSQLName funcArgs Nothing,
IR._asnPerm = tablePermissionsInfo selectPermissions,
IR._asnArgs = args,
IR._asnStrfyNum = stringifyNumbers
IR._asnStrfyNum = stringifyNumbers,
IR._asnNamingConvention = Just tCase
}
}
@ -188,6 +195,7 @@ computedFieldPG ::
TableInfo ('Postgres pgKind) ->
m (Maybe (FieldParser n (AnnotatedField ('Postgres pgKind))))
computedFieldPG sourceInfo ComputedFieldInfo {..} parentTable tableInfo = runMaybeT do
tCase <- asks getter
selectPermissions <- MaybeT $ tableSelectPermissions tableInfo
stringifyNumbers <- retrieve Options.soStringifyNumbers
fieldName <- lift $ textToName $ computedFieldNameToText _cfiName
@ -233,7 +241,8 @@ computedFieldPG sourceInfo ComputedFieldInfo {..} parentTable tableInfo = runMay
IR._asnFrom = IR.FromFunction (_cffName _cfiFunction) functionArgs' Nothing,
IR._asnPerm = tablePermissionsInfo remotePerms,
IR._asnArgs = args,
IR._asnStrfyNum = stringifyNumbers
IR._asnStrfyNum = stringifyNumbers,
IR._asnNamingConvention = Just tCase
}
where
fieldDescription :: Maybe G.Description

View File

@ -11,6 +11,7 @@ import Hasura.Backends.Postgres.SQL.DML
import Hasura.Backends.Postgres.SQL.Types
import Hasura.Backends.Postgres.SQL.Value
import Hasura.Backends.Postgres.Types.Column
import Hasura.GraphQL.Schema.NamingCase
import Hasura.GraphQL.Schema.Options qualified as Options
import Hasura.Prelude
import Hasura.RQL.Types.Column
@ -23,8 +24,8 @@ toTxtValue ColumnValue {..} =
ty = unsafePGColumnToBackend cvType
-- | Formats each columns to appropriate SQL expression
toJSONableExp :: Options.StringifyNumbers -> ColumnType ('Postgres pgKind) -> Bool -> SQLExp -> SQLExp
toJSONableExp stringifyNum colType asText expression
toJSONableExp :: Options.StringifyNumbers -> ColumnType ('Postgres pgKind) -> Bool -> Maybe NamingCase -> SQLExp -> SQLExp
toJSONableExp stringifyNum colType asText tCase expression
-- If it's a numeric column greater than a 32-bit integer, we have to stringify it as JSON spec doesn't support >32-bit integers
| asText || (isScalarColumnWhere isBigNum colType && (case stringifyNum of Options.StringifyNumbers -> True; Options.Don'tStringifyNumbers -> False)) =
expression `SETyAnn` textTypeAnn
@ -38,4 +39,5 @@ toJSONableExp stringifyNum colType asText expression
]
Nothing
`SETyAnn` jsonTypeAnn
| isEnumColumn colType && any isGraphqlCase tCase = applyUppercase expression
| otherwise = expression

View File

@ -20,7 +20,7 @@ mkDelete ::
Backend ('Postgres pgKind) =>
AnnDel ('Postgres pgKind) ->
S.SQLDelete
mkDelete (AnnDel tn (fltr, wc) _ _) =
mkDelete (AnnDel tn (fltr, wc) _ _ _) =
S.SQLDelete tn Nothing tableFltr $ Just S.returningStar
where
tableFltr =

View File

@ -18,6 +18,7 @@ import Data.Coerce
import Hasura.Backends.Postgres.SQL.DML qualified as S
import Hasura.Backends.Postgres.SQL.Types
import Hasura.Backends.Postgres.Translate.Select
import Hasura.GraphQL.Schema.NamingCase (NamingCase)
import Hasura.GraphQL.Schema.Options qualified as Options
import Hasura.Prelude
import Hasura.RQL.IR.BoolExp
@ -85,9 +86,10 @@ mkMutFldExp ::
Identifier ->
Maybe Int ->
Options.StringifyNumbers ->
Maybe NamingCase ->
MutFld ('Postgres pgKind) ->
S.SQLExp
mkMutFldExp cteAlias preCalAffRows strfyNum = \case
mkMutFldExp cteAlias preCalAffRows strfyNum tCase = \case
MCount ->
let countExp =
S.SESelect $
@ -102,7 +104,7 @@ mkMutFldExp cteAlias preCalAffRows strfyNum = \case
tabPerm = TablePerm annBoolExpTrue Nothing
in S.SESelect $
mkSQLSelect JASMultipleRows $
AnnSelectG selFlds tabFrom tabPerm noSelectArgs strfyNum
AnnSelectG selFlds tabFrom tabPerm noSelectArgs strfyNum tCase
toFIIdentifier :: Identifier -> FIIdentifier
toFIIdentifier = coerce . getIdenTxt
@ -143,8 +145,9 @@ mkMutationOutputExp ::
MutationCTE ->
MutationOutput ('Postgres pgKind) ->
Options.StringifyNumbers ->
Maybe NamingCase ->
S.SelectWith
mkMutationOutputExp qt allCols preCalAffRows cte mutOutput strfyNum =
mkMutationOutputExp qt allCols preCalAffRows cte mutOutput strfyNum tCase =
S.SelectWith
[ (S.toTableAlias mutationResultAlias, getMutationCTE cte),
(S.toTableAlias allColumnsAlias, allColumnsSelect)
@ -173,7 +176,7 @@ mkMutationOutputExp qt allCols preCalAffRows cte mutOutput strfyNum =
let jsonBuildObjArgs = flip concatMap mutFlds $
\(FieldName k, mutFld) ->
[ S.SELit k,
mkMutFldExp allColumnsAlias preCalAffRows strfyNum mutFld
mkMutFldExp allColumnsAlias preCalAffRows strfyNum tCase mutFld
]
in S.SEFnApp "json_build_object" jsonBuildObjArgs Nothing
MOutSinglerowObject annFlds ->
@ -181,7 +184,7 @@ mkMutationOutputExp qt allCols preCalAffRows cte mutOutput strfyNum =
tabPerm = TablePerm annBoolExpTrue Nothing
in S.SESelect $
mkSQLSelect JASSingleObject $
AnnSelectG annFlds tabFrom tabPerm noSelectArgs strfyNum
AnnSelectG annFlds tabFrom tabPerm noSelectArgs strfyNum tCase
mkCheckErrorExp :: IsIdentifier a => a -> S.SQLExp
mkCheckErrorExp alias =

View File

@ -75,6 +75,7 @@ import Hasura.Backends.Postgres.Translate.Select.Internal.JoinTree
)
import Hasura.Backends.Postgres.Translate.Select.Internal.OrderBy (processOrderByItems)
import Hasura.Backends.Postgres.Translate.Types
import Hasura.GraphQL.Schema.NamingCase (NamingCase)
import Hasura.GraphQL.Schema.Node (currentNodeIdVersion, nodeIdVersionInt)
import Hasura.GraphQL.Schema.Options qualified as Options
import Hasura.Prelude
@ -198,7 +199,7 @@ processAnnAggregateSelect sourcePrefixes fieldAlias annAggSel = do
aggregateFieldToExp aggFields strfyNum
)
TAFNodes _ annFields -> do
annFieldExtr <- processAnnFields thisSourcePrefix fieldName similarArrayFields annFields
annFieldExtr <- processAnnFields thisSourcePrefix fieldName similarArrayFields annFields tCase
pure
( [annFieldExtr],
withJsonAggExtr permLimitSubQuery (orderByForJsonAgg selectSource) $
@ -221,7 +222,7 @@ processAnnAggregateSelect sourcePrefixes fieldAlias annAggSel = do
pure (selectSource, nodeExtractors, topLevelExtractor)
where
AnnSelectG aggSelFields tableFrom tablePermissions tableArgs strfyNum = annAggSel
AnnSelectG aggSelFields tableFrom tablePermissions tableArgs strfyNum tCase = annAggSel
permLimit = _tpLimit tablePermissions
orderBy = _saOrderBy tableArgs
permLimitSubQuery = mkPermissionLimitSubQuery permLimit aggSelFields orderBy
@ -268,8 +269,9 @@ processAnnFields ::
FieldName ->
SimilarArrayFields ->
AnnFields ('Postgres pgKind) ->
Maybe NamingCase ->
m (S.ColumnAlias, S.SQLExp)
processAnnFields sourcePrefix fieldAlias similarArrFields annFields = do
processAnnFields sourcePrefix fieldAlias similarArrFields annFields tCase = do
fieldExps <- forM annFields $ \(fieldName, field) ->
(fieldName,)
<$> case field of
@ -281,7 +283,7 @@ processAnnFields sourcePrefix fieldAlias similarArrFields annFields = do
AnnObjectSelectG objAnnFields tableFrom tableFilter = annObjSel
objRelSourcePrefix = mkObjectRelationTableAlias sourcePrefix relName
sourcePrefixes = mkSourcePrefixes objRelSourcePrefix
annFieldsExtr <- processAnnFields (_pfThis sourcePrefixes) fieldName HM.empty objAnnFields
annFieldsExtr <- processAnnFields (_pfThis sourcePrefixes) fieldName HM.empty objAnnFields tCase
let selectSource =
ObjectSelectSource
(_pfThis sourcePrefixes)
@ -296,7 +298,7 @@ processAnnFields sourcePrefix fieldAlias similarArrFields annFields = do
AFArrayRelation arrSel -> do
let arrRelSourcePrefix = mkArrayRelationSourcePrefix sourcePrefix fieldAlias similarArrFields fieldName
arrRelAlias = mkArrayRelationAlias fieldAlias similarArrFields fieldName
processArrayRelation (mkSourcePrefixes arrRelSourcePrefix) fieldName arrRelAlias arrSel
processArrayRelation (mkSourcePrefixes arrRelSourcePrefix) fieldName arrRelAlias arrSel tCase
pure $ S.mkQIdenExp arrRelSourcePrefix fieldName
AFComputedField _ _ (CFSScalar scalar caseBoolExpMaybe) -> do
computedFieldSQLExp <- fromScalarComputedField scalar
@ -355,13 +357,13 @@ processAnnFields sourcePrefix fieldAlias similarArrFields annFields = do
toSQLBoolExp (S.QualifiedIdentifier baseTableIdentifier Nothing) $
_accColCaseBoolExpField <$> caseBoolExp
in S.SECond boolExp sqlExpression S.SENull
pure $ toJSONableExp strfyNum typ asText finalSQLExpression
pure $ toJSONableExp strfyNum typ asText tCase finalSQLExpression
fromScalarComputedField :: ComputedFieldScalarSelect ('Postgres pgKind) S.SQLExp -> m S.SQLExp
fromScalarComputedField computedFieldScalar = do
strfyNum <- ask
pure $
toJSONableExp strfyNum (ColumnScalar ty) False $
toJSONableExp strfyNum (ColumnScalar ty) False Nothing $
withColumnOp colOpM $
S.SEFunction $ S.FunctionExp fn (fromTableRowArgs sourcePrefix args) Nothing
where
@ -375,7 +377,7 @@ processAnnFields sourcePrefix fieldAlias similarArrFields annFields = do
mkNodeId :: SourceName -> QualifiedTable -> PrimaryKeyColumns ('Postgres pgKind) -> S.SQLExp
mkNodeId _sourceName (QualifiedObject tableSchema tableName) pkeyColumns =
let columnInfoToSQLExp pgColumnInfo =
toJSONableExp Options.Don'tStringifyNumbers (ciType pgColumnInfo) False $
toJSONableExp Options.Don'tStringifyNumbers (ciType pgColumnInfo) False Nothing $
S.mkQIdenExp (mkBaseTableAlias sourcePrefix) $ ciColumn pgColumnInfo
in -- See Note [Relay Node id].
encodeBase64 $
@ -447,8 +449,9 @@ processArrayRelation ::
FieldName ->
S.TableAlias ->
ArraySelect ('Postgres pgKind) ->
Maybe NamingCase ->
m ()
processArrayRelation sourcePrefixes fieldAlias relAlias arrSel =
processArrayRelation sourcePrefixes fieldAlias relAlias arrSel _tCase =
case arrSel of
ASSimple annArrRel -> withWriteArrayRelation $ do
let AnnRelationSelectG _ colMapping sel = annArrRel
@ -504,7 +507,7 @@ aggregateFieldToExp aggFlds strfyNum = jsonRow
colFldsToExtr opText (FieldName t, CFCol col ty) =
[ S.SELit t,
toJSONableExp strfyNum ty False $
toJSONableExp strfyNum ty False Nothing $
S.SEFnApp opText [S.SEIdentifier $ toIdentifier col] Nothing
]
colFldsToExtr _ (FieldName t, CFExp e) =
@ -535,11 +538,11 @@ processAnnSimpleSelect sourcePrefixes fieldAlias permLimitSubQuery annSimpleSel
permLimitSubQuery
tablePermissions
tableArgs
annFieldsExtr <- processAnnFields (_pfThis sourcePrefixes) fieldAlias similarArrayFields annSelFields
annFieldsExtr <- processAnnFields (_pfThis sourcePrefixes) fieldAlias similarArrayFields annSelFields tCase
let allExtractors = HM.fromList $ annFieldsExtr : orderByAndDistinctExtrs
pure (selectSource, allExtractors)
where
AnnSelectG annSelFields tableFrom tablePermissions tableArgs _ = annSimpleSel
AnnSelectG annSelFields tableFrom tablePermissions tableArgs _ tCase = annSimpleSel
similarArrayFields =
mkSimilarArrayFields annSelFields $ _saOrderBy tableArgs
@ -595,7 +598,7 @@ processConnectionSelect sourcePrefixes fieldAlias relAlias colMapping connection
)
where
ConnectionSelect _ primaryKeyColumns maybeSplit maybeSlice select = connectionSelect
AnnSelectG fields selectFrom tablePermissions tableArgs _ = select
AnnSelectG fields selectFrom tablePermissions tableArgs _ tCase = select
fieldIdentifier = toIdentifier fieldAlias
thisPrefix = _pfThis sourcePrefixes
permLimitSubQuery = PLSQNotRequired
@ -605,7 +608,7 @@ processConnectionSelect sourcePrefixes fieldAlias relAlias colMapping connection
flip concatMap (toList primaryKeyColumns) $
\pgColumnInfo ->
[ S.SELit $ getPGColTxt $ ciColumn pgColumnInfo,
toJSONableExp Options.Don'tStringifyNumbers (ciType pgColumnInfo) False $
toJSONableExp Options.Don'tStringifyNumbers (ciType pgColumnInfo) False tCase $
S.mkQIdenExp (mkBaseTableAlias thisPrefix) $ ciColumn pgColumnInfo
]
@ -685,7 +688,7 @@ processConnectionSelect sourcePrefixes fieldAlias relAlias colMapping connection
FieldName $
getFieldNameTxt fieldAlias <> "." <> fieldText <> "." <> edgeText
edgeFieldIdentifier = toIdentifier edgeFieldName
annFieldsExtrExp <- processAnnFields thisPrefix edgeFieldName similarArrayFields annFields
annFieldsExtrExp <- processAnnFields thisPrefix edgeFieldName similarArrayFields annFields tCase
modify' (<> [annFieldsExtrExp])
pure $ S.SEIdentifier edgeFieldIdentifier

View File

@ -96,7 +96,7 @@ mkStreamSQLSelect (AnnSelectStreamG () fields from perm args strfyNum) =
_saOrderBy = orderByItems,
_saLimit = Just $ _ssaBatchSize args
}
sqlSelect = AnnSelectG fields from perm selectArgs strfyNum
sqlSelect = AnnSelectG fields from perm selectArgs strfyNum Nothing
permLimitSubQuery = PLSQNotRequired
((selectSource, nodeExtractors), joinTree) =
runWriter $

View File

@ -34,7 +34,7 @@ mkUpdateCTE ::
Backend ('Postgres pgKind) =>
AnnotatedUpdate ('Postgres pgKind) ->
UpdateCTE
mkUpdateCTE (AnnotatedUpdateG tn (permFltr, wc) chk backendUpdate _ columnsInfo) =
mkUpdateCTE (AnnotatedUpdateG tn (permFltr, wc) chk backendUpdate _ columnsInfo _tCase) =
case backendUpdate of
BackendUpdate opExps ->
Update $ S.CTEUpdate update

View File

@ -321,7 +321,7 @@ resolveAsyncActionQuery userInfo annAction =
{ RS._saWhere = Just tableBoolExpression
}
tablePermissions = RS.TablePerm annBoolExpTrue Nothing
in RS.AnnSelectG annotatedFields tableFromExp tablePermissions tableArguments stringifyNumerics
in RS.AnnSelectG annotatedFields tableFromExp tablePermissions tableArguments stringifyNumerics Nothing
where
IR.AnnActionAsyncQuery _ actionId outputType asyncFields definitionList stringifyNumerics _ actionSource = annAction
@ -658,8 +658,8 @@ processOutputSelectionSet ::
IR.ActionFields ->
Options.StringifyNumbers ->
RS.AnnSimpleSelectG ('Postgres 'Vanilla) Void v
processOutputSelectionSet tableRowInput actionOutputType definitionList actionFields =
RS.AnnSelectG annotatedFields selectFrom RS.noTablePermissions RS.noSelectArgs
processOutputSelectionSet tableRowInput actionOutputType definitionList actionFields strfyNum =
RS.AnnSelectG annotatedFields selectFrom RS.noTablePermissions RS.noSelectArgs strfyNum Nothing
where
annotatedFields = fmap actionFieldToAnnField <$> actionFields
jsonbToPostgresRecordFunction =

View File

@ -211,7 +211,8 @@ convertRemoteSourceRelationship
_asnFrom = selectFrom,
_asnPerm = TablePerm annBoolExpTrue Nothing,
_asnArgs = noSelectArgs,
_asnStrfyNum = Options.Don'tStringifyNumbers
_asnStrfyNum = Options.Don'tStringifyNumbers,
_asnNamingConvention = Nothing
}
data DBStepInfo b = DBStepInfo

View File

@ -12,6 +12,7 @@ module Hasura.GraphQL.Schema.Mutation
)
where
import Data.Has (getter)
import Data.HashMap.Strict qualified as Map
import Data.HashSet qualified as Set
import Data.Text.Extended
@ -19,6 +20,7 @@ import Hasura.GraphQL.Parser.Class
import Hasura.GraphQL.Schema.Backend
import Hasura.GraphQL.Schema.BoolExp
import Hasura.GraphQL.Schema.Common
import Hasura.GraphQL.Schema.NamingCase (NamingCase)
import Hasura.GraphQL.Schema.Parser
( FieldParser,
InputFieldsParser,
@ -75,6 +77,7 @@ insertIntoTable backendInsertAction scenario sourceInfo tableInfo fieldName desc
-- If we're in a frontend scenario, we should not include backend_only inserts
-- For more info see Note [Backend only permissions]
guard $ not $ scenario == Frontend && ipiBackendOnly insertPerms
tCase <- asks getter
lift do
updatePerms <- _permUpd <$> tablePermissions tableInfo
-- objects [{ ... }]
@ -88,7 +91,7 @@ insertIntoTable backendInsertAction scenario sourceInfo tableInfo fieldName desc
pure $ mkInsertObject objects tableInfo backendInsert insertPerms updatePerms
pure $
P.subselection fieldName description argsParser selectionParser
<&> \(insertObject, output) -> IR.AnnotatedInsert (G.unName fieldName) False insertObject (IR.MOutMultirowFields output)
<&> \(insertObject, output) -> IR.AnnotatedInsert (G.unName fieldName) False insertObject (IR.MOutMultirowFields output) (Just tCase)
where
mkObjectsArg objectParser =
P.field
@ -124,6 +127,7 @@ insertOneIntoTable backendInsertAction scenario sourceInfo tableInfo fieldName d
-- For more info see Note [Backend only permissions]
guard $ not $ scenario == Frontend && ipiBackendOnly insertPerms
selectionParser <- MaybeT $ tableSelectionSet sourceInfo tableInfo
tCase <- asks getter
lift do
updatePerms <- _permUpd <$> tablePermissions tableInfo
objectParser <- tableFieldsInput sourceInfo tableInfo
@ -134,7 +138,7 @@ insertOneIntoTable backendInsertAction scenario sourceInfo tableInfo fieldName d
pure $ mkInsertObject [object] tableInfo backendInsert insertPerms updatePerms
pure $
P.subselection fieldName description argsParser selectionParser
<&> \(insertObject, output) -> IR.AnnotatedInsert (G.unName fieldName) True insertObject (IR.MOutSinglerowObject output)
<&> \(insertObject, output) -> IR.AnnotatedInsert (G.unName fieldName) True insertObject (IR.MOutSinglerowObject output) (Just tCase)
where
mkObjectArg objectParser =
P.field
@ -358,6 +362,7 @@ deleteFromTable scenario sourceInfo tableInfo fieldName description = runMaybeT
-- If we're in a frontend scenario, we should not include backend_only deletes
-- For more info see Note [Backend only permissions]
guard $ not $ scenario == Frontend && dpiBackendOnly deletePerms
tCase <- asks getter
lift do
let whereName = Name._where
whereDesc = "filter the rows which have to be deleted"
@ -366,7 +371,7 @@ deleteFromTable scenario sourceInfo tableInfo fieldName description = runMaybeT
let columns = tableColumns tableInfo
pure $
P.subselection fieldName description whereArg selection
<&> mkDeleteObject (tableInfoName tableInfo) columns deletePerms . fmap IR.MOutMultirowFields
<&> mkDeleteObject (tableInfoName tableInfo) columns deletePerms (Just tCase) . fmap IR.MOutMultirowFields
-- | Construct a root field, normally called delete_tablename_by_pk, that can be used to delete an
-- individual rows from a DB table, specified by primary key. Select permissions are required, as
@ -394,24 +399,27 @@ deleteFromTableByPk scenario sourceInfo tableInfo fieldName description = runMay
-- For more info see Note [Backend only permissions]
guard $ not $ scenario == Frontend && dpiBackendOnly deletePerms
selection <- MaybeT $ tableSelectionSet sourceInfo tableInfo
tCase <- asks getter
let columns = tableColumns tableInfo
pure $
P.subselection fieldName description pkArgs selection
<&> mkDeleteObject (tableInfoName tableInfo) columns deletePerms . fmap IR.MOutSinglerowObject
<&> mkDeleteObject (tableInfoName tableInfo) columns deletePerms (Just tCase) . fmap IR.MOutSinglerowObject
mkDeleteObject ::
Backend b =>
TableName b ->
[ColumnInfo b] ->
DelPermInfo b ->
Maybe NamingCase ->
(AnnBoolExp b (IR.UnpreparedValue b), IR.MutationOutputG b (IR.RemoteRelationshipField IR.UnpreparedValue) (IR.UnpreparedValue b)) ->
IR.AnnDelG b (IR.RemoteRelationshipField IR.UnpreparedValue) (IR.UnpreparedValue b)
mkDeleteObject table columns deletePerms (whereExp, mutationOutput) =
mkDeleteObject table columns deletePerms tCase (whereExp, mutationOutput) =
IR.AnnDel
{ IR._adTable = table,
IR._adWhere = (permissionFilter, whereExp),
IR._adOutput = mutationOutput,
IR._adAllCols = columns
IR._adAllCols = columns,
IR._adNamingConvention = tCase
}
where
permissionFilter = fmap partialSQLExpToUnpreparedValue <$> dpiFilter deletePerms

View File

@ -1,5 +1,6 @@
module Hasura.GraphQL.Schema.NamingCase
( NamingCase (..),
isGraphqlCase,
parseNamingConventionFromText,
)
where
@ -29,3 +30,7 @@ parseNamingConventionFromText :: Text -> Either String NamingCase
parseNamingConventionFromText "hasura-default" = Right HasuraCase
parseNamingConventionFromText "graphql-default" = Right GraphqlCase
parseNamingConventionFromText _ = Left "naming_convention can either be \"hasura-default\" or \"graphql-default\""
isGraphqlCase :: NamingCase -> Bool
isGraphqlCase GraphqlCase = True
isGraphqlCase _ = False

View File

@ -23,6 +23,7 @@ import Hasura.Base.ToErrorValue
import Hasura.GraphQL.Schema.Backend
import Hasura.GraphQL.Schema.Common
import Hasura.GraphQL.Schema.Instances ()
import Hasura.GraphQL.Schema.NamingCase (NamingCase)
import Hasura.GraphQL.Schema.Node
import Hasura.GraphQL.Schema.Options qualified as Options
import Hasura.GraphQL.Schema.Parser (Kind (..), Parser, memoizeOn)
@ -110,6 +111,7 @@ nodeField sourceCache = do
let idDescription = G.Description "A globally unique id"
idArgument = P.field Name._id (Just idDescription) P.identifier
stringifyNumbers <- retrieve Options.soStringifyNumbers
tCase <- asks getter
nodeObject <-
retrieve scSchemaKind >>= \case
HasuraSchema -> throw500 "internal error: the node field should only be built for the Relay schema"
@ -130,7 +132,7 @@ nodeField sourceCache = do
let matchingTables = flip mapMaybe (Map.keys sourceCache) \sourceName ->
(sourceName,) <$> findNode @('Postgres 'Vanilla) sourceName tableName parseds
case matchingTables of
[(sourceName, nodeValue)] -> createRootField stringifyNumbers sourceName tableName nodeValue pKeys
[(sourceName, nodeValue)] -> createRootField stringifyNumbers sourceName tableName nodeValue pKeys (Just tCase)
[] -> throwInvalidNodeId $ "no such table found: " <> toErrorValue tableName
l ->
throwInvalidNodeId $
@ -146,7 +148,7 @@ nodeField sourceCache = do
nodeValue <-
findNode @b sourceName tableName parseds
`onNothing` throwInvalidNodeId ("no table " <> toErrorValue tableName <> " found in source " <> toErrorValue sourceName)
createRootField stringifyNumbers sourceName tableName nodeValue pKeys
createRootField stringifyNumbers sourceName tableName nodeValue pKeys (Just tCase)
where
throwInvalidNodeId :: ErrorMessage -> n a
throwInvalidNodeId t = P.withKey (J.Key "args") $ P.withKey (J.Key "id") $ P.parseError $ "invalid node id: " <> t
@ -165,8 +167,9 @@ nodeField sourceCache = do
TableName b ->
NodeInfo b ->
NESeq.NESeq J.Value ->
Maybe NamingCase ->
n (IR.QueryRootField IR.UnpreparedValue)
createRootField stringifyNumbers sourceName tableName (NodeInfo sourceConfig perms pKeys fields) columnValues = do
createRootField stringifyNumbers sourceName tableName (NodeInfo sourceConfig perms pKeys fields) columnValues tCase = do
whereExp <- buildNodeIdBoolExp columnValues pKeys
pure $
IR.RFDB sourceName $
@ -186,7 +189,8 @@ nodeField sourceCache = do
IR._saOffset = Nothing,
IR._saDistinct = Nothing
},
IR._asnStrfyNum = stringifyNumbers
IR._asnStrfyNum = stringifyNumbers,
IR._asnNamingConvention = tCase
}
-- Craft the 'where' condition of the query by making an `AEQ` entry for

View File

@ -103,6 +103,7 @@ defaultSelectTable ::
Maybe G.Description ->
m (Maybe (FieldParser n (SelectExp b)))
defaultSelectTable sourceInfo tableInfo fieldName description = runMaybeT do
tCase <- asks getter
selectPermissions <- MaybeT $ tableSelectPermissions tableInfo
selectionSetParser <- MaybeT $ tableSelectionList sourceInfo tableInfo
lift $ memoizeOn 'defaultSelectTable (_siName sourceInfo, tableName, fieldName) do
@ -117,7 +118,8 @@ defaultSelectTable sourceInfo tableInfo fieldName description = runMaybeT do
IR._asnFrom = IR.FromTable tableName,
IR._asnPerm = tablePermissionsInfo selectPermissions,
IR._asnArgs = args,
IR._asnStrfyNum = stringifyNumbers
IR._asnStrfyNum = stringifyNumbers,
IR._asnNamingConvention = Just tCase
}
where
tableName = tableInfoName tableInfo
@ -157,6 +159,7 @@ selectTableConnection ::
PrimaryKeyColumns b ->
m (Maybe (FieldParser n (ConnectionSelectExp b)))
selectTableConnection sourceInfo tableInfo fieldName description pkeyColumns = runMaybeT do
tCase <- asks getter
xRelayInfo <- hoistMaybe $ relayExtension @b
selectPermissions <- MaybeT $ tableSelectPermissions tableInfo
selectionSetParser <- fmap P.nonNullableParser <$> MaybeT $ tableConnectionSelectionSet sourceInfo tableInfo
@ -177,7 +180,8 @@ selectTableConnection sourceInfo tableInfo fieldName description pkeyColumns = r
IR._asnFrom = IR.FromTable tableName,
IR._asnPerm = tablePermissionsInfo selectPermissions,
IR._asnArgs = args,
IR._asnStrfyNum = stringifyNumbers
IR._asnStrfyNum = stringifyNumbers,
IR._asnNamingConvention = Just tCase
}
}
where
@ -205,6 +209,7 @@ selectTableByPk ::
Maybe G.Description ->
m (Maybe (FieldParser n (SelectExp b)))
selectTableByPk sourceInfo tableInfo fieldName description = runMaybeT do
tCase <- asks getter
selectPermissions <- MaybeT $ tableSelectPermissions tableInfo
primaryKeys <- hoistMaybe $ fmap _pkColumns . _tciPrimaryKey . _tiCoreInfo $ tableInfo
selectionSetParser <- MaybeT $ tableSelectionSet sourceInfo tableInfo
@ -230,7 +235,8 @@ selectTableByPk sourceInfo tableInfo fieldName description = runMaybeT do
IR._asnFrom = IR.FromTable tableName,
IR._asnPerm = permissions,
IR._asnArgs = IR.noSelectArgs {IR._saWhere = whereExpr},
IR._asnStrfyNum = stringifyNumbers
IR._asnStrfyNum = stringifyNumbers,
IR._asnNamingConvention = Just tCase
}
where
tableName = tableInfoName tableInfo
@ -257,6 +263,7 @@ defaultSelectTableAggregate ::
Maybe G.Description ->
m (Maybe (FieldParser n (AggSelectExp b)))
defaultSelectTableAggregate sourceInfo tableInfo fieldName description = runMaybeT $ do
tCase <- asks getter
selectPermissions <- MaybeT $ tableSelectPermissions tableInfo
guard $ spiAllowAgg selectPermissions
xNodesAgg <- hoistMaybe $ nodesAggExtension @b
@ -285,7 +292,8 @@ defaultSelectTableAggregate sourceInfo tableInfo fieldName description = runMayb
IR._asnFrom = IR.FromTable tableName,
IR._asnPerm = tablePermissionsInfo selectPermissions,
IR._asnArgs = args,
IR._asnStrfyNum = stringifyNumbers
IR._asnStrfyNum = stringifyNumbers,
IR._asnNamingConvention = Just tCase
}
where
tableName = tableInfoName tableInfo

View File

@ -16,7 +16,7 @@ module Hasura.GraphQL.Schema.Update
)
where
import Data.Has (Has)
import Data.Has (Has (getter))
import Data.HashMap.Strict qualified as M
import Data.HashMap.Strict.Extended qualified as M
import Data.List.NonEmpty qualified as NE
@ -277,10 +277,11 @@ updateTable backendUpdate scenario sourceInfo tableInfo fieldName description =
guard $ not $ scenario == Frontend && upiBackendOnly updatePerms
whereArg <- lift $ P.field whereName (Just whereDesc) <$> boolExp sourceInfo tableInfo
selection <- lift $ mutationSelectionSet sourceInfo tableInfo
tCase <- asks getter
let argsParser = liftA2 (,) backendUpdate whereArg
pure $
P.subselection fieldName description argsParser selection
<&> mkUpdateObject tableName columns updatePerms . fmap MOutMultirowFields
<&> mkUpdateObject tableName columns updatePerms (Just tCase) . fmap MOutMultirowFields
-- | Construct a root field, normally called 'update_tablename_by_pk', that can be used
-- to update a single in a DB table, specified by primary key. Only returns a
@ -313,6 +314,7 @@ updateTableByPk backendUpdate scenario sourceInfo tableInfo fieldName descriptio
guard $ not $ scenario == Frontend && upiBackendOnly updatePerms
pkArgs <- MaybeT $ primaryKeysArguments tableInfo
selection <- MaybeT $ tableSelectionSet sourceInfo tableInfo
tCase <- asks getter
lift $ do
tableGQLName <- getTableGQLName tableInfo
pkObjectName <- mkTypename $ tableGQLName <> $$(litName "_pk_columns_input")
@ -322,20 +324,21 @@ updateTableByPk backendUpdate scenario sourceInfo tableInfo fieldName descriptio
argsParser = (,) <$> backendUpdate <*> P.field pkFieldName Nothing pkParser
pure $
P.subselection fieldName description argsParser selection
<&> mkUpdateObject tableName columns updatePerms . fmap MOutSinglerowObject
<&> mkUpdateObject tableName columns updatePerms (Just tCase) . fmap MOutSinglerowObject
mkUpdateObject ::
Backend b =>
TableName b ->
[ColumnInfo b] ->
UpdPermInfo b ->
(Maybe NamingCase) ->
( ( BackendUpdate b (UnpreparedValue b),
AnnBoolExp b (UnpreparedValue b)
),
MutationOutputG b (RemoteRelationshipField UnpreparedValue) (UnpreparedValue b)
) ->
AnnotatedUpdateG b (RemoteRelationshipField UnpreparedValue) (UnpreparedValue b)
mkUpdateObject _auTable _auAllCols updatePerms ((_auBackend, whereExp), _auOutput) =
mkUpdateObject _auTable _auAllCols updatePerms _auNamingConvention ((_auBackend, whereExp), _auOutput) =
AnnotatedUpdateG {..}
where
permissionFilter = fmap partialSQLExpToUnpreparedValue <$> upiFilter updatePerms

View File

@ -86,6 +86,7 @@ validateDeleteQWith
(resolvedDelFltr, annSQLBoolExp)
(mkDefaultMutFlds mAnnRetCols)
allCols
Nothing
where
selNecessaryMsg =
"; \"delete\" is only allowed if the role "
@ -123,4 +124,4 @@ runDelete q = do
validateDeleteQ q
>>= runTxWithCtx (_pscExecCtx sourceConfig) Q.ReadWrite
. flip runReaderT emptyQueryTagsComment
. execDeleteQuery strfyNum userInfo
. execDeleteQuery strfyNum Nothing userInfo

View File

@ -253,7 +253,7 @@ runInsert q = do
res <- convInsQ q
strfyNum <- stringifyNum . _sccSQLGenCtx <$> askServerConfigCtx
runTxWithCtx (_pscExecCtx sourceConfig) Q.ReadWrite $
flip runReaderT emptyQueryTagsComment $ execInsertQuery strfyNum userInfo res
flip runReaderT emptyQueryTagsComment $ execInsertQuery strfyNum Nothing userInfo res
decodeInsObjs :: (UserInfoM m, QErrM m) => Value -> m [InsObj ('Postgres 'Vanilla)]
decodeInsObjs v = do

View File

@ -232,7 +232,7 @@ convSelectQ table fieldInfoMap selPermInfo selQ sessVarBldr prepValBldr = do
tabArgs = SelectArgs wClause annOrdByM mQueryLimit (fromIntegral <$> mQueryOffset) Nothing
strfyNum <- stringifyNum . _sccSQLGenCtx <$> askServerConfigCtx
pure $ AnnSelectG annFlds tabFrom tabPerm tabArgs strfyNum
pure $ AnnSelectG annFlds tabFrom tabPerm tabArgs strfyNum Nothing
where
mQueryOffset = sqOffset selQ
mQueryLimit = sqLimit selQ

View File

@ -191,6 +191,7 @@ validateUpdateQueryWith sessVarBldr prepValBldr uq = do
(BackendUpdate $ Map.fromList $ fmap UpdateSet <$> setExpItems)
(mkDefaultMutFlds mAnnRetCols)
allCols
Nothing
where
mRetCols = uqReturning uq
selNecessaryMsg =
@ -229,4 +230,4 @@ runUpdate q = do
validateUpdateQuery q
>>= runTxWithCtx (_pscExecCtx sourceConfig) Q.ReadWrite
. flip runReaderT emptyQueryTagsComment
. execUpdateQuery strfyNum userInfo
. execUpdateQuery strfyNum Nothing userInfo

View File

@ -8,11 +8,13 @@ module Hasura.RQL.IR.Delete
adWhere,
adOutput,
adAllCols,
adNamingConvention,
)
where
import Control.Lens.TH (makeLenses)
import Data.Kind (Type)
import Hasura.GraphQL.Schema.NamingCase (NamingCase)
import Hasura.Prelude
import Hasura.RQL.IR.BoolExp
import Hasura.RQL.IR.Returning
@ -24,7 +26,8 @@ data AnnDelG (b :: BackendType) (r :: Type) v = AnnDel
{ _adTable :: TableName b,
_adWhere :: (AnnBoolExp b v, AnnBoolExp b v),
_adOutput :: MutationOutputG b r v,
_adAllCols :: [ColumnInfo b]
_adAllCols :: [ColumnInfo b],
_adNamingConvention :: Maybe NamingCase
}
deriving (Functor, Foldable, Traversable)

View File

@ -18,6 +18,7 @@ module Hasura.RQL.IR.Insert
aiIsSingle,
aiData,
aiOutput,
aiNamingConvention,
AnnotatedInsertField (..),
AnnotatedInsertRow,
ArrayRelationInsert,
@ -42,6 +43,7 @@ where
import Control.Lens ((^?))
import Control.Lens.TH (makeLenses, makePrisms)
import Data.Kind (Type)
import Hasura.GraphQL.Schema.NamingCase (NamingCase)
import Hasura.Prelude
import Hasura.RQL.IR.BoolExp
import Hasura.RQL.IR.Conflict
@ -60,7 +62,8 @@ data AnnotatedInsert (b :: BackendType) (r :: Type) v = AnnotatedInsert
{ _aiFieldName :: Text,
_aiIsSingle :: Bool,
_aiData :: MultiObjectInsert b v,
_aiOutput :: MutationOutputG b r v
_aiOutput :: MutationOutputG b r v,
_aiNamingConvention :: Maybe NamingCase
}
deriving (Functor, Foldable, Traversable)

View File

@ -104,6 +104,7 @@ module Hasura.RQL.IR.Select
asnFrom,
asnPerm,
asnStrfyNum,
asnNamingConvention,
bifoldMapAnnSelectG,
csXRelay,
csPrimaryKeyColumns,
@ -152,6 +153,7 @@ import Data.Kind (Type)
import Data.List.NonEmpty qualified as NE
import Data.Sequence qualified as Seq
import Hasura.Backends.Postgres.SQL.Types qualified as PG
import Hasura.GraphQL.Schema.NamingCase (NamingCase)
import Hasura.GraphQL.Schema.Options (StringifyNumbers)
import Hasura.Prelude
import Hasura.RQL.IR.BoolExp
@ -192,7 +194,8 @@ data AnnSelectG (b :: BackendType) (f :: Type -> Type) (v :: Type) = AnnSelectG
_asnFrom :: SelectFromG b v,
_asnPerm :: TablePermG b v,
_asnArgs :: SelectArgsG b v,
_asnStrfyNum :: StringifyNumbers
_asnStrfyNum :: StringifyNumbers,
_asnNamingConvention :: Maybe NamingCase
}
deriving stock (Functor, Foldable, Traversable)

View File

@ -10,11 +10,13 @@ module Hasura.RQL.IR.Update
auBackend,
auOutput,
auAllCols,
auNamingConvention,
)
where
import Control.Lens.TH (makeLenses)
import Data.Kind (Type)
import Hasura.GraphQL.Schema.NamingCase (NamingCase)
import Hasura.Prelude
import Hasura.RQL.IR.BoolExp
import Hasura.RQL.IR.Returning
@ -38,7 +40,8 @@ data AnnotatedUpdateG (b :: BackendType) (r :: Type) v = AnnotatedUpdateG
-- | Selection set
_auOutput :: !(MutationOutputG b r v),
_auAllCols :: ![ColumnInfo b]
_auAllCols :: ![ColumnInfo b],
_auNamingConvention :: !(Maybe NamingCase)
}
deriving stock (Functor, Foldable, Traversable)

View File

@ -5,6 +5,7 @@ module Hasura.RQL.Types.Column
( ColumnType (..),
_ColumnScalar,
_ColumnEnumReference,
isEnumColumn,
isScalarColumnWhere,
ValueParser,
onlyNumCols,
@ -133,6 +134,10 @@ isScalarColumnWhere f = \case
ColumnScalar scalar -> f scalar
ColumnEnumReference _ -> False
isEnumColumn :: ColumnType b -> Bool
isEnumColumn (ColumnEnumReference _) = True
isEnumColumn _ = False
-- | Note: Unconditionally accepts null values and returns 'PGNull'.
parseScalarValueColumnType ::
forall m b.

View File

@ -8,7 +8,7 @@ import Hasura.Backends.DataConnector.RQLGenerator.GenSelectFromG (genSelectFromG
import Hasura.Backends.DataConnector.RQLGenerator.GenTablePermG (genTablePermG)
import Hasura.Generator.Common (defaultRange)
import Hasura.GraphQL.Schema.Options qualified as Options
import Hasura.Prelude (Applicative ((<*>)), Bool (..), (<$>), (<&>))
import Hasura.Prelude hiding (bool)
import Hasura.RQL.IR (AnnSelectG (..))
import Hasura.RQL.IR.Generator (genFields)
import Hasura.SQL.Backend (BackendType (..))
@ -25,6 +25,7 @@ genAnnSelectG genA genFA =
<*> genTablePermG genA
<*> genArgs
<*> genStringifyNumbers
<*> (pure Nothing)
where
genStringifyNumbers =
bool <&> \case

View File

@ -25,6 +25,7 @@ genAnnSelectG genA genFA =
<*> genTablePermG genA
<*> genArgs
<*> genStringifyNumbers
<*> (pure Nothing)
where
genStringifyNumbers =
Gen.bool <&> \case

View File

@ -19,6 +19,7 @@ import Hasura.Backends.Postgres.Types.Update (BackendUpdate (..), MultiRowUpdate
import Hasura.GraphQL.Parser.Internal.Parser (FieldParser (..))
import Hasura.GraphQL.Parser.Schema (Definition (..))
import Hasura.GraphQL.Parser.Variable (Variable (..))
import Hasura.GraphQL.Schema.NamingCase
import Hasura.Prelude
import Hasura.RQL.IR.BoolExp (AnnBoolExpFld (..), GBoolExp (..), OpExpG (..))
import Hasura.RQL.IR.Returning (MutationOutputG (..))
@ -197,3 +198,6 @@ mkAnnotatedUpdate AnnotatedUpdateBuilder {..} = AnnotatedUpdateG {..}
BoolAnd
. fmap (\c -> BoolField . AVColumn c $ stuff)
$ aubColumns
_auNamingConvention :: Maybe NamingCase
_auNamingConvention = Just HasuraCase

View File

@ -34,7 +34,7 @@
);
INSERT INTO days_of_the_week (day_name)
VALUES ('Monday'), ('Tuesday'), ('Wednesday'), ('Thursday'), ('Friday'), ('Saturday'), ('Sunday');
CREATE TABLE users(
id serial PRIMARY KEY,
favourite_day text NOT NULL REFERENCES days_of_the_week
@ -86,6 +86,135 @@
}
}
- description: Insert users returning enum values (should be uppercased)
url: /v1/graphql
status: 200
response:
data:
insertUsers:
returning:
- id: 2
favouriteDay: SUNDAY
- id: 3
favouriteDay: FRIDAY
- id: 4
favouriteDay: MONDAY
- id: 5
favouriteDay: SATURDAY
query:
query: |
mutation {
insertUsers(objects: [{favouriteDay: SUNDAY},{favouriteDay: FRIDAY},{favouriteDay: MONDAY},{favouriteDay: SATURDAY}]) {
returning {
id
favouriteDay
}
}
}
- description: Update users returning enum values (should be uppercased)
url: /v1/graphql
status: 200
response:
data:
updateUsers:
returning:
- id: 1
favouriteDay: MONDAY
- id: 2
favouriteDay: MONDAY
query:
query: |
mutation {
updateUsers(where: {favouriteDay: {_eq: SUNDAY}}, _set: {favouriteDay: MONDAY}) {
returning {
id
favouriteDay
}
}
}
- description: Delete users returning enum values (should be uppercased)
url: /v1/graphql
status: 200
response:
data:
deleteUsers:
returning:
- id: 4
favouriteDay: MONDAY
- id: 1
favouriteDay: MONDAY
- id: 2
favouriteDay: MONDAY
query:
query: |
mutation MyMutation {
deleteUsers(where: {favouriteDay: {_eq: MONDAY}}) {
returning {
id
favouriteDay
}
}
}
- description: Insert user by pk returning enum value (should be uppercased)
url: /v1/graphql
status: 200
response:
data:
insertUsersOne:
id: 6
favouriteDay: SUNDAY
query:
query: |
mutation {
insertUsersOne(object: {favouriteDay: SUNDAY}) {
id
favouriteDay
}
}
- description: Update user by pk returning enum value (should be uppercased)
url: /v1/graphql
status: 200
response:
data:
updateUsersByPk:
id: 3
favouriteDay: WEDNESDAY
query:
query: |
mutation {
updateUsersByPk(pk_columns: {id: 3}, _set: {favouriteDay: WEDNESDAY}) {
id
favouriteDay
}
}
- description: Delete user by pk returning enum value (should be uppercased)
url: /v1/graphql
status: 200
response:
data:
deleteUsersByPk:
id: 5
favouriteDay: SATURDAY
query:
query: |
mutation MyMutation {
deleteUsersByPk(id: 5) {
id
favouriteDay
}
}
- description: Untrack tables
url: /v1/metadata
status: 200

View File

@ -39,6 +39,7 @@ class TestNamingConventionsFailure:
check_query_f(hge_ctx, self.dir() + '/mssql_naming_convention.yaml')
@pytest.mark.skipif(
not env_var_contains('HASURA_GRAPHQL_EXPERIMENTAL_FEATURES', 'naming_convention') or
not env_var_contains('HASURA_GRAPHQL_DEFAULT_NAMING_CONVENTION', 'graphql-default'),
reason="This test expects the HASURA_GRAPHQL_DEFAULT_NAMING_CONVENTION environment variable set to graphql-default")
class TestDefaultNamingConvention: