mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-15 01:12:56 +03:00
refactor: QualifiedIdentifier to use TableIdentifier
PR-URL: https://github.com/hasura/graphql-engine-mono/pull/6210 GitOrigin-RevId: 1fa24321396bbb68dd5f8516aab76850ebeebfa4
This commit is contained in:
parent
4fdbda05ec
commit
ee34921d0d
@ -55,6 +55,22 @@ import Language.GraphQL.Draft.Syntax qualified as G
|
||||
----------------------------------------------------------------------------------------------------
|
||||
-- Variables
|
||||
|
||||
subsAlias :: S.TableAlias
|
||||
subsAlias = S.mkTableAlias "_subs"
|
||||
|
||||
subsIdentifier :: TableIdentifier
|
||||
subsIdentifier = S.tableAliasToIdentifier subsAlias
|
||||
|
||||
resultIdAlias, resultVarsAlias :: S.ColumnAlias
|
||||
resultIdAlias = S.mkColumnAlias "result_id"
|
||||
resultVarsAlias = S.mkColumnAlias "result_vars"
|
||||
|
||||
fldRespAlias :: S.TableAlias
|
||||
fldRespAlias = S.mkTableAlias "_fld_resp"
|
||||
|
||||
fldRespIdentifier :: TableIdentifier
|
||||
fldRespIdentifier = S.tableAliasToIdentifier fldRespAlias
|
||||
|
||||
-- | Internal: Used to collect information about various parameters
|
||||
-- of a subscription field's AST as we resolve them to SQL expressions.
|
||||
data QueryParametersInfo (b :: BackendType) = QueryParametersInfo
|
||||
@ -131,8 +147,8 @@ mkMultiplexedQuery rootFields =
|
||||
S.mkSelect
|
||||
{ S.selExtr =
|
||||
-- SELECT _subs.result_id, _fld_resp.root AS result
|
||||
[ S.Extractor (mkQualifiedIdentifier (Identifier "_subs") (Identifier "result_id")) Nothing,
|
||||
S.Extractor (mkQualifiedIdentifier (Identifier "_fld_resp") (Identifier "root")) (Just $ S.toColumnAlias $ Identifier "result")
|
||||
[ S.Extractor (mkQualifiedIdentifier subsIdentifier (Identifier "result_id")) Nothing,
|
||||
S.Extractor (mkQualifiedIdentifier fldRespIdentifier (Identifier "root")) (Just $ S.toColumnAlias $ Identifier "result")
|
||||
],
|
||||
S.selFrom =
|
||||
Just $
|
||||
@ -150,14 +166,14 @@ mkMultiplexedQuery rootFields =
|
||||
[S.toColumnAlias $ Identifier "result_id", S.toColumnAlias $ Identifier "result_vars"]
|
||||
|
||||
-- LEFT OUTER JOIN LATERAL ( ... ) _fld_resp
|
||||
responseLateralFromItem = S.mkLateralFromItem selectRootFields (S.toTableAlias $ Identifier "_fld_resp")
|
||||
responseLateralFromItem = S.mkLateralFromItem selectRootFields fldRespAlias
|
||||
selectRootFields =
|
||||
S.mkSelect
|
||||
{ S.selExtr = [S.Extractor rootFieldsJsonAggregate (Just $ S.toColumnAlias $ Identifier "root")],
|
||||
S.selFrom =
|
||||
Just . S.FromExp $
|
||||
OMap.toList rootFields <&> \(fieldAlias, resolvedAST) ->
|
||||
toSQLFromItem (S.toTableAlias $ aliasToIdentifier fieldAlias) resolvedAST
|
||||
toSQLFromItem (S.mkTableAlias $ G.unName fieldAlias) resolvedAST
|
||||
}
|
||||
|
||||
-- json_build_object('field1', field1.root, 'field2', field2.root, ...)
|
||||
@ -168,7 +184,7 @@ mkMultiplexedQuery rootFields =
|
||||
]
|
||||
|
||||
mkQualifiedIdentifier prefix = S.SEQIdentifier . S.QIdentifier (S.QualifiedIdentifier prefix Nothing)
|
||||
aliasToIdentifier = Identifier . G.unName
|
||||
aliasToIdentifier = TableIdentifier . G.unName
|
||||
|
||||
mkStreamingMultiplexedQuery ::
|
||||
( Backend ('Postgres pgKind),
|
||||
@ -181,9 +197,9 @@ mkStreamingMultiplexedQuery (fieldAlias, resolvedAST) =
|
||||
S.mkSelect
|
||||
{ S.selExtr =
|
||||
-- SELECT _subs.result_id, _fld_resp.root, _fld_resp.cursor AS result
|
||||
[ S.Extractor (mkQualifiedIdentifier (Identifier "_subs") (Identifier "result_id")) Nothing,
|
||||
S.Extractor (mkQualifiedIdentifier (Identifier "_fld_resp") (Identifier "root")) (Just $ S.toColumnAlias $ Identifier "result"),
|
||||
S.Extractor (mkQualifiedIdentifier (Identifier "_fld_resp") (Identifier "cursor")) (Just $ S.toColumnAlias $ Identifier "cursor")
|
||||
[ S.Extractor (mkQualifiedIdentifier subsIdentifier (Identifier "result_id")) Nothing,
|
||||
S.Extractor (mkQualifiedIdentifier fldRespIdentifier (Identifier "root")) (Just $ S.toColumnAlias $ Identifier "result"),
|
||||
S.Extractor (mkQualifiedIdentifier fldRespIdentifier (Identifier "cursor")) (Just $ S.toColumnAlias $ Identifier "cursor")
|
||||
],
|
||||
S.selFrom =
|
||||
Just $
|
||||
@ -197,8 +213,8 @@ mkStreamingMultiplexedQuery (fieldAlias, resolvedAST) =
|
||||
subsInputFromItem =
|
||||
S.FIUnnest
|
||||
[S.SEPrep 1 `S.SETyAnn` S.TypeAnn "uuid[]", S.SEPrep 2 `S.SETyAnn` S.TypeAnn "json[]"]
|
||||
(S.toTableAlias $ Identifier "_subs")
|
||||
[S.toColumnAlias $ Identifier "result_id", S.toColumnAlias $ Identifier "result_vars"]
|
||||
subsAlias
|
||||
[resultIdAlias, resultVarsAlias]
|
||||
|
||||
-- LEFT OUTER JOIN LATERAL ( ... ) _fld_resp
|
||||
responseLateralFromItem = S.mkLateralFromItem selectRootFields (S.toTableAlias $ Identifier "_fld_resp")
|
||||
@ -207,7 +223,7 @@ mkStreamingMultiplexedQuery (fieldAlias, resolvedAST) =
|
||||
{ S.selExtr = [(S.Extractor rootFieldJsonAggregate (Just $ S.toColumnAlias $ Identifier "root")), cursorExtractor],
|
||||
S.selFrom =
|
||||
Just . S.FromExp $
|
||||
pure $ toSQLFromItem (S.toTableAlias $ aliasToIdentifier fieldAlias) resolvedAST
|
||||
pure $ toSQLFromItem (S.mkTableAlias $ G.unName fieldAlias) resolvedAST
|
||||
}
|
||||
|
||||
-- json_build_object('field1', field1.root, 'field2', field2.root, ...)
|
||||
@ -221,7 +237,7 @@ mkStreamingMultiplexedQuery (fieldAlias, resolvedAST) =
|
||||
cursorSQLExp = S.SEFnApp "to_json" [mkQualifiedIdentifier (aliasToIdentifier fieldAlias) (Identifier "cursor")] Nothing
|
||||
cursorExtractor = S.Extractor cursorSQLExp (Just $ S.toColumnAlias $ Identifier "cursor")
|
||||
mkQualifiedIdentifier prefix = S.SEQIdentifier . S.QIdentifier (S.QualifiedIdentifier prefix Nothing)
|
||||
aliasToIdentifier = Identifier . G.unName
|
||||
aliasToIdentifier = TableIdentifier . G.unName
|
||||
|
||||
-- | Resolves an 'GR.UnresolvedVal' by converting 'GR.UVPG' values to SQL
|
||||
-- expressions that refer to the @result_vars@ input object, collecting information
|
||||
@ -262,7 +278,7 @@ resolveMultiplexedValue allSessionVars = \case
|
||||
addTypeAnnotation pgType $
|
||||
S.SEOpApp
|
||||
(S.SQLOp "#>>")
|
||||
[ S.SEQIdentifier $ S.QIdentifier (S.QualifiedIdentifier (Identifier "_subs") Nothing) (Identifier "result_vars"),
|
||||
[ S.SEQIdentifier $ S.QIdentifier (S.QualifiedIdentifier subsIdentifier Nothing) (Identifier "result_vars"),
|
||||
S.SEArray $ map S.SELit jPath
|
||||
]
|
||||
addTypeAnnotation pgType =
|
||||
|
@ -96,10 +96,12 @@ module Hasura.Backends.Postgres.SQL.DML
|
||||
simplifyBoolExp,
|
||||
textArrTypeAnn,
|
||||
textTypeAnn,
|
||||
mkColumnAlias,
|
||||
mkTableAlias,
|
||||
toTableAlias,
|
||||
tableAliasToIdentifier,
|
||||
toColumnAlias,
|
||||
tableIdentifierToColumnAlias,
|
||||
)
|
||||
where
|
||||
|
||||
@ -108,6 +110,7 @@ import Data.Aeson.Casing qualified as J
|
||||
import Data.HashMap.Strict qualified as HM
|
||||
import Data.Int (Int64)
|
||||
import Data.String (fromString)
|
||||
import Data.Text (pack)
|
||||
import Data.Text.Extended
|
||||
import Hasura.Backends.Postgres.SQL.Types
|
||||
import Hasura.Incremental (Cacheable)
|
||||
@ -326,11 +329,11 @@ instance ToSQL Select where
|
||||
mkSIdenExp :: (IsIdentifier a) => a -> SQLExp
|
||||
mkSIdenExp = SEIdentifier . toIdentifier
|
||||
|
||||
mkQIdenExp :: (IsIdentifier a, IsIdentifier b) => a -> b -> SQLExp
|
||||
mkQIdenExp :: (IsIdentifier b) => TableIdentifier -> b -> SQLExp
|
||||
mkQIdenExp q t = SEQIdentifier $ mkQIdentifier q t
|
||||
|
||||
data Qual
|
||||
= QualifiedIdentifier Identifier (Maybe TypeAnn)
|
||||
= QualifiedIdentifier TableIdentifier (Maybe TypeAnn)
|
||||
| QualTable QualifiedTable
|
||||
| QualVar Text
|
||||
deriving (Show, Eq, Generic, Data)
|
||||
@ -350,8 +353,8 @@ instance ToSQL Qual where
|
||||
toSQL (QualTable qt) = toSQL qt
|
||||
toSQL (QualVar v) = TB.text v
|
||||
|
||||
mkQIdentifier :: (IsIdentifier a, IsIdentifier b) => a -> b -> QIdentifier
|
||||
mkQIdentifier q t = QIdentifier (QualifiedIdentifier (toIdentifier q) Nothing) (toIdentifier t)
|
||||
mkQIdentifier :: (IsIdentifier b) => TableIdentifier -> b -> QIdentifier
|
||||
mkQIdentifier q t = QIdentifier (QualifiedIdentifier q Nothing) (toIdentifier t)
|
||||
|
||||
mkQIdentifierTable :: (IsIdentifier a) => QualifiedTable -> a -> QIdentifier
|
||||
mkQIdentifierTable q = QIdentifier (mkQual q) . toIdentifier
|
||||
@ -505,9 +508,21 @@ instance J.ToJSON SQLExp where
|
||||
newtype ColumnAlias = ColumnAlias {getColumnAlias :: Identifier}
|
||||
deriving (Show, Eq, NFData, Data, Cacheable, Hashable)
|
||||
|
||||
instance IsString ColumnAlias where
|
||||
fromString = mkColumnAlias . pack
|
||||
|
||||
instance Semigroup ColumnAlias where
|
||||
(ColumnAlias ca1) <> (ColumnAlias ca2) = ColumnAlias (ca1 <> ca2)
|
||||
|
||||
mkColumnAlias :: Text -> ColumnAlias
|
||||
mkColumnAlias = ColumnAlias . Identifier
|
||||
|
||||
instance IsIdentifier ColumnAlias where
|
||||
toIdentifier (ColumnAlias identifier) = identifier
|
||||
|
||||
tableIdentifierToColumnAlias :: TableIdentifier -> ColumnAlias
|
||||
tableIdentifierToColumnAlias = mkColumnAlias . unTableIdentifier
|
||||
|
||||
toColumnAlias :: (IsIdentifier a) => a -> ColumnAlias
|
||||
toColumnAlias = ColumnAlias . toIdentifier
|
||||
|
||||
@ -523,6 +538,12 @@ columnAliasToSqlWithoutAs alias = toSQL (toIdentifier alias)
|
||||
newtype TableAlias = TableAlias {getTableAlias :: Identifier}
|
||||
deriving (Show, Eq, NFData, Data, Generic, Cacheable, Hashable)
|
||||
|
||||
instance IsString TableAlias where
|
||||
fromString = mkTableAlias . pack
|
||||
|
||||
instance Semigroup TableAlias where
|
||||
(TableAlias ta1) <> (TableAlias ta2) = TableAlias (ta1 <> ta2)
|
||||
|
||||
-- | Create a table alias.
|
||||
mkTableAlias :: Text -> TableAlias
|
||||
mkTableAlias = TableAlias . Identifier
|
||||
|
@ -396,7 +396,7 @@ uSqlExp =
|
||||
-- rename the table alias if needed
|
||||
uQual = \case
|
||||
S.QualifiedIdentifier identifier typeAnnotation ->
|
||||
S.QualifiedIdentifier <$> getTableNameAndPrefixHash identifier <*> pure typeAnnotation
|
||||
S.QualifiedIdentifier <$> getTableIdentifierAndPrefixHash identifier <*> pure typeAnnotation
|
||||
-- refers to a database table
|
||||
S.QualTable t -> pure $ S.QualTable t
|
||||
S.QualVar t -> pure $ S.QualVar t
|
||||
|
@ -63,6 +63,7 @@ import Data.Aeson.TH
|
||||
import Data.Aeson.Types (toJSONKeyText)
|
||||
import Data.Int
|
||||
import Data.List (uncons)
|
||||
import Data.String
|
||||
import Data.Text qualified as T
|
||||
import Data.Text.Casing qualified as C
|
||||
import Data.Text.Extended
|
||||
@ -84,6 +85,26 @@ import Language.GraphQL.Draft.Syntax qualified as G
|
||||
import PostgreSQL.Binary.Decoding qualified as PD
|
||||
import Text.Builder qualified as TB
|
||||
|
||||
{- Note [About identifier types]
|
||||
|
||||
In order to better be able to reason about values representing SQL binders and
|
||||
variables we are in the process of retiring the generic 'Identifier' type in
|
||||
favor of the more specific types 'TableIdentifier' and 'ColumnIdentifier'.
|
||||
|
||||
Likewise, we distinguish binders of names from uses of names: The types
|
||||
'TableAlias' and `ColumnAlias` are used to for binders, whereas
|
||||
`TableIdentifier` and `ColumnIdentifier` represent usages or references of
|
||||
previously bound names.
|
||||
|
||||
We want to ensure these are handled in an hygenic way:
|
||||
* 'TableAlias'es and 'ColumnAlias'es can be constructed freely, but
|
||||
* 'TableIdentifier' can only be constructed from a 'TableAlias' via
|
||||
'tableAliasToIdentifier', and
|
||||
* 'ColumnIdentifier's can only be constructed from a 'ColumnAlias', and
|
||||
potentially be qualified with a 'TableIdentifier'.
|
||||
|
||||
-}
|
||||
|
||||
newtype Identifier = Identifier {getIdenTxt :: Text}
|
||||
deriving (Show, Eq, NFData, FromJSON, ToJSON, Hashable, Semigroup, Data, Cacheable)
|
||||
|
||||
@ -97,7 +118,9 @@ class IsIdentifier a where
|
||||
instance IsIdentifier Identifier where
|
||||
toIdentifier = id
|
||||
|
||||
-- | The type of identifiers representing tabular values
|
||||
-- | The type of identifiers representing tabular values.
|
||||
-- While we are transitioning away from 'Identifier' we provisionally export
|
||||
-- the value constructor.
|
||||
newtype TableIdentifier = TableIdentifier {unTableIdentifier :: Text}
|
||||
deriving (Show, Eq, NFData, FromJSON, ToJSON, Hashable, Semigroup, Data, Cacheable)
|
||||
|
||||
|
@ -166,11 +166,12 @@ translateBoolExp = \case
|
||||
return $ sqlAnd bExps
|
||||
AVRelationship (RelInfo _ _ colMapping relTN _ _) nesAnn -> do
|
||||
-- Convert the where clause on the relationship
|
||||
aliasRelTN <- freshIdentifier relTN
|
||||
annRelBoolExp <- withCurrentTable (S.QualifiedIdentifier aliasRelTN Nothing) (translateBoolExp nesAnn)
|
||||
tableRelExp <- translateTableRelationship colMapping aliasRelTN
|
||||
relTNAlias <- S.toTableAlias <$> freshIdentifier relTN
|
||||
let relTNIdentifier = S.tableAliasToIdentifier relTNAlias
|
||||
annRelBoolExp <- withCurrentTable (S.QualifiedIdentifier relTNIdentifier Nothing) (translateBoolExp nesAnn)
|
||||
tableRelExp <- translateTableRelationship colMapping relTNIdentifier
|
||||
let innerBoolExp = S.BEBin S.AndOp tableRelExp annRelBoolExp
|
||||
return $ S.mkExists (S.FISimple relTN $ Just $ S.toTableAlias aliasRelTN) innerBoolExp
|
||||
return $ S.mkExists (S.FISimple relTN $ Just $ relTNAlias) innerBoolExp
|
||||
AVComputedField (AnnComputedFieldBoolExp _ _ function sessionArgPresence cfBoolExp) -> do
|
||||
case cfBoolExp of
|
||||
CFBEScalar opExps -> do
|
||||
@ -181,11 +182,12 @@ translateBoolExp = \case
|
||||
CFBETable _ be -> do
|
||||
-- Convert the where clause on table computed field
|
||||
BoolExpCtx {currTableReference} <- ask
|
||||
aliasFunction <- freshIdentifier function
|
||||
let functionExp =
|
||||
functionAlias <- S.toTableAlias <$> freshIdentifier function
|
||||
let functionIdentifier = S.tableAliasToIdentifier functionAlias
|
||||
functionExp =
|
||||
mkComputedFieldFunctionExp currTableReference function sessionArgPresence $
|
||||
Just $ S.toTableAlias aliasFunction
|
||||
S.mkExists (S.FIFunc functionExp) <$> withCurrentTable (S.QualifiedIdentifier aliasFunction Nothing) (translateBoolExp be)
|
||||
Just $ functionAlias
|
||||
S.mkExists (S.FIFunc functionExp) <$> withCurrentTable (S.QualifiedIdentifier functionIdentifier Nothing) (translateBoolExp be)
|
||||
AVAggregationPredicates aggPreds -> translateAVAggregationPredicates aggPreds
|
||||
|
||||
-- | Call a given translation action recursively using the given identifier for the 'current' table.
|
||||
@ -236,40 +238,42 @@ translateAVAggregationPredicates ::
|
||||
translateAVAggregationPredicates
|
||||
api@(AggregationPredicatesImplementation (RelInfo {riRTable = relTableName, riMapping = colMapping}) _rowPermissions predicate) = do
|
||||
-- e.g. __be_0_<schema>_<table_name>
|
||||
relTableNameAlias <- freshIdentifier relTableName
|
||||
tableRelExp <- translateTableRelationship colMapping relTableNameAlias
|
||||
let subselectAlias = Identifier "_sub"
|
||||
relTable = S.QualifiedIdentifier relTableNameAlias Nothing
|
||||
relTableNameAlias <- S.toTableAlias <$> freshIdentifier relTableName
|
||||
let relTableNameIdentifier = S.tableAliasToIdentifier relTableNameAlias
|
||||
tableRelExp <- translateTableRelationship colMapping relTableNameIdentifier
|
||||
let subselectAlias = S.mkTableAlias "_sub"
|
||||
subselectIdentifier = S.tableAliasToIdentifier subselectAlias
|
||||
relTable = S.QualifiedIdentifier relTableNameIdentifier Nothing
|
||||
subselect <-
|
||||
local
|
||||
(\e -> e {currTableReference = relTable, rootReference = relTable})
|
||||
$ translateAggPredsSubselect subselectAlias relTableNameAlias tableRelExp api
|
||||
outerWhereFrag <- translateAggPredBoolExp relTableName subselectAlias predicate
|
||||
outerWhereFrag <- translateAggPredBoolExp relTableName subselectIdentifier predicate
|
||||
pure $ S.mkExists subselect outerWhereFrag
|
||||
|
||||
translateAggPredBoolExp ::
|
||||
forall pgKind.
|
||||
TableName ('Postgres pgKind) ->
|
||||
Identifier ->
|
||||
TableIdentifier ->
|
||||
AggregationPredicate ('Postgres pgKind) S.SQLExp ->
|
||||
BoolExpM S.BoolExp
|
||||
translateAggPredBoolExp
|
||||
relTableName
|
||||
subselectAlias
|
||||
subselectIdentifier
|
||||
(AggregationPredicate {aggPredFunctionName, aggPredPredicate}) = do
|
||||
BoolExpCtx {rootReference} <- ask
|
||||
let (Identifier aggAlias) = identifierWithSuffix relTableName aggPredFunctionName
|
||||
boolExps =
|
||||
map
|
||||
(mkFieldCompExp rootReference (S.QualifiedIdentifier subselectAlias Nothing) $ LColumn (FieldName aggAlias))
|
||||
(mkFieldCompExp rootReference (S.QualifiedIdentifier subselectIdentifier Nothing) $ LColumn (FieldName aggAlias))
|
||||
aggPredPredicate
|
||||
pure $ sqlAnd boolExps
|
||||
|
||||
translateAggPredsSubselect ::
|
||||
forall pgKind.
|
||||
(Backend ('Postgres pgKind)) =>
|
||||
Identifier ->
|
||||
Identifier ->
|
||||
S.TableAlias ->
|
||||
S.TableAlias ->
|
||||
S.BoolExp ->
|
||||
AggregationPredicatesImplementation ('Postgres pgKind) S.SQLExp ->
|
||||
BoolExpM S.FromItem
|
||||
@ -284,8 +288,9 @@ translateAggPredsSubselect
|
||||
) = do
|
||||
mFilter <- traverse translateBoolExp (aggPredFilter predicate)
|
||||
rowPermExp <- translateBoolExp rowPermissions
|
||||
let -- SELECT <aggregate_function> AS <aggregate_function_alias>
|
||||
extractorsExp = translateAggPredExtractor relTableNameAlias relTableName predicate
|
||||
let relTableNameIdentifier = S.tableAliasToIdentifier relTableNameAlias
|
||||
-- SELECT <aggregate_function> AS <aggregate_function_alias>
|
||||
extractorsExp = translateAggPredExtractor relTableNameIdentifier relTableName predicate
|
||||
-- FROM <array_relationship_table> AS <array_relationship_table_alias>
|
||||
fromExp = pure $ S.FISimple relTableName $ Just $ S.toTableAlias relTableNameAlias
|
||||
-- WHERE <relationship_table_key> AND <row_permissions> AND <mFilter>
|
||||
@ -297,39 +302,39 @@ translateAggPredsSubselect
|
||||
S.selFrom = Just $ S.FromExp fromExp,
|
||||
S.selWhere = Just $ S.WhereFrag whereExp
|
||||
}
|
||||
(S.toTableAlias subselectAlias)
|
||||
subselectAlias
|
||||
|
||||
translateAggPredExtractor ::
|
||||
forall pgKind field.
|
||||
Identifier ->
|
||||
TableIdentifier ->
|
||||
TableName ('Postgres pgKind) ->
|
||||
AggregationPredicate ('Postgres pgKind) field ->
|
||||
S.Extractor
|
||||
translateAggPredExtractor relTableNameAlias relTableName (AggregationPredicate {aggPredFunctionName, aggPredArguments}) =
|
||||
let predArgsExp = toList $ translateAggPredArguments aggPredArguments relTableNameAlias
|
||||
translateAggPredExtractor relTableNameIdentifier relTableName (AggregationPredicate {aggPredFunctionName, aggPredArguments}) =
|
||||
let predArgsExp = toList $ translateAggPredArguments aggPredArguments relTableNameIdentifier
|
||||
aggAlias = S.toColumnAlias $ identifierWithSuffix relTableName aggPredFunctionName
|
||||
in S.Extractor (S.SEFnApp aggPredFunctionName predArgsExp Nothing) (Just aggAlias)
|
||||
|
||||
translateAggPredArguments ::
|
||||
forall pgKind.
|
||||
AggregationPredicateArguments ('Postgres pgKind) ->
|
||||
Identifier ->
|
||||
TableIdentifier ->
|
||||
NonEmpty S.SQLExp
|
||||
translateAggPredArguments predArgs relTableNameAlias =
|
||||
translateAggPredArguments predArgs relTableNameIdentifier =
|
||||
case predArgs of
|
||||
AggregationPredicateArgumentsStar -> pure $ S.SEStar Nothing
|
||||
(AggregationPredicateArguments cols) ->
|
||||
S.SEQIdentifier . S.mkQIdentifier relTableNameAlias <$> cols
|
||||
S.SEQIdentifier . S.mkQIdentifier relTableNameIdentifier <$> cols
|
||||
|
||||
translateTableRelationship :: HashMap PGCol PGCol -> Identifier -> BoolExpM S.BoolExp
|
||||
translateTableRelationship colMapping relTableNameAlias = do
|
||||
translateTableRelationship :: HashMap PGCol PGCol -> TableIdentifier -> BoolExpM S.BoolExp
|
||||
translateTableRelationship colMapping relTableNameIdentifier = do
|
||||
BoolExpCtx {currTableReference} <- ask
|
||||
pure $
|
||||
sqlAnd $
|
||||
flip map (M.toList colMapping) $ \(lCol, rCol) ->
|
||||
S.BECompare
|
||||
S.SEQ
|
||||
(S.mkIdentifierSQLExp (S.QualifiedIdentifier relTableNameAlias Nothing) rCol)
|
||||
(S.mkIdentifierSQLExp (S.QualifiedIdentifier relTableNameIdentifier Nothing) rCol)
|
||||
(S.mkIdentifierSQLExp currTableReference lCol)
|
||||
|
||||
data LHSField b
|
||||
|
@ -38,15 +38,16 @@ mkSelectExpFromColumnValues qt allCols = \case
|
||||
[] -> return selNoRows
|
||||
colVals -> do
|
||||
tuples <- mapM mkTupsFromColVal colVals
|
||||
let fromItem = S.FIValues (S.ValuesExp tuples) (S.toTableAlias rowAlias) Nothing
|
||||
let fromItem = S.FIValues (S.ValuesExp tuples) 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
|
||||
rowAlias = S.mkTableAlias "row"
|
||||
rowIdentifier = S.tableAliasToIdentifier rowAlias
|
||||
extractor = S.selectStar' $ S.QualifiedIdentifier rowIdentifier $ Just $ S.TypeAnn $ toSQLTxt qt
|
||||
sortedCols = sortCols allCols
|
||||
mkTupsFromColVal colVal =
|
||||
fmap S.TupleExp $
|
||||
|
@ -5,8 +5,9 @@ module Hasura.Backends.Postgres.Translate.Select.Internal.Aliases
|
||||
mkArrayRelationAlias,
|
||||
mkArrayRelationSourcePrefix,
|
||||
mkBaseTableAlias,
|
||||
mkBaseTableColumnAlias,
|
||||
mkComputedFieldTableAlias,
|
||||
mkBaseTableIdentifier,
|
||||
contextualizeBaseTableColumn,
|
||||
mkComputedFieldTableIdentifier,
|
||||
mkObjectRelationTableAlias,
|
||||
mkOrderByFieldName,
|
||||
)
|
||||
@ -29,65 +30,52 @@ import Hasura.SQL.Backend
|
||||
|
||||
-- | Generate alias for order by extractors
|
||||
mkAnnOrderByAlias ::
|
||||
Identifier -> FieldName -> SimilarArrayFields -> AnnotatedOrderByElement ('Postgres pgKind) v -> S.ColumnAlias
|
||||
mkAnnOrderByAlias pfx parAls similarFields = \case
|
||||
TableIdentifier -> FieldName -> SimilarArrayFields -> AnnotatedOrderByElement ('Postgres pgKind) v -> S.ColumnAlias
|
||||
mkAnnOrderByAlias tablePrefix parAls similarFields = \case
|
||||
AOCColumn pgColumnInfo ->
|
||||
let pgColumn = ciColumn pgColumnInfo
|
||||
obColAls = mkBaseTableColumnAlias pfx pgColumn
|
||||
obColAls = contextualizeBaseTableColumn tablePrefix pgColumn
|
||||
in obColAls
|
||||
-- "pfx.or.relname"."pfx.ob.or.relname.rest" AS "pfx.ob.or.relname.rest"
|
||||
AOCObjectRelation relInfo _ rest ->
|
||||
let rn = riName relInfo
|
||||
relPfx = mkObjectRelationTableAlias pfx rn
|
||||
relPfx = mkObjectRelationTableAlias tablePrefix rn
|
||||
ordByFldName = mkOrderByFieldName rn
|
||||
nesAls = mkAnnOrderByAlias relPfx ordByFldName mempty rest
|
||||
in nesAls
|
||||
AOCArrayAggregation relInfo _ aggOrderBy ->
|
||||
let rn = riName relInfo
|
||||
arrPfx =
|
||||
mkArrayRelationSourcePrefix pfx parAls similarFields $
|
||||
mkArrayRelationSourcePrefix tablePrefix parAls similarFields $
|
||||
mkOrderByFieldName rn
|
||||
obAls = arrPfx <> Identifier "." <> toIdentifier (mkAggregateOrderByAlias aggOrderBy)
|
||||
obAls = S.tableIdentifierToColumnAlias arrPfx <> "." <> mkAggregateOrderByAlias aggOrderBy
|
||||
in S.toColumnAlias obAls
|
||||
AOCComputedField cfOrderBy ->
|
||||
let fieldName = fromComputedField $ _cfobName cfOrderBy
|
||||
in case _cfobOrderByElement cfOrderBy of
|
||||
CFOBEScalar _ -> S.toColumnAlias $ mkComputedFieldTableAlias pfx fieldName
|
||||
CFOBEScalar _ -> S.tableIdentifierToColumnAlias $ mkComputedFieldTableIdentifier tablePrefix fieldName
|
||||
CFOBETableAggregation _ _ aggOrderBy ->
|
||||
let cfPfx = mkComputedFieldTableAlias pfx fieldName
|
||||
obAls = cfPfx <> Identifier "." <> toIdentifier (mkAggregateOrderByAlias aggOrderBy)
|
||||
let cfPfx = mkComputedFieldTableIdentifier tablePrefix fieldName
|
||||
obAls = S.tableIdentifierToColumnAlias cfPfx <> "." <> mkAggregateOrderByAlias aggOrderBy
|
||||
in S.toColumnAlias obAls
|
||||
|
||||
-- array relationships are not grouped, so have to be prefixed by
|
||||
-- parent's alias
|
||||
mkUniqArrayRelationAlias :: FieldName -> [FieldName] -> Identifier
|
||||
mkUniqArrayRelationAlias parAls flds =
|
||||
let sortedFields = sort flds
|
||||
in Identifier $
|
||||
getFieldNameTxt parAls <> "."
|
||||
<> T.intercalate "." (map getFieldNameTxt sortedFields)
|
||||
|
||||
mkArrayRelationTableAlias :: Identifier -> FieldName -> [FieldName] -> Identifier
|
||||
mkArrayRelationTableAlias pfx parAls flds =
|
||||
pfx <> Identifier ".ar." <> uniqArrRelAls
|
||||
where
|
||||
uniqArrRelAls = mkUniqArrayRelationAlias parAls flds
|
||||
|
||||
mkObjectRelationTableAlias :: Identifier -> RelName -> Identifier
|
||||
mkObjectRelationTableAlias :: TableIdentifier -> RelName -> TableIdentifier
|
||||
mkObjectRelationTableAlias pfx relName =
|
||||
pfx <> Identifier ".or." <> toIdentifier relName
|
||||
pfx <> TableIdentifier (".or." <> relNameToTxt relName)
|
||||
|
||||
mkComputedFieldTableAlias :: Identifier -> FieldName -> Identifier
|
||||
mkComputedFieldTableAlias pfx fldAls =
|
||||
pfx <> Identifier ".cf." <> toIdentifier fldAls
|
||||
mkComputedFieldTableIdentifier :: TableIdentifier -> FieldName -> TableIdentifier
|
||||
mkComputedFieldTableIdentifier pfx fldAls =
|
||||
pfx <> TableIdentifier ".cf." <> TableIdentifier (getFieldNameTxt fldAls)
|
||||
|
||||
mkBaseTableAlias :: Identifier -> S.TableAlias
|
||||
mkBaseTableAlias pfx =
|
||||
S.toTableAlias $ pfx <> Identifier ".base"
|
||||
mkBaseTableIdentifier :: TableIdentifier -> TableIdentifier
|
||||
mkBaseTableIdentifier pfx = pfx <> TableIdentifier ".base"
|
||||
|
||||
mkBaseTableColumnAlias :: Identifier -> PGCol -> S.ColumnAlias
|
||||
mkBaseTableColumnAlias pfx pgColumn =
|
||||
S.toColumnAlias $ pfx <> Identifier ".pg." <> toIdentifier pgColumn
|
||||
mkBaseTableAlias :: S.TableAlias -> S.TableAlias
|
||||
mkBaseTableAlias pfx = pfx <> ".base"
|
||||
|
||||
contextualizeBaseTableColumn :: TableIdentifier -> PGCol -> S.ColumnAlias
|
||||
contextualizeBaseTableColumn pfx pgColumn =
|
||||
S.tableIdentifierToColumnAlias pfx <> ".pg." <> S.mkColumnAlias (getPGColTxt pgColumn)
|
||||
|
||||
mkAggregateOrderByAlias :: AnnotatedAggregateOrderBy ('Postgres pgKind) -> S.ColumnAlias
|
||||
mkAggregateOrderByAlias =
|
||||
@ -100,21 +88,35 @@ mkOrderByFieldName name =
|
||||
FieldName $ toTxt name <> "." <> "order_by"
|
||||
|
||||
mkArrayRelationSourcePrefix ::
|
||||
Identifier ->
|
||||
TableIdentifier ->
|
||||
FieldName ->
|
||||
HM.HashMap FieldName [FieldName] ->
|
||||
FieldName ->
|
||||
Identifier
|
||||
TableIdentifier
|
||||
mkArrayRelationSourcePrefix parentSourcePrefix parentFieldName similarFieldsMap fieldName =
|
||||
mkArrayRelationTableAlias parentSourcePrefix parentFieldName $
|
||||
mkArrayRelationTableIdentifier parentSourcePrefix parentFieldName $
|
||||
HM.lookupDefault [fieldName] fieldName similarFieldsMap
|
||||
|
||||
mkArrayRelationTableIdentifier :: TableIdentifier -> FieldName -> [FieldName] -> TableIdentifier
|
||||
mkArrayRelationTableIdentifier pfx parAls flds =
|
||||
pfx <> TableIdentifier ".ar." <> TableIdentifier uniqArrRelAls
|
||||
where
|
||||
uniqArrRelAls = mkUniqArrayRelationAlias parAls flds
|
||||
|
||||
mkArrayRelationAlias ::
|
||||
FieldName ->
|
||||
HM.HashMap FieldName [FieldName] ->
|
||||
FieldName ->
|
||||
S.TableAlias
|
||||
mkArrayRelationAlias parentFieldName similarFieldsMap fieldName =
|
||||
S.toTableAlias $
|
||||
S.mkTableAlias $
|
||||
mkUniqArrayRelationAlias parentFieldName $
|
||||
HM.lookupDefault [fieldName] fieldName similarFieldsMap
|
||||
|
||||
-- array relationships are not grouped, so have to be prefixed by
|
||||
-- parent's alias
|
||||
mkUniqArrayRelationAlias :: FieldName -> [FieldName] -> Text
|
||||
mkUniqArrayRelationAlias parAls flds =
|
||||
let sortedFields = sort flds
|
||||
in getFieldNameTxt parAls <> "."
|
||||
<> T.intercalate "." (map getFieldNameTxt sortedFields)
|
||||
|
@ -23,7 +23,7 @@ import Hasura.RQL.Types.Common
|
||||
import Hasura.SQL.Backend
|
||||
|
||||
aggregateFieldsToExtractorExps ::
|
||||
Identifier -> AggregateFields ('Postgres pgKind) -> [(S.ColumnAlias, S.SQLExp)]
|
||||
TableIdentifier -> AggregateFields ('Postgres pgKind) -> [(S.ColumnAlias, S.SQLExp)]
|
||||
aggregateFieldsToExtractorExps sourcePrefix aggregateFields =
|
||||
flip concatMap aggregateFields $ \(_, field) ->
|
||||
case field of
|
||||
@ -42,7 +42,7 @@ aggregateFieldsToExtractorExps sourcePrefix aggregateFields =
|
||||
_ -> Nothing
|
||||
|
||||
mkColExp c =
|
||||
let qualCol = S.mkQIdenExp (mkBaseTableAlias sourcePrefix) (toIdentifier c)
|
||||
let qualCol = S.mkQIdenExp (mkBaseTableIdentifier sourcePrefix) (toIdentifier c)
|
||||
colAls = toIdentifier c
|
||||
in (S.toColumnAlias colAls, qualCol)
|
||||
|
||||
@ -85,8 +85,10 @@ withJsonAggExtr permLimitSubQuery ordBy alias =
|
||||
where
|
||||
simpleJsonAgg = mkSimpleJsonAgg rowIdenExp ordBy
|
||||
rowIdenExp = S.SEIdentifier $ toIdentifier alias
|
||||
subSelAls = Identifier "sub_query"
|
||||
unnestTable = Identifier "unnest_table"
|
||||
subSelAls = S.mkTableAlias "sub_query"
|
||||
subSelIdentifier = S.tableAliasToIdentifier subSelAls
|
||||
unnestTable = S.mkTableAlias "unnest_table"
|
||||
unnestTableIdentifier = S.tableAliasToIdentifier unnestTable
|
||||
|
||||
mkSimpleJsonAgg rowExp ob =
|
||||
let jsonAggExp = S.SEFnApp "json_agg" [rowExp] ob
|
||||
@ -94,7 +96,7 @@ withJsonAggExtr permLimitSubQuery ordBy alias =
|
||||
|
||||
withPermLimit limit =
|
||||
let subSelect = mkSubSelect limit
|
||||
rowIdentifier = S.mkQIdenExp subSelAls alias
|
||||
rowIdentifier = S.mkQIdenExp subSelIdentifier alias
|
||||
extr = S.Extractor (mkSimpleJsonAgg rowIdentifier newOrderBy) Nothing
|
||||
fromExp =
|
||||
S.FromExp $
|
||||
@ -109,9 +111,9 @@ withJsonAggExtr permLimitSubQuery ordBy alias =
|
||||
mkSubSelect limit =
|
||||
let jsonRowExtr =
|
||||
flip S.Extractor (Just alias) $
|
||||
S.mkQIdenExp unnestTable alias
|
||||
S.mkQIdenExp unnestTableIdentifier alias
|
||||
obExtrs = flip map newOBAliases $ \a ->
|
||||
S.Extractor (S.mkQIdenExp unnestTable a) $ Just $ S.toColumnAlias a
|
||||
S.Extractor (S.mkQIdenExp unnestTableIdentifier a) $ Just $ S.toColumnAlias a
|
||||
in S.mkSelect
|
||||
{ S.selExtr = jsonRowExtr : obExtrs,
|
||||
S.selFrom = Just $ S.FromExp $ pure unnestFromItem,
|
||||
|
@ -14,6 +14,7 @@ import Data.HashMap.Strict qualified as HM
|
||||
import Data.List.NonEmpty qualified as NE
|
||||
import Hasura.Backends.Postgres.SQL.DML qualified as S
|
||||
import Hasura.Backends.Postgres.SQL.Types
|
||||
import Hasura.Backends.Postgres.SQL.Types qualified as S
|
||||
import Hasura.Backends.Postgres.Translate.Select.Internal.Aliases (mkBaseTableAlias)
|
||||
import Hasura.Backends.Postgres.Translate.Select.Internal.Helpers
|
||||
( cursorIdentifier,
|
||||
@ -72,7 +73,9 @@ generateSQLSelect joinCondition selectSource selectNode =
|
||||
S.selOffset = S.OffsetExp . S.int64ToSQLExp <$> _ssOffset baseSlicing,
|
||||
S.selDistinct = baseDistinctOn
|
||||
}
|
||||
baseSelectAlias = mkBaseTableAlias sourcePrefix
|
||||
-- This is why 'SelectSource{sourcePrefix}' needs to be a TableAlias!
|
||||
baseSelectAlias = mkBaseTableAlias (S.toTableAlias sourcePrefix)
|
||||
baseSelectIdentifier = S.tableAliasToIdentifier baseSelectAlias
|
||||
baseFromItem = S.mkSelFromItem baseSelect baseSelectAlias
|
||||
|
||||
injectJoinCond ::
|
||||
@ -103,7 +106,7 @@ generateSQLSelect joinCondition selectSource selectNode =
|
||||
let ObjectRelationSource _ colMapping objectSelectSource = objectRelationSource
|
||||
alias = S.toTableAlias $ _ossPrefix objectSelectSource
|
||||
source = objectSelectSourceToSelectSource objectSelectSource
|
||||
select = generateSQLSelect (mkJoinCond baseSelectAlias colMapping) source node
|
||||
select = generateSQLSelect (mkJoinCond baseSelectIdentifier colMapping) source node
|
||||
in S.mkLateralFromItem select alias
|
||||
|
||||
arrayRelationToFromItem ::
|
||||
@ -113,7 +116,7 @@ generateSQLSelect joinCondition selectSource selectNode =
|
||||
alias = S.toTableAlias $ _ssPrefix source
|
||||
select =
|
||||
generateSQLSelectFromArrayNode source arraySelectNode $
|
||||
mkJoinCond baseSelectAlias colMapping
|
||||
mkJoinCond baseSelectIdentifier colMapping
|
||||
in S.mkLateralFromItem select alias
|
||||
|
||||
arrayConnectionToFromItem ::
|
||||
@ -154,7 +157,7 @@ generateSQLSelectFromArrayNode selectSource (MultiRowSelectNode topExtractors se
|
||||
]
|
||||
}
|
||||
|
||||
mkJoinCond :: S.TableAlias -> HashMap PGCol PGCol -> S.BoolExp
|
||||
mkJoinCond :: S.TableIdentifier -> HashMap PGCol PGCol -> S.BoolExp
|
||||
mkJoinCond baseTablepfx colMapn =
|
||||
foldl' (S.BEBin S.AndOp) (S.BELit True) $
|
||||
flip map (HM.toList colMapn) $ \(lCol, rCol) ->
|
||||
@ -177,6 +180,8 @@ connectionToSelectWith rootSelectAlias arrayConnectionSource arraySelectNode =
|
||||
arrayConnectionSource
|
||||
MultiRowSelectNode topExtractors selectNode = arraySelectNode
|
||||
|
||||
rootSelectIdentifier = S.tableAliasToIdentifier rootSelectAlias
|
||||
|
||||
baseSelectAlias = S.mkTableAlias "__base_select"
|
||||
baseSelectIdentifier = S.tableAliasToIdentifier baseSelectAlias
|
||||
|
||||
@ -201,7 +206,7 @@ connectionToSelectWith rootSelectAlias arrayConnectionSource arraySelectNode =
|
||||
endRowNumberExp = mkLastElementExp $ S.SEIdentifier rowNumberIdentifier
|
||||
|
||||
fromBaseSelections =
|
||||
let joinCond = mkJoinCond rootSelectAlias columnMapping
|
||||
let joinCond = mkJoinCond rootSelectIdentifier columnMapping
|
||||
baseSelectFrom =
|
||||
S.mkSelFromItem
|
||||
(generateSQLSelect joinCond selectSource selectNode)
|
||||
|
@ -21,7 +21,13 @@ module Hasura.Backends.Postgres.Translate.Select.Internal.Helpers
|
||||
where
|
||||
|
||||
import Hasura.Backends.Postgres.SQL.DML qualified as S
|
||||
import Hasura.Backends.Postgres.SQL.Types (Identifier (..), QualifiedFunction, TableIdentifier (..), qualifiedObjectToText, toIdentifier)
|
||||
import Hasura.Backends.Postgres.SQL.Types
|
||||
( Identifier (..),
|
||||
QualifiedFunction,
|
||||
TableIdentifier (..),
|
||||
qualifiedObjectToText,
|
||||
tableIdentifierToIdentifier,
|
||||
)
|
||||
import Hasura.Backends.Postgres.Translate.Select.Internal.Aliases
|
||||
import Hasura.Backends.Postgres.Types.Function
|
||||
import Hasura.Prelude
|
||||
@ -86,18 +92,18 @@ encodeBase64 =
|
||||
S.SEFnApp "regexp_replace" [e, S.SELit "\\n", S.SELit "", S.SELit "g"] Nothing
|
||||
|
||||
fromTableRowArgs ::
|
||||
Identifier -> FunctionArgsExpG (ArgumentExp S.SQLExp) -> S.FunctionArgs
|
||||
TableIdentifier -> FunctionArgsExpG (ArgumentExp S.SQLExp) -> S.FunctionArgs
|
||||
fromTableRowArgs prefix = toFunctionArgs . fmap toSQLExp
|
||||
where
|
||||
toFunctionArgs (FunctionArgsExp positional named) =
|
||||
S.FunctionArgs positional named
|
||||
toSQLExp =
|
||||
onArgumentExp
|
||||
(S.SERowIdentifier alias)
|
||||
(S.mkQIdenExp alias . Identifier)
|
||||
alias = toIdentifier $ mkBaseTableAlias prefix
|
||||
(S.SERowIdentifier (tableIdentifierToIdentifier baseTableIdentifier))
|
||||
(S.mkQIdenExp baseTableIdentifier . Identifier)
|
||||
baseTableIdentifier = mkBaseTableIdentifier prefix
|
||||
|
||||
selectFromToFromItem :: Identifier -> SelectFrom ('Postgres pgKind) -> S.FromItem
|
||||
selectFromToFromItem :: TableIdentifier -> SelectFrom ('Postgres pgKind) -> S.FromItem
|
||||
selectFromToFromItem prefix = \case
|
||||
FromTable tn -> S.FISimple tn Nothing
|
||||
FromIdentifier i -> S.FIIdentifier $ TableIdentifier $ unFIIdentifier i
|
||||
|
@ -9,19 +9,21 @@ import Data.HashMap.Strict qualified as HM
|
||||
import Data.List.NonEmpty qualified as NE
|
||||
import Hasura.Backends.Postgres.SQL.DML qualified as S
|
||||
import Hasura.Backends.Postgres.SQL.Types
|
||||
( Identifier,
|
||||
IsIdentifier (toIdentifier),
|
||||
( IsIdentifier (toIdentifier),
|
||||
PGCol (..),
|
||||
TableIdentifier (..),
|
||||
qualifiedObjectToText,
|
||||
tableIdentifierToIdentifier,
|
||||
)
|
||||
import Hasura.Backends.Postgres.Translate.BoolExp (toSQLBoolExp)
|
||||
import Hasura.Backends.Postgres.Translate.Select.Internal.Aliases
|
||||
( mkAggregateOrderByAlias,
|
||||
( contextualizeBaseTableColumn,
|
||||
mkAggregateOrderByAlias,
|
||||
mkAnnOrderByAlias,
|
||||
mkArrayRelationAlias,
|
||||
mkArrayRelationSourcePrefix,
|
||||
mkBaseTableAlias,
|
||||
mkBaseTableColumnAlias,
|
||||
mkComputedFieldTableAlias,
|
||||
mkBaseTableIdentifier,
|
||||
mkComputedFieldTableIdentifier,
|
||||
mkObjectRelationTableAlias,
|
||||
mkOrderByFieldName,
|
||||
)
|
||||
@ -31,7 +33,6 @@ import Hasura.Backends.Postgres.Translate.Select.Internal.Extractor
|
||||
)
|
||||
import Hasura.Backends.Postgres.Translate.Select.Internal.Helpers
|
||||
( fromTableRowArgs,
|
||||
functionToIdentifier,
|
||||
selectFromToFromItem,
|
||||
)
|
||||
import Hasura.Backends.Postgres.Translate.Select.Internal.JoinTree
|
||||
@ -77,7 +78,7 @@ processOrderByItems ::
|
||||
MonadWriter JoinTree m,
|
||||
Backend ('Postgres pgKind)
|
||||
) =>
|
||||
Identifier ->
|
||||
TableIdentifier ->
|
||||
FieldName ->
|
||||
SimilarArrayFields ->
|
||||
Maybe (NE.NonEmpty PGCol) ->
|
||||
@ -105,13 +106,13 @@ processOrderByItems sourcePrefix' fieldAlias' similarArrayFields distOnCols = \c
|
||||
<$> processAnnotatedOrderByElement sourcePrefix' fieldAlias' ordByCol
|
||||
|
||||
processAnnotatedOrderByElement ::
|
||||
Identifier -> FieldName -> AnnotatedOrderByElement ('Postgres pgKind) S.SQLExp -> m (S.ColumnAlias, (SQLExpression ('Postgres pgKind)))
|
||||
TableIdentifier -> FieldName -> AnnotatedOrderByElement ('Postgres pgKind) S.SQLExp -> m (S.ColumnAlias, (SQLExpression ('Postgres pgKind)))
|
||||
processAnnotatedOrderByElement sourcePrefix fieldAlias annObCol = do
|
||||
let ordByAlias = mkAnnOrderByAlias sourcePrefix fieldAlias similarArrayFields annObCol
|
||||
(ordByAlias,) <$> case annObCol of
|
||||
AOCColumn pgColInfo ->
|
||||
pure $
|
||||
S.mkQIdenExp (mkBaseTableAlias sourcePrefix) $ toIdentifier $ ciColumn pgColInfo
|
||||
S.mkQIdenExp (mkBaseTableIdentifier sourcePrefix) $ toIdentifier $ ciColumn pgColInfo
|
||||
AOCObjectRelation relInfo relFilter rest -> withWriteObjectRelation $ do
|
||||
let RelInfo relName _ colMapping relTable _ _ = relInfo
|
||||
relSourcePrefix = mkObjectRelationTableAlias sourcePrefix relName
|
||||
@ -120,7 +121,7 @@ processOrderByItems sourcePrefix' fieldAlias' similarArrayFields distOnCols = \c
|
||||
processAnnotatedOrderByElement relSourcePrefix fieldName rest
|
||||
let selectSource =
|
||||
ObjectSelectSource
|
||||
relSourcePrefix
|
||||
(tableIdentifierToIdentifier relSourcePrefix)
|
||||
(S.FISimple relTable Nothing)
|
||||
(toSQLBoolExp (S.QualTable relTable) relFilter)
|
||||
relSource = ObjectRelationSource relName colMapping selectSource
|
||||
@ -142,7 +143,7 @@ processOrderByItems sourcePrefix' fieldAlias' similarArrayFields distOnCols = \c
|
||||
(topExtractor, fields) = mkAggregateOrderByExtractorAndFields aggOrderBy
|
||||
selectSource =
|
||||
SelectSource
|
||||
relSourcePrefix
|
||||
(tableIdentifierToIdentifier relSourcePrefix)
|
||||
(S.FISimple relTable Nothing)
|
||||
(toSQLBoolExp (S.QualTable relTable) relFilter)
|
||||
noSortingAndSlicing
|
||||
@ -161,15 +162,15 @@ processOrderByItems sourcePrefix' fieldAlias' similarArrayFields distOnCols = \c
|
||||
pure $ S.SEFunction functionExp
|
||||
CFOBETableAggregation _ tableFilter aggOrderBy -> withWriteComputedFieldTableSet $ do
|
||||
let fieldName = mkOrderByFieldName _cfobName
|
||||
computedFieldSourcePrefix = mkComputedFieldTableAlias sourcePrefix fieldName
|
||||
computedFieldSourcePrefix = mkComputedFieldTableIdentifier sourcePrefix fieldName
|
||||
(topExtractor, fields) = mkAggregateOrderByExtractorAndFields aggOrderBy
|
||||
fromItem =
|
||||
selectFromToFromItem sourcePrefix $
|
||||
FromFunction _cfobFunction _cfobFunctionArgsExp Nothing
|
||||
functionQual = S.QualifiedIdentifier (functionToIdentifier _cfobFunction) Nothing
|
||||
functionQual = S.QualifiedIdentifier (TableIdentifier $ qualifiedObjectToText _cfobFunction) Nothing
|
||||
selectSource =
|
||||
SelectSource
|
||||
computedFieldSourcePrefix
|
||||
(tableIdentifierToIdentifier computedFieldSourcePrefix)
|
||||
fromItem
|
||||
(toSQLBoolExp functionQual tableFilter)
|
||||
noSortingAndSlicing
|
||||
@ -269,7 +270,7 @@ applyDistinctOnAtBase =
|
||||
S.DistinctOn . map (S.SEIdentifier . toIdentifier) . toList
|
||||
|
||||
applyDistinctOnAtNode ::
|
||||
Identifier ->
|
||||
TableIdentifier ->
|
||||
NE.NonEmpty PGCol ->
|
||||
( S.DistinctExpr,
|
||||
[(S.ColumnAlias, S.SQLExp)] -- additional column extractors
|
||||
@ -278,6 +279,6 @@ applyDistinctOnAtNode pfx neCols = (distOnExp, colExtrs)
|
||||
where
|
||||
cols = toList neCols
|
||||
distOnExp = S.DistinctOn $ map (S.SEIdentifier . toIdentifier . mkQColAls) cols
|
||||
mkQCol c = S.mkQIdenExp (mkBaseTableAlias pfx) $ toIdentifier c
|
||||
mkQColAls = mkBaseTableColumnAlias pfx
|
||||
mkQCol c = S.mkQIdenExp (mkBaseTableIdentifier pfx) $ toIdentifier c
|
||||
mkQColAls = contextualizeBaseTableColumn pfx
|
||||
colExtrs = flip map cols $ mkQColAls &&& mkQCol
|
||||
|
@ -28,23 +28,26 @@ import Data.List.NonEmpty qualified as NE
|
||||
import Data.Text.Extended (ToTxt (toTxt))
|
||||
import Hasura.Backends.Postgres.SQL.DML qualified as S
|
||||
import Hasura.Backends.Postgres.SQL.Types
|
||||
( Identifier,
|
||||
IsIdentifier (toIdentifier),
|
||||
( IsIdentifier (toIdentifier),
|
||||
PGCol (..),
|
||||
QualifiedObject (QualifiedObject),
|
||||
QualifiedTable,
|
||||
SchemaName (getSchemaTxt),
|
||||
TableIdentifier (..),
|
||||
identifierToTableIdentifier,
|
||||
qualifiedObjectToText,
|
||||
tableIdentifierToIdentifier,
|
||||
)
|
||||
import Hasura.Backends.Postgres.Translate.BoolExp (toSQLBoolExp)
|
||||
import Hasura.Backends.Postgres.Translate.Column (toJSONableExp)
|
||||
import Hasura.Backends.Postgres.Translate.Select.AnnotatedFieldJSON
|
||||
import Hasura.Backends.Postgres.Translate.Select.Internal.Aliases
|
||||
( mkAnnOrderByAlias,
|
||||
( contextualizeBaseTableColumn,
|
||||
mkAnnOrderByAlias,
|
||||
mkArrayRelationAlias,
|
||||
mkArrayRelationSourcePrefix,
|
||||
mkBaseTableAlias,
|
||||
mkBaseTableColumnAlias,
|
||||
mkComputedFieldTableAlias,
|
||||
mkBaseTableIdentifier,
|
||||
mkComputedFieldTableIdentifier,
|
||||
mkObjectRelationTableAlias,
|
||||
mkOrderByFieldName,
|
||||
)
|
||||
@ -59,7 +62,6 @@ import Hasura.Backends.Postgres.Translate.Select.Internal.Helpers
|
||||
encodeBase64,
|
||||
endCursorIdentifier,
|
||||
fromTableRowArgs,
|
||||
functionToIdentifier,
|
||||
hasNextPageIdentifier,
|
||||
hasPreviousPageIdentifier,
|
||||
pageInfoSelectAliasIdentifier,
|
||||
@ -115,8 +117,8 @@ processSelectParams
|
||||
tablePermissions
|
||||
tableArgs = do
|
||||
(additionalExtrs, selectSorting, cursorExp) <-
|
||||
processOrderByItems thisSourcePrefix fieldAlias similarArrFields distM orderByM
|
||||
let fromItem = selectFromToFromItem (_pfBase sourcePrefixes) selectFrom
|
||||
processOrderByItems (identifierToTableIdentifier thisSourcePrefix) fieldAlias similarArrFields distM orderByM
|
||||
let fromItem = selectFromToFromItem (identifierToTableIdentifier $ _pfBase sourcePrefixes) selectFrom
|
||||
finalWhere =
|
||||
toSQLBoolExp (selectFromToQual selectFrom) $
|
||||
maybe permFilter (andAnnBoolExps permFilter) whereM
|
||||
@ -161,8 +163,8 @@ processSelectParams
|
||||
selectFromToQual :: SelectFrom ('Postgres pgKind) -> S.Qual
|
||||
selectFromToQual = \case
|
||||
FromTable table -> S.QualTable table
|
||||
FromIdentifier i -> S.QualifiedIdentifier (toIdentifier i) Nothing
|
||||
FromFunction qf _ _ -> S.QualifiedIdentifier (functionToIdentifier qf) Nothing
|
||||
FromIdentifier i -> S.QualifiedIdentifier (TableIdentifier $ unFIIdentifier i) Nothing
|
||||
FromFunction qf _ _ -> S.QualifiedIdentifier (TableIdentifier $ qualifiedObjectToText qf) Nothing
|
||||
|
||||
processAnnAggregateSelect ::
|
||||
forall pgKind m.
|
||||
@ -189,7 +191,7 @@ processAnnAggregateSelect sourcePrefixes fieldAlias annAggSel = do
|
||||
permLimitSubQuery
|
||||
tablePermissions
|
||||
tableArgs
|
||||
let thisSourcePrefix = _pfThis sourcePrefixes
|
||||
let thisSourcePrefix = identifierToTableIdentifier $ _pfThis sourcePrefixes
|
||||
processedFields <- forM aggSelFields $ \(fieldName, field) ->
|
||||
(fieldName,)
|
||||
<$> case field of
|
||||
@ -265,7 +267,7 @@ processAnnFields ::
|
||||
Backend ('Postgres pgKind),
|
||||
PostgresAnnotatedFieldJSON pgKind
|
||||
) =>
|
||||
Identifier ->
|
||||
TableIdentifier ->
|
||||
FieldName ->
|
||||
SimilarArrayFields ->
|
||||
AnnFields ('Postgres pgKind) ->
|
||||
@ -283,7 +285,7 @@ processAnnFields sourcePrefix fieldAlias similarArrFields annFields tCase = do
|
||||
AnnObjectSelectG objAnnFields tableFrom tableFilter = annObjSel
|
||||
objRelSourcePrefix = mkObjectRelationTableAlias sourcePrefix relName
|
||||
sourcePrefixes = mkSourcePrefixes objRelSourcePrefix
|
||||
annFieldsExtr <- processAnnFields (_pfThis sourcePrefixes) fieldName HM.empty objAnnFields tCase
|
||||
annFieldsExtr <- processAnnFields (identifierToTableIdentifier $ _pfThis sourcePrefixes) fieldName HM.empty objAnnFields tCase
|
||||
let selectSource =
|
||||
ObjectSelectSource
|
||||
(_pfThis sourcePrefixes)
|
||||
@ -317,7 +319,7 @@ processAnnFields sourcePrefix fieldAlias similarArrFields annFields tCase = do
|
||||
in pure $ S.SECond boolExp computedFieldSQLExp S.SENull
|
||||
AFComputedField _ _ (CFSTable selectTy sel) -> withWriteComputedFieldTableSet $ do
|
||||
let computedFieldSourcePrefix =
|
||||
mkComputedFieldTableAlias sourcePrefix fieldName
|
||||
mkComputedFieldTableIdentifier sourcePrefix fieldName
|
||||
(selectSource, nodeExtractors) <-
|
||||
processAnnSimpleSelect
|
||||
(mkSourcePrefixes computedFieldSourcePrefix)
|
||||
@ -337,9 +339,9 @@ processAnnFields sourcePrefix fieldAlias similarArrFields annFields tCase = do
|
||||
|
||||
pure $ annRowToJson @pgKind fieldAlias fieldExps
|
||||
where
|
||||
mkSourcePrefixes newPrefix = SourcePrefixes newPrefix sourcePrefix
|
||||
mkSourcePrefixes newPrefix = SourcePrefixes (tableIdentifierToIdentifier newPrefix) (tableIdentifierToIdentifier sourcePrefix)
|
||||
|
||||
baseTableIdentifier = toIdentifier $ mkBaseTableAlias sourcePrefix
|
||||
baseTableIdentifier = mkBaseTableIdentifier sourcePrefix
|
||||
|
||||
toSQLCol :: AnnColumnField ('Postgres pgKind) S.SQLExp -> m S.SQLExp
|
||||
toSQLCol (AnnColumnField col typ asText colOpM caseBoolExpMaybe) = do
|
||||
@ -378,7 +380,7 @@ processAnnFields sourcePrefix fieldAlias similarArrFields annFields tCase = do
|
||||
mkNodeId _sourceName (QualifiedObject tableSchema tableName) pkeyColumns =
|
||||
let columnInfoToSQLExp pgColumnInfo =
|
||||
toJSONableExp Options.Don'tStringifyNumbers (ciType pgColumnInfo) False Nothing $
|
||||
S.mkQIdenExp (mkBaseTableAlias sourcePrefix) $ ciColumn pgColumnInfo
|
||||
S.mkQIdenExp (mkBaseTableIdentifier sourcePrefix) $ ciColumn pgColumnInfo
|
||||
in -- See Note [Relay Node id].
|
||||
encodeBase64 $
|
||||
flip S.SETyAnn S.textTypeAnn $
|
||||
@ -538,7 +540,7 @@ processAnnSimpleSelect sourcePrefixes fieldAlias permLimitSubQuery annSimpleSel
|
||||
permLimitSubQuery
|
||||
tablePermissions
|
||||
tableArgs
|
||||
annFieldsExtr <- processAnnFields (_pfThis sourcePrefixes) fieldAlias similarArrayFields annSelFields tCase
|
||||
annFieldsExtr <- processAnnFields (identifierToTableIdentifier $ _pfThis sourcePrefixes) fieldAlias similarArrayFields annSelFields tCase
|
||||
let allExtractors = HM.fromList $ annFieldsExtr : orderByAndDistinctExtrs
|
||||
pure (selectSource, allExtractors)
|
||||
where
|
||||
@ -600,7 +602,7 @@ processConnectionSelect sourcePrefixes fieldAlias relAlias colMapping connection
|
||||
ConnectionSelect _ primaryKeyColumns maybeSplit maybeSlice select = connectionSelect
|
||||
AnnSelectG fields selectFrom tablePermissions tableArgs _ tCase = select
|
||||
fieldIdentifier = toIdentifier fieldAlias
|
||||
thisPrefix = _pfThis sourcePrefixes
|
||||
thisPrefix = identifierToTableIdentifier $ _pfThis sourcePrefixes
|
||||
permLimitSubQuery = PLSQNotRequired
|
||||
|
||||
primaryKeyColumnsObjectExp =
|
||||
@ -609,15 +611,15 @@ processConnectionSelect sourcePrefixes fieldAlias relAlias colMapping connection
|
||||
\pgColumnInfo ->
|
||||
[ S.SELit $ getPGColTxt $ ciColumn pgColumnInfo,
|
||||
toJSONableExp Options.Don'tStringifyNumbers (ciType pgColumnInfo) False tCase $
|
||||
S.mkQIdenExp (mkBaseTableAlias thisPrefix) $ ciColumn pgColumnInfo
|
||||
S.mkQIdenExp (mkBaseTableIdentifier thisPrefix) $ ciColumn pgColumnInfo
|
||||
]
|
||||
|
||||
primaryKeyColumnExtractors =
|
||||
flip map (toList primaryKeyColumns) $
|
||||
\pgColumnInfo ->
|
||||
let pgColumn = ciColumn pgColumnInfo
|
||||
in ( mkBaseTableColumnAlias thisPrefix pgColumn,
|
||||
S.mkQIdenExp (mkBaseTableAlias thisPrefix) pgColumn
|
||||
in ( contextualizeBaseTableColumn thisPrefix pgColumn,
|
||||
S.mkQIdenExp (mkBaseTableIdentifier thisPrefix) pgColumn
|
||||
)
|
||||
|
||||
mkSplitBoolExp (firstSplit NE.:| rest) =
|
||||
|
@ -19,7 +19,7 @@ import Hasura.Backends.Postgres.SQL.RenameIdentifiers (renameIdentifiers)
|
||||
import Hasura.Backends.Postgres.SQL.Types
|
||||
import Hasura.Backends.Postgres.SQL.Value (withConstructorFn)
|
||||
import Hasura.Backends.Postgres.Translate.Select.AnnotatedFieldJSON
|
||||
import Hasura.Backends.Postgres.Translate.Select.Internal.Aliases (mkBaseTableColumnAlias)
|
||||
import Hasura.Backends.Postgres.Translate.Select.Internal.Aliases (contextualizeBaseTableColumn)
|
||||
import Hasura.Backends.Postgres.Translate.Select.Internal.Extractor (asJsonAggExtr)
|
||||
import Hasura.Backends.Postgres.Translate.Select.Internal.GenerateSelect (generateSQLSelectFromArrayNode)
|
||||
import Hasura.Backends.Postgres.Translate.Select.Internal.Process (processAnnSimpleSelect)
|
||||
@ -48,6 +48,7 @@ import Hasura.RQL.Types.Column
|
||||
import Hasura.RQL.Types.Common
|
||||
( FieldName (FieldName),
|
||||
JsonAggSelect (JASMultipleRows),
|
||||
getFieldNameTxt,
|
||||
)
|
||||
import Hasura.RQL.Types.Subscription
|
||||
( CursorOrdering (CODescending),
|
||||
@ -121,7 +122,7 @@ mkStreamSQLSelect (AnnSelectStreamG () fields from perm args strfyNum) =
|
||||
S.SETyAnn
|
||||
( mkMaxOrMinSQLExp maxOrMinTxt $
|
||||
toIdentifier $
|
||||
mkBaseTableColumnAlias rootFldIdentifier pgColumn
|
||||
contextualizeBaseTableColumn rootFldIdentifier pgColumn
|
||||
)
|
||||
S.textTypeAnn
|
||||
]
|
||||
@ -133,8 +134,8 @@ mkStreamSQLSelect (AnnSelectStreamG () fields from perm args strfyNum) =
|
||||
in renameIdentifiers $
|
||||
generateSQLSelectFromArrayNode selectSource arrayNode $ S.BELit True
|
||||
where
|
||||
rootFldIdentifier = toIdentifier rootFldName
|
||||
sourcePrefixes = SourcePrefixes rootFldIdentifier rootFldIdentifier
|
||||
rootFldIdentifier = TableIdentifier $ getFieldNameTxt rootFldName
|
||||
sourcePrefixes = SourcePrefixes (tableIdentifierToIdentifier rootFldIdentifier) (tableIdentifierToIdentifier rootFldIdentifier)
|
||||
rootFldName = FieldName "root"
|
||||
rootFldAls = S.toColumnAlias $ toIdentifier rootFldName
|
||||
|
||||
@ -143,7 +144,7 @@ mkStreamSQLSelect (AnnSelectStreamG () fields from perm args strfyNum) =
|
||||
addTypeAnnotation pgType $
|
||||
S.SEOpApp
|
||||
(S.SQLOp "#>>")
|
||||
[ S.SEQIdentifier $ S.QIdentifier (S.QualifiedIdentifier (Identifier "_subs") Nothing) (Identifier "result_vars"),
|
||||
[ S.SEQIdentifier $ S.QIdentifier (S.QualifiedIdentifier (TableIdentifier "_subs") Nothing) (Identifier "result_vars"),
|
||||
S.SEArray $ map S.SELit jPath
|
||||
]
|
||||
addTypeAnnotation pgType =
|
||||
|
@ -119,7 +119,7 @@ selectIdentifiers_ alias table columns =
|
||||
Extractor
|
||||
( SEQIdentifier
|
||||
( QIdentifier
|
||||
(QualifiedIdentifier (Identifier table) Nothing)
|
||||
(QualifiedIdentifier (TableIdentifier table) Nothing)
|
||||
(Identifier column)
|
||||
)
|
||||
)
|
||||
@ -175,12 +175,7 @@ tcolumn_ :: Text -> Text -> SQLExp
|
||||
tcolumn_ table column =
|
||||
SEQIdentifier
|
||||
( QIdentifier
|
||||
( QualifiedIdentifier
|
||||
( Identifier
|
||||
{ getIdenTxt = table
|
||||
}
|
||||
)
|
||||
Nothing
|
||||
( QualifiedIdentifier (TableIdentifier table) Nothing
|
||||
)
|
||||
( Identifier
|
||||
{ getIdenTxt = column
|
||||
|
Loading…
Reference in New Issue
Block a user