2020-10-29 19:58:13 +03:00
|
|
|
module Hasura.Backends.Postgres.Translate.Mutation
|
2020-11-12 12:25:48 +03:00
|
|
|
( mkSelectExpFromColumnValues
|
2020-10-29 19:58:13 +03:00
|
|
|
)
|
|
|
|
where
|
|
|
|
|
|
|
|
import Hasura.Prelude
|
|
|
|
|
|
|
|
import qualified Data.HashMap.Strict as Map
|
|
|
|
|
|
|
|
import Data.Text.Extended
|
|
|
|
|
|
|
|
import qualified Hasura.Backends.Postgres.SQL.DML as S
|
|
|
|
|
|
|
|
import Hasura.Backends.Postgres.SQL.Types
|
|
|
|
import Hasura.Backends.Postgres.SQL.Value
|
|
|
|
import Hasura.RQL.Instances ()
|
|
|
|
import Hasura.RQL.Types
|
|
|
|
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"`.
|
2020-11-12 12:25:48 +03:00
|
|
|
mkSelectExpFromColumnValues
|
2020-10-29 19:58:13 +03:00
|
|
|
:: (MonadError QErr m)
|
2021-02-14 09:07:52 +03:00
|
|
|
=> QualifiedTable -> [ColumnInfo 'Postgres] -> [ColumnValues 'Postgres TxtEncodedPGVal] -> m S.Select
|
2020-11-12 12:25:48 +03:00
|
|
|
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]
|
|
|
|
}
|
2020-10-29 19:58:13 +03:00
|
|
|
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 = pgiColumn ci
|
|
|
|
val <- onNothing (Map.lookup pgCol colVal) $
|
|
|
|
throw500 $ "column " <> pgCol <<> " not found in returning values"
|
|
|
|
pure $ txtEncodedToSQLExp (pgiType 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 ->
|
2020-11-25 17:18:58 +03:00
|
|
|
S.withTyAnn (unsafePGColumnToBackend colTy) $ S.SELit textValue
|