mirror of
https://github.com/hasura/graphql-engine.git
synced 2024-12-17 04:24:35 +03:00
58c44f55dd
GitOrigin-RevId: 1c8c4d60e033c8a0bc8b2beed24c5bceb7d4bcc8
617 lines
21 KiB
Haskell
617 lines
21 KiB
Haskell
{-# LANGUAGE DeriveLift #-}
|
||
{-# LANGUAGE OverloadedStrings #-}
|
||
{-# LANGUAGE UndecidableInstances #-}
|
||
|
||
module Hasura.RQL.IR.Select where
|
||
|
||
import Hasura.Prelude
|
||
|
||
import qualified Data.HashMap.Strict as HM
|
||
import qualified Data.List.NonEmpty as NE
|
||
import qualified Data.Sequence as Seq
|
||
import qualified Language.GraphQL.Draft.Syntax as G
|
||
|
||
import Control.Lens.TH (makeLenses, makePrisms)
|
||
|
||
import qualified Hasura.Backends.Postgres.SQL.DML as PG
|
||
import qualified Hasura.Backends.Postgres.SQL.Types as PG
|
||
|
||
import Hasura.GraphQL.Parser.Schema
|
||
import Hasura.RQL.IR.BoolExp
|
||
import Hasura.RQL.IR.OrderBy
|
||
import Hasura.RQL.Types.Column
|
||
import Hasura.RQL.Types.Common
|
||
import Hasura.RQL.Types.Function
|
||
import Hasura.RQL.Types.RemoteRelationship
|
||
import Hasura.RQL.Types.RemoteSchema
|
||
import Hasura.SQL.Backend
|
||
|
||
|
||
data JsonAggSelect
|
||
= JASMultipleRows
|
||
| JASSingleObject
|
||
deriving (Show, Eq, Generic)
|
||
instance Hashable JsonAggSelect
|
||
|
||
data AnnAggregateOrderBy (b :: BackendType)
|
||
= AAOCount
|
||
| AAOOp !Text !(ColumnInfo b)
|
||
deriving (Generic)
|
||
deriving instance Eq (AnnAggregateOrderBy 'Postgres)
|
||
instance Hashable (AnnAggregateOrderBy 'Postgres)
|
||
|
||
data AnnOrderByElementG (b :: BackendType) v
|
||
= AOCColumn !(ColumnInfo b)
|
||
| AOCObjectRelation !RelInfo !v !(AnnOrderByElementG b v)
|
||
| AOCArrayAggregation !RelInfo !v !(AnnAggregateOrderBy b)
|
||
deriving (Generic, Functor)
|
||
deriving instance Eq v => Eq (AnnOrderByElementG 'Postgres v)
|
||
instance (Hashable v) => Hashable (AnnOrderByElementG 'Postgres v)
|
||
|
||
type AnnOrderByElement b v = AnnOrderByElementG b (AnnBoolExp b v)
|
||
|
||
traverseAnnOrderByElement
|
||
:: (Applicative f)
|
||
=> (a -> f b) -> AnnOrderByElement backend a -> f (AnnOrderByElement backend b)
|
||
traverseAnnOrderByElement f = \case
|
||
AOCColumn pgColInfo -> pure $ AOCColumn pgColInfo
|
||
AOCObjectRelation relInfo annBoolExp annObCol ->
|
||
AOCObjectRelation relInfo
|
||
<$> traverseAnnBoolExp f annBoolExp
|
||
<*> traverseAnnOrderByElement f annObCol
|
||
AOCArrayAggregation relInfo annBoolExp annAggOb ->
|
||
AOCArrayAggregation relInfo
|
||
<$> traverseAnnBoolExp f annBoolExp
|
||
<*> pure annAggOb
|
||
|
||
type AnnOrderByItemG b v = OrderByItemG b (AnnOrderByElement b v)
|
||
|
||
traverseAnnOrderByItem
|
||
:: (Applicative f)
|
||
=> (a -> f b) -> AnnOrderByItemG backend a -> f (AnnOrderByItemG backend b)
|
||
traverseAnnOrderByItem f =
|
||
traverse (traverseAnnOrderByElement f)
|
||
|
||
type AnnOrderByItem b = AnnOrderByItemG b (SQLExp b)
|
||
|
||
type OrderByItemExp b =
|
||
OrderByItemG b (AnnOrderByElement b (SQLExp b), (PG.Alias, (SQLExp b)))
|
||
|
||
data AnnRelationSelectG (b :: BackendType) a
|
||
= AnnRelationSelectG
|
||
{ aarRelationshipName :: !RelName -- Relationship name
|
||
, aarColumnMapping :: !(HashMap (Column b) (Column b)) -- Column of left table to join with
|
||
, aarAnnSelect :: !a -- Current table. Almost ~ to SQL Select
|
||
} deriving (Functor, Foldable, Traversable)
|
||
|
||
type ArrayRelationSelectG b v = AnnRelationSelectG b (AnnSimpleSelG b v)
|
||
type ArrayAggregateSelectG b v = AnnRelationSelectG b (AnnAggregateSelectG b v)
|
||
type ArrayConnectionSelect b v = AnnRelationSelectG b (ConnectionSelect b v)
|
||
type ArrayAggregateSelect b = ArrayAggregateSelectG b (SQLExp b)
|
||
|
||
data AnnObjectSelectG (b :: BackendType) v
|
||
= AnnObjectSelectG
|
||
{ _aosFields :: !(AnnFieldsG b v)
|
||
, _aosTableFrom :: !(TableName b)
|
||
, _aosTableFilter :: !(AnnBoolExp b v)
|
||
}
|
||
|
||
type AnnObjectSelect b = AnnObjectSelectG b (SQLExp b)
|
||
|
||
traverseAnnObjectSelect
|
||
:: (Applicative f)
|
||
=> (a -> f b)
|
||
-> AnnObjectSelectG backend a -> f (AnnObjectSelectG backend b)
|
||
traverseAnnObjectSelect f (AnnObjectSelectG fields fromTable permissionFilter) =
|
||
AnnObjectSelectG
|
||
<$> traverseAnnFields f fields
|
||
<*> pure fromTable
|
||
<*> traverseAnnBoolExp f permissionFilter
|
||
|
||
type ObjectRelationSelectG b v = AnnRelationSelectG b (AnnObjectSelectG b v)
|
||
type ObjectRelationSelect b = ObjectRelationSelectG b (SQLExp b)
|
||
|
||
data ComputedFieldScalarSelect (b :: BackendType) v
|
||
= ComputedFieldScalarSelect
|
||
{ _cfssFunction :: !PG.QualifiedFunction
|
||
, _cfssArguments :: !(FunctionArgsExpTableRow v)
|
||
, _cfssType :: !PG.PGScalarType
|
||
, _cfssColumnOp :: !(Maybe (ColumnOp b))
|
||
} deriving (Functor, Foldable, Traversable)
|
||
deriving instance Show v => Show (ComputedFieldScalarSelect 'Postgres v)
|
||
deriving instance Eq v => Eq (ComputedFieldScalarSelect 'Postgres v)
|
||
|
||
data ComputedFieldSelect (b :: BackendType) v
|
||
= CFSScalar !(ComputedFieldScalarSelect b v)
|
||
| CFSTable !JsonAggSelect !(AnnSimpleSelG b v)
|
||
|
||
traverseComputedFieldSelect
|
||
:: (Applicative f)
|
||
=> (v -> f w)
|
||
-> ComputedFieldSelect backend v -> f (ComputedFieldSelect backend w)
|
||
traverseComputedFieldSelect fv = \case
|
||
CFSScalar scalarSel -> CFSScalar <$> traverse fv scalarSel
|
||
CFSTable b tableSel -> CFSTable b <$> traverseAnnSimpleSelect fv tableSel
|
||
|
||
type Fields a = [(FieldName, a)]
|
||
|
||
data ArraySelectG (b :: BackendType) v
|
||
= ASSimple !(ArrayRelationSelectG b v)
|
||
| ASAggregate !(ArrayAggregateSelectG b v)
|
||
| ASConnection !(ArrayConnectionSelect b v)
|
||
|
||
traverseArraySelect
|
||
:: (Applicative f)
|
||
=> (a -> f b)
|
||
-> ArraySelectG backend a
|
||
-> f (ArraySelectG backend b)
|
||
traverseArraySelect f = \case
|
||
ASSimple arrRel ->
|
||
ASSimple <$> traverse (traverseAnnSimpleSelect f) arrRel
|
||
ASAggregate arrRelAgg ->
|
||
ASAggregate <$> traverse (traverseAnnAggregateSelect f) arrRelAgg
|
||
ASConnection relConnection ->
|
||
ASConnection <$> traverse (traverseConnectionSelect f) relConnection
|
||
|
||
type ArraySelect b = ArraySelectG b (SQLExp b)
|
||
|
||
type ArraySelectFieldsG b v = Fields (ArraySelectG b v)
|
||
|
||
data ColumnOp (b :: BackendType)
|
||
= ColumnOp
|
||
{ _colOp :: PG.SQLOp
|
||
, _colExp :: (SQLExp b)
|
||
}
|
||
deriving instance Show (ColumnOp 'Postgres)
|
||
deriving instance Eq (ColumnOp 'Postgres)
|
||
|
||
data AnnColumnField (b :: BackendType)
|
||
= AnnColumnField
|
||
{ _acfInfo :: !(ColumnInfo b)
|
||
, _acfAsText :: !Bool
|
||
-- ^ If this field is 'True', columns are explicitly casted to @text@ when fetched, which avoids
|
||
-- an issue that occurs because we don’t currently have proper support for array types. See
|
||
-- https://github.com/hasura/graphql-engine/pull/3198 for more details.
|
||
, _acfOp :: !(Maybe (ColumnOp b))
|
||
}
|
||
|
||
data RemoteFieldArgument
|
||
= RemoteFieldArgument
|
||
{ _rfaArgument :: !G.Name
|
||
, _rfaValue :: !(InputValue Variable)
|
||
} deriving (Eq,Show)
|
||
|
||
data RemoteSelect (b :: BackendType)
|
||
= RemoteSelect
|
||
{ _rselArgs :: ![RemoteFieldArgument]
|
||
, _rselSelection :: !(G.SelectionSet G.NoFragments Variable)
|
||
, _rselHasuraColumns :: !(HashSet (ColumnInfo b))
|
||
, _rselFieldCall :: !(NonEmpty FieldCall)
|
||
, _rselRemoteSchema :: !RemoteSchemaInfo
|
||
}
|
||
|
||
data AnnFieldG (b :: BackendType) v
|
||
= AFColumn !(AnnColumnField b)
|
||
| AFObjectRelation !(ObjectRelationSelectG b v)
|
||
| AFArrayRelation !(ArraySelectG b v)
|
||
| AFComputedField !(ComputedFieldSelect b v)
|
||
| AFRemote !(RemoteSelect b)
|
||
| AFNodeId !(TableName b) !(PrimaryKeyColumns b)
|
||
| AFExpression !Text
|
||
|
||
mkAnnColumnField :: ColumnInfo backend -> Maybe (ColumnOp backend) -> AnnFieldG backend v
|
||
mkAnnColumnField ci colOpM =
|
||
AFColumn $ AnnColumnField ci False colOpM
|
||
|
||
mkAnnColumnFieldAsText :: ColumnInfo backend -> AnnFieldG backend v
|
||
mkAnnColumnFieldAsText ci =
|
||
AFColumn $ AnnColumnField ci True Nothing
|
||
|
||
traverseAnnField
|
||
:: (Applicative f)
|
||
=> (a -> f b) -> AnnFieldG backend a -> f (AnnFieldG backend b)
|
||
traverseAnnField f = \case
|
||
AFColumn colFld -> pure $ AFColumn colFld
|
||
AFObjectRelation sel -> AFObjectRelation <$> traverse (traverseAnnObjectSelect f) sel
|
||
AFArrayRelation sel -> AFArrayRelation <$> traverseArraySelect f sel
|
||
AFComputedField sel -> AFComputedField <$> traverseComputedFieldSelect f sel
|
||
AFRemote s -> pure $ AFRemote s
|
||
AFNodeId qt pKeys -> pure $ AFNodeId qt pKeys
|
||
AFExpression t -> AFExpression <$> pure t
|
||
|
||
type AnnField b = AnnFieldG b (SQLExp b)
|
||
|
||
data SelectArgsG (b :: BackendType) v
|
||
= SelectArgs
|
||
{ _saWhere :: !(Maybe (AnnBoolExp b v))
|
||
, _saOrderBy :: !(Maybe (NE.NonEmpty (AnnOrderByItemG b v)))
|
||
, _saLimit :: !(Maybe Int)
|
||
, _saOffset :: !(Maybe (SQLExp b))
|
||
, _saDistinct :: !(Maybe (NE.NonEmpty (Column b)))
|
||
} deriving (Generic)
|
||
deriving instance Eq v => Eq (SelectArgsG 'Postgres v)
|
||
instance (Hashable v) => Hashable (SelectArgsG 'Postgres v)
|
||
|
||
traverseSelectArgs
|
||
:: (Applicative f)
|
||
=> (a -> f b) -> SelectArgsG backend a -> f (SelectArgsG backend b)
|
||
traverseSelectArgs f (SelectArgs wh ordBy lmt ofst distCols) =
|
||
SelectArgs
|
||
<$> traverse (traverseAnnBoolExp f) wh
|
||
-- traversing through maybe -> nonempty -> annorderbyitem
|
||
<*> traverse (traverse (traverseAnnOrderByItem f)) ordBy
|
||
<*> pure lmt
|
||
<*> pure ofst
|
||
<*> pure distCols
|
||
|
||
type SelectArgs b = SelectArgsG b (SQLExp b)
|
||
|
||
noSelectArgs :: SelectArgsG backend v
|
||
noSelectArgs = SelectArgs Nothing Nothing Nothing Nothing Nothing
|
||
|
||
data ColFld (b :: BackendType)
|
||
= CFCol !(Column b)
|
||
| CFExp !Text
|
||
{-
|
||
deriving instance Eq (Column b) => Eq (ColFld b)
|
||
deriving instance Show (Column b) => Show (ColFld b)
|
||
-}
|
||
|
||
type ColumnFields b = Fields (ColFld b)
|
||
|
||
data AggregateOp (b :: BackendType)
|
||
= AggregateOp
|
||
{ _aoOp :: !Text
|
||
, _aoFields :: !(ColumnFields b)
|
||
}
|
||
|
||
data AggregateField (b :: BackendType)
|
||
= AFCount !PG.CountType
|
||
| AFOp !(AggregateOp b)
|
||
| AFExp !Text
|
||
|
||
type AggregateFields b = Fields (AggregateField b)
|
||
type AnnFieldsG b v = Fields (AnnFieldG b v)
|
||
|
||
traverseAnnFields
|
||
:: (Applicative f)
|
||
=> (a -> f b) -> AnnFieldsG backend a -> f (AnnFieldsG backend b)
|
||
traverseAnnFields f = traverse (traverse (traverseAnnField f))
|
||
|
||
type AnnFields b = AnnFieldsG b (SQLExp b)
|
||
|
||
data TableAggregateFieldG (b :: BackendType) v
|
||
= TAFAgg !(AggregateFields b)
|
||
| TAFNodes !(AnnFieldsG b v)
|
||
| TAFExp !Text
|
||
|
||
data PageInfoField
|
||
= PageInfoTypename !Text
|
||
| PageInfoHasNextPage
|
||
| PageInfoHasPreviousPage
|
||
| PageInfoStartCursor
|
||
| PageInfoEndCursor
|
||
deriving (Show, Eq)
|
||
type PageInfoFields = Fields PageInfoField
|
||
|
||
data EdgeField (b :: BackendType) v
|
||
= EdgeTypename !Text
|
||
| EdgeCursor
|
||
| EdgeNode !(AnnFieldsG b v)
|
||
type EdgeFields b v = Fields (EdgeField b v)
|
||
|
||
traverseEdgeField
|
||
:: (Applicative f)
|
||
=> (a -> f b) -> EdgeField backend a -> f (EdgeField backend b)
|
||
traverseEdgeField f = \case
|
||
EdgeTypename t -> pure $ EdgeTypename t
|
||
EdgeCursor -> pure EdgeCursor
|
||
EdgeNode fields -> EdgeNode <$> traverseAnnFields f fields
|
||
|
||
data ConnectionField (b :: BackendType) v
|
||
= ConnectionTypename !Text
|
||
| ConnectionPageInfo !PageInfoFields
|
||
| ConnectionEdges !(EdgeFields b v)
|
||
type ConnectionFields b v = Fields (ConnectionField b v)
|
||
|
||
traverseConnectionField
|
||
:: (Applicative f)
|
||
=> (a -> f b) -> ConnectionField backend a -> f (ConnectionField backend b)
|
||
traverseConnectionField f = \case
|
||
ConnectionTypename t -> pure $ ConnectionTypename t
|
||
ConnectionPageInfo fields -> pure $ ConnectionPageInfo fields
|
||
ConnectionEdges fields ->
|
||
ConnectionEdges <$> traverse (traverse (traverseEdgeField f)) fields
|
||
|
||
traverseTableAggregateField
|
||
:: (Applicative f)
|
||
=> (a -> f b) -> TableAggregateFieldG backend a -> f (TableAggregateFieldG backend b)
|
||
traverseTableAggregateField f = \case
|
||
TAFAgg aggFlds -> pure $ TAFAgg aggFlds
|
||
TAFNodes annFlds -> TAFNodes <$> traverseAnnFields f annFlds
|
||
TAFExp t -> pure $ TAFExp t
|
||
|
||
type TableAggregateField b = TableAggregateFieldG b (SQLExp b)
|
||
type TableAggregateFieldsG b v = Fields (TableAggregateFieldG b v)
|
||
type TableAggregateFields b = TableAggregateFieldsG b (SQLExp b)
|
||
|
||
data ArgumentExp a
|
||
= AETableRow !(Maybe PG.Identifier) -- ^ table row accessor
|
||
| AESession !a -- ^ JSON/JSONB hasura session variable object
|
||
| AEInput !a
|
||
deriving (Show, Eq, Functor, Foldable, Traversable, Generic)
|
||
instance (Hashable v) => Hashable (ArgumentExp v)
|
||
|
||
type FunctionArgsExpTableRow v = FunctionArgsExpG (ArgumentExp v)
|
||
|
||
data SelectFromG (b :: BackendType) v
|
||
= FromTable !(TableName b)
|
||
| FromIdentifier !PG.Identifier
|
||
| FromFunction !PG.QualifiedFunction
|
||
!(FunctionArgsExpTableRow v)
|
||
-- a definition list
|
||
!(Maybe [(Column b, ScalarType b)])
|
||
deriving (Functor, Foldable, Traversable, Generic)
|
||
instance (Hashable v) => Hashable (SelectFromG 'Postgres v)
|
||
|
||
type SelectFrom b = SelectFromG b (SQLExp b)
|
||
|
||
data TablePermG (b :: BackendType) v
|
||
= TablePerm
|
||
{ _tpFilter :: !(AnnBoolExp b v)
|
||
, _tpLimit :: !(Maybe Int)
|
||
} deriving (Generic)
|
||
instance (Hashable v) => Hashable (TablePermG 'Postgres v)
|
||
|
||
traverseTablePerm
|
||
:: (Applicative f)
|
||
=> (a -> f b)
|
||
-> TablePermG backend a
|
||
-> f (TablePermG backend b)
|
||
traverseTablePerm f (TablePerm boolExp limit) =
|
||
TablePerm
|
||
<$> traverseAnnBoolExp f boolExp
|
||
<*> pure limit
|
||
|
||
noTablePermissions :: TablePermG backend v
|
||
noTablePermissions =
|
||
TablePerm annBoolExpTrue Nothing
|
||
|
||
type TablePerm b = TablePermG b (SQLExp b)
|
||
|
||
data AnnSelectG (b :: BackendType) a v
|
||
= AnnSelectG
|
||
{ _asnFields :: !a
|
||
, _asnFrom :: !(SelectFromG b v)
|
||
, _asnPerm :: !(TablePermG b v)
|
||
, _asnArgs :: !(SelectArgsG b v)
|
||
, _asnStrfyNum :: !Bool
|
||
}
|
||
|
||
traverseAnnSimpleSelect
|
||
:: (Applicative f)
|
||
=> (a -> f b)
|
||
-> AnnSimpleSelG backend a -> f (AnnSimpleSelG backend b)
|
||
traverseAnnSimpleSelect f = traverseAnnSelect (traverseAnnFields f) f
|
||
|
||
traverseAnnAggregateSelect
|
||
:: (Applicative f)
|
||
=> (a -> f b)
|
||
-> AnnAggregateSelectG backend a -> f (AnnAggregateSelectG backend b)
|
||
traverseAnnAggregateSelect f =
|
||
traverseAnnSelect (traverse (traverse (traverseTableAggregateField f))) f
|
||
|
||
traverseAnnSelect
|
||
:: (Applicative f)
|
||
=> (a -> f b) -> (v -> f w)
|
||
-> AnnSelectG backend a v -> f (AnnSelectG backend b w)
|
||
traverseAnnSelect f1 f2 (AnnSelectG flds tabFrom perm args strfyNum) =
|
||
AnnSelectG
|
||
<$> f1 flds
|
||
<*> traverse f2 tabFrom
|
||
<*> traverseTablePerm f2 perm
|
||
<*> traverseSelectArgs f2 args
|
||
<*> pure strfyNum
|
||
|
||
type AnnSimpleSelG b v = AnnSelectG b (AnnFieldsG b v) v
|
||
type AnnSimpleSel b = AnnSimpleSelG b (SQLExp b)
|
||
|
||
type AnnAggregateSelectG b v = AnnSelectG b (TableAggregateFieldsG b v) v
|
||
type AnnAggregateSelect b = AnnAggregateSelectG b (SQLExp b)
|
||
|
||
data ConnectionSlice
|
||
= SliceFirst !Int
|
||
| SliceLast !Int
|
||
deriving (Show, Eq, Generic)
|
||
instance Hashable ConnectionSlice
|
||
|
||
data ConnectionSplitKind
|
||
= CSKBefore
|
||
| CSKAfter
|
||
deriving (Show, Eq, Generic)
|
||
instance Hashable ConnectionSplitKind
|
||
|
||
data ConnectionSplit (b :: BackendType) v
|
||
= ConnectionSplit
|
||
{ _csKind :: !ConnectionSplitKind
|
||
, _csValue :: !v
|
||
, _csOrderBy :: !(OrderByItemG b (AnnOrderByElementG b ()))
|
||
} deriving (Functor, Generic, Foldable, Traversable)
|
||
instance (Hashable v) => Hashable (ConnectionSplit 'Postgres v)
|
||
|
||
traverseConnectionSplit
|
||
:: (Applicative f)
|
||
=> (a -> f b) -> ConnectionSplit backend a -> f (ConnectionSplit backend b)
|
||
traverseConnectionSplit f (ConnectionSplit k v ob) =
|
||
ConnectionSplit k <$> f v <*> pure ob
|
||
|
||
data ConnectionSelect (b :: BackendType) v
|
||
= ConnectionSelect
|
||
{ _csPrimaryKeyColumns :: !(PrimaryKeyColumns b)
|
||
, _csSplit :: !(Maybe (NE.NonEmpty (ConnectionSplit b v)))
|
||
, _csSlice :: !(Maybe ConnectionSlice)
|
||
, _csSelect :: !(AnnSelectG b (ConnectionFields b v) v)
|
||
}
|
||
|
||
traverseConnectionSelect
|
||
:: (Applicative f)
|
||
=> (a -> f b)
|
||
-> ConnectionSelect backend a -> f (ConnectionSelect backend b)
|
||
traverseConnectionSelect f (ConnectionSelect pkCols cSplit cSlice sel) =
|
||
ConnectionSelect pkCols
|
||
<$> traverse (traverse (traverseConnectionSplit f)) cSplit
|
||
<*> pure cSlice
|
||
<*> traverseAnnSelect (traverse (traverse (traverseConnectionField f))) f sel
|
||
|
||
data FunctionArgsExpG a
|
||
= FunctionArgsExp
|
||
{ _faePositional :: ![a]
|
||
, _faeNamed :: !(HM.HashMap Text a)
|
||
} deriving (Show, Eq, Functor, Foldable, Traversable, Generic)
|
||
instance (Hashable a) => Hashable (FunctionArgsExpG a)
|
||
|
||
emptyFunctionArgsExp :: FunctionArgsExpG a
|
||
emptyFunctionArgsExp = FunctionArgsExp [] HM.empty
|
||
|
||
type FunctionArgExp b = FunctionArgsExpG (SQLExp b)
|
||
|
||
-- | If argument positional index is less than or equal to length of
|
||
-- 'positional' arguments then insert the value in 'positional' arguments else
|
||
-- insert the value with argument name in 'named' arguments
|
||
insertFunctionArg
|
||
:: FunctionArgName
|
||
-> Int
|
||
-> a
|
||
-> FunctionArgsExpG a
|
||
-> FunctionArgsExpG a
|
||
insertFunctionArg argName idx value (FunctionArgsExp positional named) =
|
||
if (idx + 1) <= length positional then
|
||
FunctionArgsExp (insertAt idx value positional) named
|
||
else FunctionArgsExp positional $
|
||
HM.insert (getFuncArgNameTxt argName) value named
|
||
where
|
||
insertAt i a = toList . Seq.insertAt i a . Seq.fromList
|
||
|
||
data SourcePrefixes
|
||
= SourcePrefixes
|
||
{ _pfThis :: !PG.Identifier -- ^ Current source prefix
|
||
, _pfBase :: !PG.Identifier
|
||
-- ^ Base table source row identifier to generate
|
||
-- the table's column identifiers for computed field
|
||
-- function input parameters
|
||
} deriving (Show, Eq, Generic)
|
||
instance Hashable SourcePrefixes
|
||
|
||
data SelectSource (b :: BackendType)
|
||
= SelectSource
|
||
{ _ssPrefix :: !PG.Identifier
|
||
, _ssFrom :: !PG.FromItem
|
||
, _ssDistinct :: !(Maybe PG.DistinctExpr)
|
||
, _ssWhere :: !PG.BoolExp
|
||
, _ssOrderBy :: !(Maybe PG.OrderByExp)
|
||
, _ssLimit :: !(Maybe Int)
|
||
, _ssOffset :: !(Maybe (SQLExp b))
|
||
} deriving (Generic)
|
||
instance Hashable (SelectSource 'Postgres)
|
||
deriving instance Show (SelectSource 'Postgres)
|
||
deriving instance Eq (SelectSource 'Postgres)
|
||
|
||
data SelectNode (b :: BackendType)
|
||
= SelectNode
|
||
{ _snExtractors :: !(HM.HashMap PG.Alias (SQLExp b))
|
||
, _snJoinTree :: !(JoinTree b)
|
||
}
|
||
|
||
instance Semigroup (SelectNode 'Postgres) where
|
||
SelectNode lExtrs lJoinTree <> SelectNode rExtrs rJoinTree =
|
||
SelectNode (lExtrs <> rExtrs) (lJoinTree <> rJoinTree)
|
||
|
||
data ObjectSelectSource
|
||
= ObjectSelectSource
|
||
{ _ossPrefix :: !PG.Identifier
|
||
, _ossFrom :: !PG.FromItem
|
||
, _ossWhere :: !PG.BoolExp
|
||
} deriving (Show, Eq, Generic)
|
||
instance Hashable ObjectSelectSource
|
||
|
||
objectSelectSourceToSelectSource :: ObjectSelectSource -> (SelectSource backend)
|
||
objectSelectSourceToSelectSource ObjectSelectSource{..} =
|
||
SelectSource _ossPrefix _ossFrom Nothing _ossWhere Nothing Nothing Nothing
|
||
|
||
data ObjectRelationSource (b :: BackendType)
|
||
= ObjectRelationSource
|
||
{ _orsRelationshipName :: !RelName
|
||
, _orsRelationMapping :: !(HM.HashMap (Column b) (Column b))
|
||
, _orsSelectSource :: !ObjectSelectSource
|
||
} deriving (Generic)
|
||
instance Hashable (ObjectRelationSource 'Postgres)
|
||
deriving instance Eq (Column b) => Eq (ObjectRelationSource b)
|
||
|
||
data ArrayRelationSource (b :: BackendType)
|
||
= ArrayRelationSource
|
||
{ _arsAlias :: !PG.Alias
|
||
, _arsRelationMapping :: !(HM.HashMap (Column b) (Column b))
|
||
, _arsSelectSource :: !(SelectSource b)
|
||
} deriving (Generic)
|
||
instance Hashable (ArrayRelationSource 'Postgres)
|
||
deriving instance Eq (ArrayRelationSource 'Postgres)
|
||
|
||
data ArraySelectNode (b :: BackendType)
|
||
= ArraySelectNode
|
||
{ _asnTopExtractors :: ![PG.Extractor]
|
||
, _asnSelectNode :: !(SelectNode b)
|
||
}
|
||
|
||
instance Semigroup (ArraySelectNode 'Postgres) where
|
||
ArraySelectNode lTopExtrs lSelNode <> ArraySelectNode rTopExtrs rSelNode =
|
||
ArraySelectNode (lTopExtrs <> rTopExtrs) (lSelNode <> rSelNode)
|
||
|
||
data ComputedFieldTableSetSource (b :: BackendType)
|
||
= ComputedFieldTableSetSource
|
||
{ _cftssFieldName :: !FieldName
|
||
, _cftssSelectType :: !JsonAggSelect
|
||
, _cftssSelectSource :: !(SelectSource b)
|
||
} deriving (Generic)
|
||
instance Hashable (ComputedFieldTableSetSource 'Postgres)
|
||
deriving instance Show (ComputedFieldTableSetSource 'Postgres)
|
||
deriving instance Eq (ComputedFieldTableSetSource 'Postgres)
|
||
|
||
data ArrayConnectionSource (b :: BackendType)
|
||
= ArrayConnectionSource
|
||
{ _acsAlias :: !PG.Alias
|
||
, _acsRelationMapping :: !(HM.HashMap (Column b) (Column b))
|
||
, _acsSplitFilter :: !(Maybe PG.BoolExp)
|
||
, _acsSlice :: !(Maybe ConnectionSlice)
|
||
, _acsSource :: !(SelectSource b)
|
||
} deriving (Generic)
|
||
deriving instance Eq (ArrayConnectionSource 'Postgres)
|
||
|
||
instance Hashable (ArrayConnectionSource 'Postgres)
|
||
|
||
data JoinTree (b :: BackendType)
|
||
= JoinTree
|
||
{ _jtObjectRelations :: !(HM.HashMap (ObjectRelationSource b) (SelectNode b))
|
||
, _jtArrayRelations :: !(HM.HashMap (ArrayRelationSource b) (ArraySelectNode b))
|
||
, _jtArrayConnections :: !(HM.HashMap (ArrayConnectionSource b) (ArraySelectNode b))
|
||
, _jtComputedFieldTableSets :: !(HM.HashMap (ComputedFieldTableSetSource b) (SelectNode b))
|
||
}
|
||
|
||
instance Semigroup (JoinTree 'Postgres) where
|
||
JoinTree lObjs lArrs lArrConns lCfts <> JoinTree rObjs rArrs rArrConns rCfts =
|
||
JoinTree (HM.unionWith (<>) lObjs rObjs)
|
||
(HM.unionWith (<>) lArrs rArrs)
|
||
(HM.unionWith (<>) lArrConns rArrConns)
|
||
(HM.unionWith (<>) lCfts rCfts)
|
||
|
||
instance Monoid (JoinTree 'Postgres) where
|
||
mempty = JoinTree mempty mempty mempty mempty
|
||
|
||
data PermissionLimitSubQuery
|
||
= PLSQRequired !Int -- ^ Permission limit
|
||
| PLSQNotRequired
|
||
deriving (Show, Eq)
|
||
|
||
$(makeLenses ''AnnSelectG)
|
||
$(makePrisms ''AnnFieldG)
|
||
$(makePrisms ''AnnOrderByElementG)
|