2018-06-27 16:11:32 +03:00
|
|
|
module Hasura.GraphQL.Resolve.Mutation
|
|
|
|
( convertUpdate
|
2020-02-13 20:38:23 +03:00
|
|
|
, convertUpdateByPk
|
2018-06-27 16:11:32 +03:00
|
|
|
, convertDelete
|
2020-02-13 20:38:23 +03:00
|
|
|
, convertDeleteByPk
|
|
|
|
, resolveMutationFields
|
2019-01-28 10:24:24 +03:00
|
|
|
, buildEmptyMutResp
|
2018-06-27 16:11:32 +03:00
|
|
|
) where
|
|
|
|
|
2019-03-25 21:25:25 +03:00
|
|
|
import Data.Has
|
2018-06-27 16:11:32 +03:00
|
|
|
import Hasura.Prelude
|
|
|
|
|
2019-12-03 23:00:37 +03:00
|
|
|
import qualified Control.Monad.Validate as MV
|
|
|
|
import qualified Data.Aeson as J
|
|
|
|
import qualified Data.HashMap.Strict as Map
|
|
|
|
import qualified Data.HashMap.Strict.InsOrd as OMap
|
|
|
|
import qualified Data.HashMap.Strict.InsOrd.Extended as OMap
|
|
|
|
import qualified Data.Sequence.NonEmpty as NESeq
|
|
|
|
import qualified Data.Text as T
|
|
|
|
import qualified Language.GraphQL.Draft.Syntax as G
|
|
|
|
|
|
|
|
import qualified Hasura.RQL.DML.Delete as RD
|
|
|
|
import qualified Hasura.RQL.DML.Returning as RR
|
|
|
|
import qualified Hasura.RQL.DML.Update as RU
|
|
|
|
|
|
|
|
import qualified Hasura.RQL.DML.Select as RS
|
|
|
|
import qualified Hasura.SQL.DML as S
|
2018-06-27 16:11:32 +03:00
|
|
|
|
2019-03-22 10:08:42 +03:00
|
|
|
import Hasura.EncJSON
|
2018-06-27 16:11:32 +03:00
|
|
|
import Hasura.GraphQL.Resolve.BoolExp
|
|
|
|
import Hasura.GraphQL.Resolve.Context
|
|
|
|
import Hasura.GraphQL.Resolve.InputValue
|
2020-02-13 20:38:23 +03:00
|
|
|
import Hasura.GraphQL.Resolve.Select (processTableSelectionSet)
|
2018-06-27 16:11:32 +03:00
|
|
|
import Hasura.GraphQL.Validate.Field
|
|
|
|
import Hasura.GraphQL.Validate.Types
|
2020-02-13 20:38:23 +03:00
|
|
|
import Hasura.RQL.DML.Internal (currentSession, sessVarFromCurrentSetting)
|
2018-06-27 16:11:32 +03:00
|
|
|
import Hasura.RQL.Types
|
|
|
|
import Hasura.SQL.Types
|
2018-07-20 13:51:20 +03:00
|
|
|
import Hasura.SQL.Value
|
2018-06-27 16:11:32 +03:00
|
|
|
|
2020-02-13 20:38:23 +03:00
|
|
|
resolveMutationFields
|
2019-10-16 17:33:34 +03:00
|
|
|
:: ( MonadReusability m, MonadError QErr m, MonadReader r m, Has FieldMap r
|
2019-03-25 21:25:25 +03:00
|
|
|
, Has OrdByCtx r, Has SQLGenCtx r
|
|
|
|
)
|
2019-04-17 12:48:41 +03:00
|
|
|
=> G.NamedType -> SelSet -> m (RR.MutFldsG UnresolvedVal)
|
2020-02-13 20:38:23 +03:00
|
|
|
resolveMutationFields ty selSet = fmap (map (first FieldName)) $
|
2018-10-26 12:02:44 +03:00
|
|
|
withSelSet selSet $ \fld -> case _fName fld of
|
|
|
|
"__typename" -> return $ RR.MExp $ G.unName $ G.unNamedType ty
|
|
|
|
"affected_rows" -> return RR.MCount
|
2019-04-17 12:48:41 +03:00
|
|
|
"returning" -> do
|
2020-02-13 20:38:23 +03:00
|
|
|
annFlds <- processTableSelectionSet (_fType fld) $ _fSelSet fld
|
2019-04-17 12:48:41 +03:00
|
|
|
annFldsResolved <- traverse
|
2019-11-20 09:47:06 +03:00
|
|
|
(traverse (RS.traverseAnnFld convertPGValueToTextValue)) annFlds
|
2019-04-17 12:48:41 +03:00
|
|
|
return $ RR.MRet annFldsResolved
|
2018-10-26 12:02:44 +03:00
|
|
|
G.Name t -> throw500 $ "unexpected field in mutation resp : " <> t
|
2019-04-17 12:48:41 +03:00
|
|
|
where
|
2019-11-20 09:47:06 +03:00
|
|
|
convertPGValueToTextValue = \case
|
2019-04-17 12:48:41 +03:00
|
|
|
UVPG annPGVal -> UVSQL <$> txtConverter annPGVal
|
|
|
|
UVSessVar colTy sessVar -> pure $ UVSessVar colTy sessVar
|
|
|
|
UVSQL sqlExp -> pure $ UVSQL sqlExp
|
2019-11-20 09:47:06 +03:00
|
|
|
UVSession -> pure UVSession
|
2018-06-27 16:11:32 +03:00
|
|
|
|
|
|
|
convertRowObj
|
2019-10-16 17:33:34 +03:00
|
|
|
:: (MonadReusability m, MonadError QErr m)
|
2019-09-19 07:47:36 +03:00
|
|
|
=> PGColGNameMap
|
|
|
|
-> AnnInpVal
|
2019-04-17 12:48:41 +03:00
|
|
|
-> m [(PGCol, UnresolvedVal)]
|
2019-09-19 07:47:36 +03:00
|
|
|
convertRowObj colGNameMap val =
|
2018-11-02 18:08:38 +03:00
|
|
|
flip withObject val $ \_ obj ->
|
|
|
|
forM (OMap.toList obj) $ \(k, v) -> do
|
2019-09-14 09:01:06 +03:00
|
|
|
prepExpM <- fmap mkParameterizablePGValue <$> asPGColumnValueM v
|
2019-09-19 07:47:36 +03:00
|
|
|
pgCol <- pgiColumn <$> resolvePGCol colGNameMap k
|
2019-08-29 16:07:05 +03:00
|
|
|
let prepExp = fromMaybe (UVSQL S.SENull) prepExpM
|
2019-09-19 07:47:36 +03:00
|
|
|
return (pgCol, prepExp)
|
2018-06-27 16:11:32 +03:00
|
|
|
|
2018-07-20 13:51:20 +03:00
|
|
|
type ApplySQLOp = (PGCol, S.SQLExp) -> S.SQLExp
|
|
|
|
|
2019-07-10 13:19:58 +03:00
|
|
|
rhsExpOp :: S.SQLOp -> S.TypeAnn -> ApplySQLOp
|
2018-07-20 13:51:20 +03:00
|
|
|
rhsExpOp op annTy (col, e) =
|
|
|
|
S.mkSQLOpExp op (S.SEIden $ toIden col) annExp
|
|
|
|
where
|
|
|
|
annExp = S.SETyAnn e annTy
|
|
|
|
|
2019-07-10 13:19:58 +03:00
|
|
|
lhsExpOp :: S.SQLOp -> S.TypeAnn -> ApplySQLOp
|
2018-07-20 13:51:20 +03:00
|
|
|
lhsExpOp op annTy (col, e) =
|
|
|
|
S.mkSQLOpExp op annExp $ S.SEIden $ toIden col
|
|
|
|
where
|
|
|
|
annExp = S.SETyAnn e annTy
|
|
|
|
|
|
|
|
convObjWithOp
|
2019-10-16 17:33:34 +03:00
|
|
|
:: (MonadReusability m, MonadError QErr m)
|
2019-09-19 07:47:36 +03:00
|
|
|
=> PGColGNameMap -> ApplySQLOp -> AnnInpVal -> m [(PGCol, UnresolvedVal)]
|
|
|
|
convObjWithOp colGNameMap opFn val =
|
2018-10-12 13:36:47 +03:00
|
|
|
flip withObject val $ \_ obj -> forM (OMap.toList obj) $ \(k, v) -> do
|
2019-09-14 09:01:06 +03:00
|
|
|
colVal <- openOpaqueValue =<< asPGColumnValue v
|
2019-09-19 07:47:36 +03:00
|
|
|
pgCol <- pgiColumn <$> resolvePGCol colGNameMap k
|
|
|
|
-- TODO: why are we using txtEncoder here?
|
|
|
|
let encVal = txtEncoder $ pstValue $ _apvValue colVal
|
2018-07-20 13:51:20 +03:00
|
|
|
sqlExp = opFn (pgCol, encVal)
|
2019-04-17 12:48:41 +03:00
|
|
|
return (pgCol, UVSQL sqlExp)
|
2018-07-20 13:51:20 +03:00
|
|
|
|
|
|
|
convDeleteAtPathObj
|
2019-10-16 17:33:34 +03:00
|
|
|
:: (MonadReusability m, MonadError QErr m)
|
2019-09-19 07:47:36 +03:00
|
|
|
=> PGColGNameMap -> AnnInpVal -> m [(PGCol, UnresolvedVal)]
|
|
|
|
convDeleteAtPathObj colGNameMap val =
|
2018-10-12 13:36:47 +03:00
|
|
|
flip withObject val $ \_ obj -> forM (OMap.toList obj) $ \(k, v) -> do
|
2019-09-14 09:01:06 +03:00
|
|
|
vals <- traverse (openOpaqueValue <=< asPGColumnValue) =<< asArray v
|
2019-09-19 07:47:36 +03:00
|
|
|
pgCol <- pgiColumn <$> resolvePGCol colGNameMap k
|
2019-07-22 15:47:13 +03:00
|
|
|
let valExps = map (txtEncoder . pstValue . _apvValue) vals
|
2019-07-10 13:19:58 +03:00
|
|
|
annEncVal = S.SETyAnn (S.SEArray valExps) S.textArrTypeAnn
|
2018-07-20 13:51:20 +03:00
|
|
|
sqlExp = S.SEOpApp S.jsonbDeleteAtPathOp
|
|
|
|
[S.SEIden $ toIden pgCol, annEncVal]
|
2019-04-17 12:48:41 +03:00
|
|
|
return (pgCol, UVSQL sqlExp)
|
2018-07-20 13:51:20 +03:00
|
|
|
|
2019-03-25 21:25:25 +03:00
|
|
|
convertUpdateP1
|
2020-02-13 20:38:23 +03:00
|
|
|
:: (MonadReusability m, MonadError QErr m)
|
2019-03-25 21:25:25 +03:00
|
|
|
=> UpdOpCtx -- the update context
|
2020-02-13 20:38:23 +03:00
|
|
|
-> (ArgsMap -> m AnnBoolExpUnresolved) -- the bool expression parser
|
|
|
|
-> (Field -> m (RR.MutationOutputG UnresolvedVal)) -- the selection set resolver
|
2018-06-27 16:11:32 +03:00
|
|
|
-> Field -- the mutation field
|
2019-04-17 12:48:41 +03:00
|
|
|
-> m (RU.AnnUpdG UnresolvedVal)
|
2020-02-13 20:38:23 +03:00
|
|
|
convertUpdateP1 opCtx boolExpParser selectionResolver fld = do
|
2018-06-27 16:11:32 +03:00
|
|
|
-- a set expression is same as a row object
|
2019-12-03 23:00:37 +03:00
|
|
|
setExpM <- resolveUpdateOperator "_set" $ convertRowObj colGNameMap
|
2018-07-20 13:51:20 +03:00
|
|
|
-- where bool expression to filter column
|
2020-02-13 20:38:23 +03:00
|
|
|
whereExp <- boolExpParser args
|
2018-07-20 13:51:20 +03:00
|
|
|
-- increment operator on integer columns
|
2019-12-03 23:00:37 +03:00
|
|
|
incExpM <- resolveUpdateOperator "_inc" $
|
2019-09-19 07:47:36 +03:00
|
|
|
convObjWithOp' $ rhsExpOp S.incOp S.intTypeAnn
|
2018-07-20 13:51:20 +03:00
|
|
|
-- append jsonb value
|
2019-12-03 23:00:37 +03:00
|
|
|
appendExpM <- resolveUpdateOperator "_append" $
|
2019-09-19 07:47:36 +03:00
|
|
|
convObjWithOp' $ rhsExpOp S.jsonbConcatOp S.jsonbTypeAnn
|
2018-07-20 13:51:20 +03:00
|
|
|
-- prepend jsonb value
|
2019-12-03 23:00:37 +03:00
|
|
|
prependExpM <- resolveUpdateOperator "_prepend" $
|
2019-09-19 07:47:36 +03:00
|
|
|
convObjWithOp' $ lhsExpOp S.jsonbConcatOp S.jsonbTypeAnn
|
2018-07-20 13:51:20 +03:00
|
|
|
-- delete a key in jsonb object
|
2019-12-03 23:00:37 +03:00
|
|
|
deleteKeyExpM <- resolveUpdateOperator "_delete_key" $
|
2019-09-19 07:47:36 +03:00
|
|
|
convObjWithOp' $ rhsExpOp S.jsonbDeleteOp S.textTypeAnn
|
2018-07-20 13:51:20 +03:00
|
|
|
-- delete an element in jsonb array
|
2019-12-03 23:00:37 +03:00
|
|
|
deleteElemExpM <- resolveUpdateOperator "_delete_elem" $
|
2019-09-19 07:47:36 +03:00
|
|
|
convObjWithOp' $ rhsExpOp S.jsonbDeleteOp S.intTypeAnn
|
2018-07-20 13:51:20 +03:00
|
|
|
-- delete at path in jsonb value
|
2019-12-03 23:00:37 +03:00
|
|
|
deleteAtPathExpM <- resolveUpdateOperator "_delete_at_path" $
|
|
|
|
convDeleteAtPathObj colGNameMap
|
2019-04-17 12:48:41 +03:00
|
|
|
|
2019-12-03 23:00:37 +03:00
|
|
|
updateItems <- combineUpdateExpressions
|
|
|
|
[ setExpM, incExpM, appendExpM, prependExpM
|
2018-07-20 13:51:20 +03:00
|
|
|
, deleteKeyExpM, deleteElemExpM, deleteAtPathExpM
|
|
|
|
]
|
2019-03-25 21:25:25 +03:00
|
|
|
|
2020-02-13 20:38:23 +03:00
|
|
|
mutOutput <- selectionResolver fld
|
2019-04-17 12:48:41 +03:00
|
|
|
|
2020-02-13 20:38:23 +03:00
|
|
|
pure $ RU.AnnUpd tn updateItems (unresolvedPermFilter, whereExp) unresolvedPermCheck mutOutput allCols
|
2018-06-27 16:11:32 +03:00
|
|
|
where
|
2019-09-19 07:47:36 +03:00
|
|
|
convObjWithOp' = convObjWithOp colGNameMap
|
|
|
|
allCols = Map.elems colGNameMap
|
2020-02-13 10:38:49 +03:00
|
|
|
UpdOpCtx tn _ colGNameMap filterExp checkExpr preSetCols = opCtx
|
2018-06-27 16:11:32 +03:00
|
|
|
args = _fArguments fld
|
2019-12-03 23:00:37 +03:00
|
|
|
resolvedPreSetItems = Map.toList $ fmap partialSQLExpToUnresolvedVal preSetCols
|
|
|
|
unresolvedPermFilter = fmapAnnBoolExp partialSQLExpToUnresolvedVal filterExp
|
2020-02-13 10:38:49 +03:00
|
|
|
unresolvedPermCheck = maybe annBoolExpTrue (fmapAnnBoolExp partialSQLExpToUnresolvedVal) checkExpr
|
2019-12-03 23:00:37 +03:00
|
|
|
|
|
|
|
resolveUpdateOperator operator resolveAction =
|
|
|
|
(operator,) <$> withArgM args operator resolveAction
|
|
|
|
|
|
|
|
combineUpdateExpressions updateExps = do
|
|
|
|
let allOperatorNames = map fst updateExps
|
|
|
|
updateItems = mapMaybe (\(op, itemsM) -> (op,) <$> itemsM) updateExps
|
|
|
|
-- Atleast any one of operator is expected or preset expressions shouldn't be empty
|
|
|
|
if null updateItems && null resolvedPreSetItems then
|
|
|
|
throwVE $ "atleast any one of " <> showNames allOperatorNames <> " is expected"
|
|
|
|
else do
|
|
|
|
let itemsWithOps = concatMap (\(op, items) -> map (second (op,)) items) updateItems
|
|
|
|
validateMultiOps col items = do
|
|
|
|
when (length items > 1) $ MV.dispute [(col, map fst $ toList items)]
|
|
|
|
pure $ snd $ NESeq.head items
|
|
|
|
eitherResult = MV.runValidate $ OMap.traverseWithKey validateMultiOps $
|
|
|
|
OMap.groupTuples itemsWithOps
|
|
|
|
case eitherResult of
|
|
|
|
-- A column shouldn't be present in more than one operator.
|
|
|
|
-- If present, then generated UPDATE statement throws unexpected query error
|
|
|
|
Left columnsWithMultiOps -> throwVE $
|
|
|
|
"column found in multiple operators; "
|
|
|
|
<> T.intercalate ". "
|
|
|
|
(map (\(col, ops) -> col <<> " in " <> showNames ops)
|
|
|
|
columnsWithMultiOps)
|
|
|
|
Right items -> pure $ resolvedPreSetItems <> OMap.toList items
|
2018-06-27 16:11:32 +03:00
|
|
|
|
2020-02-13 20:38:23 +03:00
|
|
|
convertUpdateGeneric
|
2019-10-16 17:33:34 +03:00
|
|
|
:: ( MonadReusability m, MonadError QErr m
|
2020-02-13 20:38:23 +03:00
|
|
|
, MonadReader r m
|
|
|
|
, Has SQLGenCtx r
|
2019-04-17 12:48:41 +03:00
|
|
|
)
|
|
|
|
=> UpdOpCtx -- the update context
|
2020-02-13 20:38:23 +03:00
|
|
|
-> (ArgsMap -> m AnnBoolExpUnresolved) -- the bool exp parser
|
|
|
|
-> (Field -> m (RR.MutationOutputG UnresolvedVal)) -- the selection set resolver
|
|
|
|
-> Field
|
2019-04-17 12:48:41 +03:00
|
|
|
-> m RespTx
|
2020-02-13 20:38:23 +03:00
|
|
|
convertUpdateGeneric opCtx boolExpParser selectionResolver fld = do
|
|
|
|
annUpdUnresolved <- convertUpdateP1 opCtx boolExpParser selectionResolver fld
|
2019-04-17 12:48:41 +03:00
|
|
|
(annUpdResolved, prepArgs) <- withPrepArgs $ RU.traverseAnnUpd
|
|
|
|
resolveValPrep annUpdUnresolved
|
2019-03-25 21:25:25 +03:00
|
|
|
strfyNum <- stringifyNum <$> asks getter
|
2019-04-17 12:48:41 +03:00
|
|
|
let whenNonEmptyItems = return $ RU.updateQueryToTx strfyNum
|
|
|
|
(annUpdResolved, prepArgs)
|
2019-03-25 21:25:25 +03:00
|
|
|
whenEmptyItems = return $ return $
|
2020-02-13 20:38:23 +03:00
|
|
|
buildEmptyMutResp $ RU.uqp1Output annUpdResolved
|
2019-03-25 21:25:25 +03:00
|
|
|
-- if there are not set items then do not perform
|
|
|
|
-- update and return empty mutation response
|
2019-04-17 12:48:41 +03:00
|
|
|
bool whenNonEmptyItems whenEmptyItems $ null $ RU.uqp1SetExps annUpdResolved
|
2019-03-25 21:25:25 +03:00
|
|
|
|
2020-02-13 20:38:23 +03:00
|
|
|
convertUpdate
|
|
|
|
:: ( MonadReusability m, MonadError QErr m
|
|
|
|
, MonadReader r m, Has FieldMap r
|
|
|
|
, Has OrdByCtx r, Has SQLGenCtx r
|
|
|
|
)
|
|
|
|
=> UpdOpCtx -- the update context
|
|
|
|
-> Field -- the mutation field
|
|
|
|
-> m RespTx
|
|
|
|
convertUpdate opCtx =
|
|
|
|
convertUpdateGeneric opCtx whereExpressionParser mutationFieldsResolver
|
|
|
|
|
|
|
|
convertUpdateByPk
|
2019-10-16 17:33:34 +03:00
|
|
|
:: ( MonadReusability m, MonadError QErr m
|
2019-04-17 12:48:41 +03:00
|
|
|
, MonadReader r m, Has FieldMap r
|
|
|
|
, Has OrdByCtx r, Has SQLGenCtx r
|
|
|
|
)
|
2020-02-13 20:38:23 +03:00
|
|
|
=> UpdOpCtx -- the update context
|
|
|
|
-> Field -- the mutation field
|
|
|
|
-> m RespTx
|
|
|
|
convertUpdateByPk opCtx field =
|
|
|
|
convertUpdateGeneric opCtx boolExpParser tableSelectionAsMutationOutput field
|
|
|
|
where
|
|
|
|
boolExpParser args = withArg args "pk_columns" $ \inpVal -> do
|
|
|
|
obj <- asObject inpVal
|
|
|
|
pgColValToBoolExp (_uocAllCols opCtx) $ Map.fromList $ OMap.toList obj
|
|
|
|
|
|
|
|
|
|
|
|
convertDeleteGeneric
|
|
|
|
:: ( MonadReusability m
|
|
|
|
, MonadReader r m
|
|
|
|
, Has SQLGenCtx r
|
|
|
|
)
|
2019-04-17 12:48:41 +03:00
|
|
|
=> DelOpCtx -- the delete context
|
2020-02-13 20:38:23 +03:00
|
|
|
-> (ArgsMap -> m AnnBoolExpUnresolved) -- the bool exp parser
|
|
|
|
-> (Field -> m (RR.MutationOutputG UnresolvedVal)) -- the selection set resolver
|
2018-06-27 16:11:32 +03:00
|
|
|
-> Field -- the mutation field
|
2019-04-17 12:48:41 +03:00
|
|
|
-> m RespTx
|
2020-02-13 20:38:23 +03:00
|
|
|
convertDeleteGeneric opCtx boolExpParser selectionResolver fld = do
|
|
|
|
whereExp <- boolExpParser $ _fArguments fld
|
|
|
|
mutOutput <- selectionResolver fld
|
2019-04-17 12:48:41 +03:00
|
|
|
let unresolvedPermFltr =
|
|
|
|
fmapAnnBoolExp partialSQLExpToUnresolvedVal filterExp
|
|
|
|
annDelUnresolved = RD.AnnDel tn (unresolvedPermFltr, whereExp)
|
2020-02-13 20:38:23 +03:00
|
|
|
mutOutput allCols
|
2019-04-17 12:48:41 +03:00
|
|
|
(annDelResolved, prepArgs) <- withPrepArgs $ RD.traverseAnnDel
|
|
|
|
resolveValPrep annDelUnresolved
|
2019-03-01 14:45:04 +03:00
|
|
|
strfyNum <- stringifyNum <$> asks getter
|
2019-04-17 12:48:41 +03:00
|
|
|
return $ RD.deleteQueryToTx strfyNum (annDelResolved, prepArgs)
|
2019-02-22 13:27:38 +03:00
|
|
|
where
|
2020-02-13 20:38:23 +03:00
|
|
|
DelOpCtx tn _ colGNameMap filterExp = opCtx
|
|
|
|
allCols = Map.elems colGNameMap
|
|
|
|
|
|
|
|
convertDelete
|
|
|
|
:: ( MonadReusability m, MonadError QErr m
|
|
|
|
, MonadReader r m, Has FieldMap r
|
|
|
|
, Has OrdByCtx r, Has SQLGenCtx r
|
|
|
|
)
|
|
|
|
=> DelOpCtx -- the delete context
|
|
|
|
-> Field -- the mutation field
|
|
|
|
-> m RespTx
|
|
|
|
convertDelete opCtx =
|
|
|
|
convertDeleteGeneric opCtx whereExpressionParser mutationFieldsResolver
|
|
|
|
|
|
|
|
convertDeleteByPk
|
|
|
|
:: ( MonadReusability m, MonadError QErr m
|
|
|
|
, MonadReader r m, Has FieldMap r
|
|
|
|
, Has OrdByCtx r, Has SQLGenCtx r
|
|
|
|
)
|
|
|
|
=> DelOpCtx -- the delete context
|
|
|
|
-> Field -- the mutation field
|
|
|
|
-> m RespTx
|
|
|
|
convertDeleteByPk opCtx field =
|
|
|
|
convertDeleteGeneric opCtx boolExpParser tableSelectionAsMutationOutput field
|
|
|
|
where
|
|
|
|
boolExpParser = pgColValToBoolExp (_docAllCols opCtx)
|
|
|
|
|
|
|
|
whereExpressionParser
|
|
|
|
:: ( MonadReusability m, MonadError QErr m
|
|
|
|
, MonadReader r m, Has FieldMap r
|
|
|
|
)
|
|
|
|
=> ArgsMap -> m AnnBoolExpUnresolved
|
|
|
|
whereExpressionParser args = withArg args "where" parseBoolExp
|
|
|
|
|
|
|
|
mutationFieldsResolver
|
|
|
|
:: ( MonadReusability m, MonadError QErr m
|
|
|
|
, MonadReader r m, Has FieldMap r
|
|
|
|
, Has OrdByCtx r, Has SQLGenCtx r
|
|
|
|
)
|
|
|
|
=> Field -> m (RR.MutationOutputG UnresolvedVal)
|
|
|
|
mutationFieldsResolver field =
|
|
|
|
RR.MOutMultirowFields <$> resolveMutationFields (_fType field) (_fSelSet field)
|
|
|
|
|
|
|
|
tableSelectionAsMutationOutput
|
|
|
|
:: ( MonadReusability m, MonadError QErr m
|
|
|
|
, MonadReader r m, Has FieldMap r
|
|
|
|
, Has OrdByCtx r, Has SQLGenCtx r
|
|
|
|
)
|
|
|
|
=> Field -> m (RR.MutationOutputG UnresolvedVal)
|
|
|
|
tableSelectionAsMutationOutput field =
|
|
|
|
RR.MOutSinglerowObject <$> processTableSelectionSet (_fType field) (_fSelSet field)
|
2019-01-28 10:24:24 +03:00
|
|
|
|
|
|
|
-- | build mutation response for empty objects
|
2020-02-13 20:38:23 +03:00
|
|
|
buildEmptyMutResp :: RR.MutationOutput -> EncJSON
|
2019-03-18 19:22:21 +03:00
|
|
|
buildEmptyMutResp = mkTx
|
2019-01-28 10:24:24 +03:00
|
|
|
where
|
2020-02-13 20:38:23 +03:00
|
|
|
mkTx = \case
|
|
|
|
RR.MOutMultirowFields mutFlds -> encJFromJValue $ OMap.fromList $ map (second convMutFld) mutFlds
|
|
|
|
RR.MOutSinglerowObject _ -> encJFromJValue $ J.Object mempty
|
2019-01-28 10:24:24 +03:00
|
|
|
-- generate empty mutation response
|
|
|
|
convMutFld = \case
|
|
|
|
RR.MCount -> J.toJSON (0 :: Int)
|
|
|
|
RR.MExp e -> J.toJSON e
|
|
|
|
RR.MRet _ -> J.toJSON ([] :: [J.Value])
|
2020-02-13 20:38:23 +03:00
|
|
|
|
|
|
|
resolveValPrep
|
|
|
|
:: (MonadState PrepArgs m)
|
|
|
|
=> UnresolvedVal -> m S.SQLExp
|
|
|
|
resolveValPrep = \case
|
|
|
|
UVPG annPGVal -> prepare annPGVal
|
|
|
|
UVSessVar colTy sessVar -> sessVarFromCurrentSetting colTy sessVar
|
|
|
|
UVSQL sqlExp -> pure sqlExp
|
|
|
|
UVSession -> pure currentSession
|