graphql-engine/server/src-lib/Hasura/Backends/Postgres/Translate/Mutation.hs
Antoine Leblanc f684fecc6c Cut ties with RQL.DML.Internal
## Description

As the name suggests, `DML.Internal` contains internal implementation details of RQL's DML. However, a lot of unrelated parts of the codebase still use some of the code it contains. This PR fixes this, and removes all imports of `RQL.DML.Internal` from outside of `RQL.DML`. Most of the time, this involves moving a function out of `DML.Internal` to an underlying module (see `getRolePermInfo`) or moving a function _back_ into it (see `checkRetCols`).

This PR also clarifies a bit the situation with `withTyAnn` and `withTypeAnn` by renaming the former into `withScalarTypeAnn` and moving them together. Worth noting: there might be a bug lurking in that function, as it doesn't seem to use the proper type annotations for some extension types!

PR-URL: https://github.com/hasura/graphql-engine-mono/pull/4380
GitOrigin-RevId: c8ae5b4e8378fefc0bcccf778d97813df727d3cb
2022-04-27 15:37:23 +00:00

71 lines
2.5 KiB
Haskell

-- | Postgres Translate Mutation
--
-- Provide a combinator for generating a Postgres SQL SELECT statement for the
-- selected columns in mutation queries.
--
-- See 'Hasura.Backends.Postgres.Execute.Mutation' and note
-- [Prepared statements in Mutations]
module Hasura.Backends.Postgres.Translate.Mutation
( mkSelectExpFromColumnValues,
)
where
import Data.HashMap.Strict qualified as Map
import Data.Text.Extended
import Hasura.Backends.Postgres.SQL.DML qualified as S
import Hasura.Backends.Postgres.SQL.Types
import Hasura.Backends.Postgres.SQL.Value
import Hasura.Backends.Postgres.Types.Column
import Hasura.Base.Error
import Hasura.Prelude
import Hasura.RQL.Types.Column
import Hasura.RQL.Types.Table
import Hasura.SQL.Backend
import Hasura.SQL.Types
-- | Note:- Using sorted columns is necessary to enable casting the rows returned by VALUES expression to table type.
-- For example, let's consider the table, `CREATE TABLE test (id serial primary key, name text not null, age int)`.
-- The generated values expression should be in order of columns;
-- `SELECT ("row"::table).* VALUES (1, 'Robert', 23) AS "row"`.
mkSelectExpFromColumnValues ::
forall pgKind m.
MonadError QErr m =>
QualifiedTable ->
[ColumnInfo ('Postgres pgKind)] ->
[ColumnValues ('Postgres pgKind) TxtEncodedVal] ->
m S.Select
mkSelectExpFromColumnValues qt allCols = \case
[] -> return selNoRows
colVals -> do
tuples <- mapM mkTupsFromColVal colVals
let fromItem = S.FIValues (S.ValuesExp tuples) (S.Alias rowAlias) Nothing
return
S.mkSelect
{ S.selExtr = [extractor],
S.selFrom = Just $ S.FromExp [fromItem]
}
where
rowAlias = Identifier "row"
extractor = S.selectStar' $ S.QualifiedIdentifier rowAlias $ Just $ S.TypeAnn $ toSQLTxt qt
sortedCols = sortCols allCols
mkTupsFromColVal colVal =
fmap S.TupleExp $
forM sortedCols $ \ci -> do
let pgCol = ciColumn ci
val <-
onNothing (Map.lookup pgCol colVal) $
throw500 $ "column " <> pgCol <<> " not found in returning values"
pure $ txtEncodedToSQLExp (ciType ci) val
selNoRows =
S.mkSelect
{ S.selExtr = [S.selectStar],
S.selFrom = Just $ S.mkSimpleFromExp qt,
S.selWhere = Just $ S.WhereFrag $ S.BELit False
}
txtEncodedToSQLExp colTy = \case
TENull -> S.SENull
TELit textValue ->
withScalarTypeAnn (unsafePGColumnToBackend colTy) $ S.SELit textValue