graphql-engine/server/src-lib/Hasura/RQL/DML/Delete.hs
Antoine Leblanc d8c56a40f6 server: split boolean operators between core and backend-specific
GitOrigin-RevId: f1291946a1122220e82371676d88867fd7b2b7c4
2021-03-25 17:51:08 +00:00

110 lines
3.6 KiB
Haskell

module Hasura.RQL.DML.Delete
( validateDeleteQWith
, validateDeleteQ
, AnnDelG(..)
, traverseAnnDel
, AnnDel
, execDeleteQuery
, runDelete
) where
import Hasura.Prelude
import qualified Data.Environment as Env
import qualified Data.Sequence as DS
import qualified Database.PG.Query as Q
import Control.Monad.Trans.Control (MonadBaseControl)
import Data.Aeson
import qualified Hasura.Backends.Postgres.SQL.DML as S
import qualified Hasura.Tracing as Tracing
import Hasura.Backends.Postgres.Connection
import Hasura.Backends.Postgres.Execute.Mutation
import Hasura.Backends.Postgres.Translate.Returning
import Hasura.Backends.Postgres.Types.Table
import Hasura.EncJSON
import Hasura.RQL.DML.Internal
import Hasura.RQL.DML.Types
import Hasura.RQL.IR.Delete
import Hasura.RQL.Types
import Hasura.RQL.Types.Run
import Hasura.Server.Version (HasVersion)
import Hasura.Session
validateDeleteQWith
:: (UserInfoM m, QErrM m, TableInfoRM 'Postgres m)
=> SessVarBldr 'Postgres m
-> (ColumnType 'Postgres -> Value -> m S.SQLExp)
-> DeleteQuery
-> m (AnnDel 'Postgres)
validateDeleteQWith sessVarBldr prepValBldr
(DeleteQuery tableName _ rqlBE mRetCols) = do
tableInfo <- askTabInfoSource tableName
let coreInfo = _tiCoreInfo tableInfo
-- If table is view then check if it deletable
mutableView tableName viIsDeletable
(_tciViewInfo coreInfo) "deletable"
-- Check if the role has delete permissions
delPerm <- askDelPermInfo tableInfo
-- Check if all dependent headers are present
validateHeaders $ dpiRequiredHeaders delPerm
-- Check if select is allowed
selPerm <- modifyErr (<> selNecessaryMsg) $
askSelPermInfo tableInfo
let fieldInfoMap = _tciFieldInfoMap coreInfo
allCols = getCols fieldInfoMap
-- convert the returning cols into sql returing exp
mAnnRetCols <- forM mRetCols $ \retCols ->
withPathK "returning" $ checkRetCols fieldInfoMap selPerm retCols
-- convert the where clause
annSQLBoolExp <- withPathK "where" $
convBoolExp fieldInfoMap selPerm rqlBE sessVarBldr (valueParserWithCollectableType prepValBldr)
resolvedDelFltr <- convAnnBoolExpPartialSQL sessVarBldr $
dpiFilter delPerm
return $ AnnDel tableName
(resolvedDelFltr, annSQLBoolExp)
(mkDefaultMutFlds mAnnRetCols) allCols
where
selNecessaryMsg =
"; \"delete\" is only allowed if the role "
<> "has \"select\" permission as \"where\" can't be used "
<> "without \"select\" permission on the table"
validateDeleteQ
:: (QErrM m, UserInfoM m, CacheRM m)
=> DeleteQuery -> m (AnnDel 'Postgres, DS.Seq Q.PrepArg)
validateDeleteQ query = do
let source = doSource query
tableCache :: TableCache 'Postgres <- askTableCache source
flip runTableCacheRT (source, tableCache) $ runDMLP1T $
validateDeleteQWith sessVarFromCurrentSetting binRHSBuilder query
runDelete
:: ( HasVersion, QErrM m, UserInfoM m, CacheRM m
, HasServerConfigCtx m, MonadIO m
, Tracing.MonadTrace m, MonadBaseControl IO m
, MetadataM m
)
=> Env.Environment
-> DeleteQuery
-> m EncJSON
runDelete env q = do
sourceConfig <- askSourceConfig (doSource q)
strfyNum <- stringifyNum . _sccSQLGenCtx <$> askServerConfigCtx
validateDeleteQ q
>>= runQueryLazyTx (_pscExecCtx sourceConfig) Q.ReadWrite
. execDeleteQuery env strfyNum Nothing