{-# LANGUAGE ViewPatterns #-}

-- | This module defines translation functions for queries which select data.
-- Principally this includes translating the @query@ root field, but parts are
-- also reused for serving the responses for mutations.
module Hasura.Backends.MSSQL.FromIr.Query
  ( fromQueryRootField,
    fromSelect,
    fromSourceRelationship,
  )
where

import Control.Applicative (getConst)
import Control.Monad.Validate
import Data.Aeson.Extended qualified as J
import Data.HashMap.Strict qualified as HM
import Data.List.NonEmpty qualified as NE
import Data.Map.Strict (Map)
import Data.Map.Strict qualified as M
import Data.Proxy
import Data.Text.NonEmpty (mkNonEmptyTextUnsafe)
import Database.ODBC.SQLServer qualified as ODBC
import Hasura.Backends.MSSQL.FromIr
  ( Error (..),
    FromIr,
    NameTemplate (..),
    generateAlias,
  )
import Hasura.Backends.MSSQL.FromIr.Constants
import Hasura.Backends.MSSQL.FromIr.Expression
import Hasura.Backends.MSSQL.Instances.Types ()
import Hasura.Backends.MSSQL.Types.Internal as TSQL
import Hasura.Prelude
import Hasura.RQL.IR qualified as IR
import Hasura.RQL.Types.Column qualified as IR
import Hasura.RQL.Types.Common qualified as IR
import Hasura.RQL.Types.Relationships.Local qualified as IR
import Hasura.SQL.Backend

-- | This is the top-level entry point for translation of Query root fields.
fromQueryRootField :: IR.QueryDB 'MSSQL Void Expression -> FromIr Select
fromQueryRootField :: QueryDB 'MSSQL Void Expression -> FromIr Select
fromQueryRootField =
  \case
    (IR.QDBSingleRow AnnSimpleSelectG 'MSSQL Void Expression
s) -> JsonAggSelect
-> AnnSimpleSelectG 'MSSQL Void Expression -> FromIr Select
fromSelect JsonAggSelect
IR.JASSingleObject AnnSimpleSelectG 'MSSQL Void Expression
s
    (IR.QDBMultipleRows AnnSimpleSelectG 'MSSQL Void Expression
s) -> JsonAggSelect
-> AnnSimpleSelectG 'MSSQL Void Expression -> FromIr Select
fromSelect JsonAggSelect
IR.JASMultipleRows AnnSimpleSelectG 'MSSQL Void Expression
s
    (IR.QDBAggregation AnnAggregateSelectG 'MSSQL Void Expression
s) -> Maybe (EntityAlias, HashMap ColumnName ColumnName)
-> AnnAggregateSelectG 'MSSQL Void Expression -> FromIr Select
fromSelectAggregate Maybe (EntityAlias, HashMap ColumnName ColumnName)
forall a. Maybe a
Nothing AnnAggregateSelectG 'MSSQL Void Expression
s

fromSelect ::
  IR.JsonAggSelect ->
  IR.AnnSelectG 'MSSQL (IR.AnnFieldG 'MSSQL Void) Expression ->
  FromIr TSQL.Select
fromSelect :: JsonAggSelect
-> AnnSimpleSelectG 'MSSQL Void Expression -> FromIr Select
fromSelect JsonAggSelect
jsonAggSelect AnnSimpleSelectG 'MSSQL Void Expression
annSimpleSel =
  case JsonAggSelect
jsonAggSelect of
    JsonAggSelect
IR.JASMultipleRows ->
      Expression -> Select -> Select
guardSelectYieldingNull Expression
emptyArrayExpression (Select -> Select) -> FromIr Select -> FromIr Select
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> AnnSimpleSelectG 'MSSQL Void Expression -> FromIr Select
fromSelectRows AnnSimpleSelectG 'MSSQL Void Expression
annSimpleSel
    JsonAggSelect
IR.JASSingleObject ->
      (Select -> Select) -> FromIr Select -> FromIr Select
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap (Expression -> Select -> Select
guardSelectYieldingNull Expression
nullExpression) (FromIr Select -> FromIr Select) -> FromIr Select -> FromIr Select
forall a b. (a -> b) -> a -> b
$
        AnnSimpleSelectG 'MSSQL Void Expression -> FromIr Select
fromSelectRows AnnSimpleSelectG 'MSSQL Void Expression
annSimpleSel FromIr Select -> (Select -> Select) -> FromIr Select
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> \Select
sel ->
          Select
sel
            { $sel:selectFor:Select :: For
selectFor =
                ForJson -> For
JsonFor
                  ForJson :: JsonCardinality -> Root -> ForJson
ForJson {$sel:jsonCardinality:ForJson :: JsonCardinality
jsonCardinality = JsonCardinality
JsonSingleton, $sel:jsonRoot:ForJson :: Root
jsonRoot = Root
NoRoot},
              $sel:selectTop:Select :: Top
selectTop = Int -> Top
Top Int
1
            }
  where
    guardSelectYieldingNull :: TSQL.Expression -> TSQL.Select -> TSQL.Select
    guardSelectYieldingNull :: Expression -> Select -> Select
guardSelectYieldingNull Expression
fallbackExpression Select
select =
      let isNullApplication :: FunctionApplicationExpression
isNullApplication = Expression -> Expression -> FunctionApplicationExpression
FunExpISNULL (Select -> Expression
SelectExpression Select
select) Expression
fallbackExpression
       in Select
emptySelect
            { $sel:selectProjections:Select :: [Projection]
selectProjections =
                [ Aliased Expression -> Projection
ExpressionProjection (Aliased Expression -> Projection)
-> Aliased Expression -> Projection
forall a b. (a -> b) -> a -> b
$
                    Aliased :: forall a. a -> Text -> Aliased a
Aliased
                      { $sel:aliasedThing:Aliased :: Expression
aliasedThing = FunctionApplicationExpression -> Expression
FunctionApplicationExpression FunctionApplicationExpression
isNullApplication,
                        $sel:aliasedAlias:Aliased :: Text
aliasedAlias = Text
"root"
                      }
                ]
            }

-- | Used in 'Hasura.Backends.MSSQL.Plan.planSourceRelationship', which is in
-- turn used by to implement `mkDBRemoteRelationship' for 'BackendExecute'.
-- For more information, see the module/documentation of 'Hasura.GraphQL.Execute.RemoteJoin.Source'.
fromSourceRelationship ::
  -- | List of json objects, each of which becomes a row of the table
  NE.NonEmpty J.Object ->
  -- | The above objects have this schema
  HM.HashMap IR.FieldName (ColumnName, ScalarType) ->
  IR.FieldName ->
  (IR.FieldName, IR.SourceRelationshipSelection 'MSSQL Void (Const Expression)) ->
  FromIr TSQL.Select
fromSourceRelationship :: NonEmpty Object
-> HashMap FieldName (ColumnName, ScalarType)
-> FieldName
-> (FieldName,
    SourceRelationshipSelection 'MSSQL Void (Const Expression))
-> FromIr Select
fromSourceRelationship NonEmpty Object
lhs HashMap FieldName (ColumnName, ScalarType)
lhsSchema FieldName
argumentId (FieldName,
 SourceRelationshipSelection 'MSSQL Void (Const Expression))
relationshipField = do
  (Expression
argumentIdQualified, FieldSource
fieldSource) <-
    (ReaderT EntityAlias FromIr (Expression, FieldSource)
 -> EntityAlias -> FromIr (Expression, FieldSource))
-> EntityAlias
-> ReaderT EntityAlias FromIr (Expression, FieldSource)
-> FromIr (Expression, FieldSource)
forall a b c. (a -> b -> c) -> b -> a -> c
flip ReaderT EntityAlias FromIr (Expression, FieldSource)
-> EntityAlias -> FromIr (Expression, FieldSource)
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT (From -> EntityAlias
fromAlias From
selectFrom) (ReaderT EntityAlias FromIr (Expression, FieldSource)
 -> FromIr (Expression, FieldSource))
-> ReaderT EntityAlias FromIr (Expression, FieldSource)
-> FromIr (Expression, FieldSource)
forall a b. (a -> b) -> a -> b
$ do
      FieldName
argumentIdQualified <- ColumnName -> ReaderT EntityAlias FromIr FieldName
fromColumn (FieldName -> ColumnName
coerceToColumn FieldName
argumentId)
      FieldSource
relationshipSource <-
        Map TableName EntityAlias
-> HashMap ColumnName ColumnName
-> (FieldName,
    SourceRelationshipSelection 'MSSQL Void (Const Expression))
-> ReaderT EntityAlias FromIr FieldSource
fromRemoteRelationFieldsG
          Map TableName EntityAlias
forall a. Monoid a => a
mempty
          ((ColumnName, ScalarType) -> ColumnName
forall a b. (a, b) -> a
fst ((ColumnName, ScalarType) -> ColumnName)
-> HashMap ColumnName (ColumnName, ScalarType)
-> HashMap ColumnName ColumnName
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> HashMap ColumnName (ColumnName, ScalarType)
joinColumns)
          (FieldName,
 SourceRelationshipSelection 'MSSQL Void (Const Expression))
relationshipField
      (Expression, FieldSource)
-> ReaderT EntityAlias FromIr (Expression, FieldSource)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (FieldName -> Expression
ColumnExpression FieldName
argumentIdQualified, FieldSource
relationshipSource)
  let selectProjections :: [Projection]
selectProjections = [Expression -> Projection
projectArgumentId Expression
argumentIdQualified, FieldSource -> Projection
fieldSourceProjections FieldSource
fieldSource]
  Select -> FromIr Select
forall (f :: * -> *) a. Applicative f => a -> f a
pure
    Select :: Maybe With
-> Top
-> [Projection]
-> Maybe From
-> [Join]
-> Where
-> For
-> Maybe (NonEmpty OrderBy)
-> Maybe Expression
-> Select
Select
      { $sel:selectWith:Select :: Maybe With
selectWith = Maybe With
forall a. Maybe a
Nothing,
        $sel:selectOrderBy:Select :: Maybe (NonEmpty OrderBy)
selectOrderBy = Maybe (NonEmpty OrderBy)
forall a. Maybe a
Nothing,
        $sel:selectTop:Select :: Top
selectTop = Top
NoTop,
        [Projection]
selectProjections :: [Projection]
$sel:selectProjections:Select :: [Projection]
selectProjections,
        $sel:selectFrom:Select :: Maybe From
selectFrom = From -> Maybe From
forall a. a -> Maybe a
Just From
selectFrom,
        $sel:selectJoins:Select :: [Join]
selectJoins = (FieldSource -> Maybe Join) -> [FieldSource] -> [Join]
forall (f :: * -> *) a b.
Filterable f =>
(a -> Maybe b) -> f a -> f b
mapMaybe FieldSource -> Maybe Join
fieldSourceJoin ([FieldSource] -> [Join]) -> [FieldSource] -> [Join]
forall a b. (a -> b) -> a -> b
$ FieldSource -> [FieldSource]
forall (f :: * -> *) a. Applicative f => a -> f a
pure FieldSource
fieldSource,
        $sel:selectWhere:Select :: Where
selectWhere = Where
forall a. Monoid a => a
mempty,
        $sel:selectFor:Select :: For
selectFor =
          ForJson -> For
JsonFor ForJson :: JsonCardinality -> Root -> ForJson
ForJson {$sel:jsonCardinality:ForJson :: JsonCardinality
jsonCardinality = JsonCardinality
JsonArray, $sel:jsonRoot:ForJson :: Root
jsonRoot = Root
NoRoot},
        $sel:selectOffset:Select :: Maybe Expression
selectOffset = Maybe Expression
forall a. Maybe a
Nothing
      }
  where
    projectArgumentId :: Expression -> Projection
projectArgumentId Expression
column =
      Aliased Expression -> Projection
ExpressionProjection (Aliased Expression -> Projection)
-> Aliased Expression -> Projection
forall a b. (a -> b) -> a -> b
$
        Aliased :: forall a. a -> Text -> Aliased a
Aliased
          { $sel:aliasedThing:Aliased :: Expression
aliasedThing = Expression
column,
            $sel:aliasedAlias:Aliased :: Text
aliasedAlias = FieldName -> Text
IR.getFieldNameTxt FieldName
argumentId
          }
    selectFrom :: From
selectFrom =
      Aliased OpenJson -> From
FromOpenJson
        Aliased :: forall a. a -> Text -> Aliased a
Aliased
          { $sel:aliasedThing:Aliased :: OpenJson
aliasedThing =
              OpenJson :: Expression -> Maybe (NonEmpty JsonFieldSpec) -> OpenJson
OpenJson
                { $sel:openJsonExpression:OpenJson :: Expression
openJsonExpression =
                    Value -> Expression
ValueExpression (Text -> Value
ODBC.TextValue (Text -> Value) -> Text -> Value
forall a b. (a -> b) -> a -> b
$ ByteString -> Text
lbsToTxt (ByteString -> Text) -> ByteString -> Text
forall a b. (a -> b) -> a -> b
$ NonEmpty Object -> ByteString
forall a. ToJSON a => a -> ByteString
J.encode NonEmpty Object
lhs),
                  $sel:openJsonWith:OpenJson :: Maybe (NonEmpty JsonFieldSpec)
openJsonWith =
                    NonEmpty JsonFieldSpec -> Maybe (NonEmpty JsonFieldSpec)
forall a. a -> Maybe a
Just (NonEmpty JsonFieldSpec -> Maybe (NonEmpty JsonFieldSpec))
-> NonEmpty JsonFieldSpec -> Maybe (NonEmpty JsonFieldSpec)
forall a b. (a -> b) -> a -> b
$
                      FieldName -> ScalarType -> JsonFieldSpec
toJsonFieldSpec FieldName
argumentId ScalarType
IntegerType
                        JsonFieldSpec -> [JsonFieldSpec] -> NonEmpty JsonFieldSpec
forall a. a -> [a] -> NonEmpty a
NE.:| ((FieldName, (ColumnName, ScalarType)) -> JsonFieldSpec)
-> [(FieldName, (ColumnName, ScalarType))] -> [JsonFieldSpec]
forall a b. (a -> b) -> [a] -> [b]
map ((FieldName -> ScalarType -> JsonFieldSpec)
-> (FieldName, ScalarType) -> JsonFieldSpec
forall a b c. (a -> b -> c) -> (a, b) -> c
uncurry FieldName -> ScalarType -> JsonFieldSpec
toJsonFieldSpec ((FieldName, ScalarType) -> JsonFieldSpec)
-> ((FieldName, (ColumnName, ScalarType))
    -> (FieldName, ScalarType))
-> (FieldName, (ColumnName, ScalarType))
-> JsonFieldSpec
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((ColumnName, ScalarType) -> ScalarType)
-> (FieldName, (ColumnName, ScalarType)) -> (FieldName, ScalarType)
forall (a :: * -> * -> *) b c d.
Arrow a =>
a b c -> a (d, b) (d, c)
second (ColumnName, ScalarType) -> ScalarType
forall a b. (a, b) -> b
snd) (HashMap FieldName (ColumnName, ScalarType)
-> [(FieldName, (ColumnName, ScalarType))]
forall k v. HashMap k v -> [(k, v)]
HM.toList HashMap FieldName (ColumnName, ScalarType)
lhsSchema)
                },
            $sel:aliasedAlias:Aliased :: Text
aliasedAlias = Text
"lhs"
          }

    joinColumns :: HashMap ColumnName (ColumnName, ScalarType)
joinColumns = (FieldName -> ColumnName)
-> HashMap FieldName (ColumnName, ScalarType)
-> HashMap ColumnName (ColumnName, ScalarType)
forall k2 k1 v.
(Eq k2, Hashable k2) =>
(k1 -> k2) -> HashMap k1 v -> HashMap k2 v
mapKeys FieldName -> ColumnName
coerceToColumn HashMap FieldName (ColumnName, ScalarType)
lhsSchema

    coerceToColumn :: FieldName -> ColumnName
coerceToColumn = Text -> ColumnName
ColumnName (Text -> ColumnName)
-> (FieldName -> Text) -> FieldName -> ColumnName
forall b c a. (b -> c) -> (a -> b) -> a -> c
. FieldName -> Text
IR.getFieldNameTxt

    toJsonFieldSpec :: FieldName -> ScalarType -> JsonFieldSpec
toJsonFieldSpec (IR.FieldName Text
lhsFieldName) ScalarType
scalarType =
      ScalarType -> DataLength -> Text -> Maybe JsonPath -> JsonFieldSpec
ScalarField ScalarType
scalarType DataLength
DataLengthMax Text
lhsFieldName (JsonPath -> Maybe JsonPath
forall a. a -> Maybe a
Just (JsonPath -> Maybe JsonPath) -> JsonPath -> Maybe JsonPath
forall a b. (a -> b) -> a -> b
$ JsonPath -> Text -> JsonPath
FieldPath JsonPath
RootPath Text
lhsFieldName)

-- | Build the 'FieldSource' for the relation field, depending on whether it's
-- an object, array, or aggregate relationship.
fromRemoteRelationFieldsG ::
  Map TableName EntityAlias ->
  HM.HashMap ColumnName ColumnName ->
  (IR.FieldName, IR.SourceRelationshipSelection 'MSSQL Void (Const Expression)) ->
  ReaderT EntityAlias FromIr FieldSource
fromRemoteRelationFieldsG :: Map TableName EntityAlias
-> HashMap ColumnName ColumnName
-> (FieldName,
    SourceRelationshipSelection 'MSSQL Void (Const Expression))
-> ReaderT EntityAlias FromIr FieldSource
fromRemoteRelationFieldsG Map TableName EntityAlias
existingJoins HashMap ColumnName ColumnName
joinColumns (IR.FieldName Text
name, SourceRelationshipSelection 'MSSQL Void (Const Expression)
field) =
  case SourceRelationshipSelection 'MSSQL Void (Const Expression)
field of
    IR.SourceRelationshipObject AnnObjectSelectG 'MSSQL Void (Const Expression 'MSSQL)
selectionSet ->
      (Join -> FieldSource)
-> ReaderT EntityAlias FromIr Join
-> ReaderT EntityAlias FromIr FieldSource
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap
        ( \Join
aliasedThing ->
            JsonCardinality -> Aliased Join -> FieldSource
JoinFieldSource JsonCardinality
JsonSingleton (Aliased :: forall a. a -> Text -> Aliased a
Aliased {Join
aliasedThing :: Join
$sel:aliasedThing:Aliased :: Join
aliasedThing, $sel:aliasedAlias:Aliased :: Text
aliasedAlias = Text
name})
        )
        ( Map TableName EntityAlias
-> ObjectRelationSelectG 'MSSQL Void Expression
-> ReaderT EntityAlias FromIr Join
fromObjectRelationSelectG
            Map TableName EntityAlias
existingJoins
            ( AnnObjectSelectG 'MSSQL Void Expression
-> ObjectRelationSelectG 'MSSQL Void Expression
forall s. s -> AnnRelationSelectG 'MSSQL s
withJoinColumns (AnnObjectSelectG 'MSSQL Void Expression
 -> ObjectRelationSelectG 'MSSQL Void Expression)
-> AnnObjectSelectG 'MSSQL Void Expression
-> ObjectRelationSelectG 'MSSQL Void Expression
forall a b. (a -> b) -> a -> b
$
                Identity (AnnObjectSelectG 'MSSQL Void Expression)
-> AnnObjectSelectG 'MSSQL Void Expression
forall a. Identity a -> a
runIdentity (Identity (AnnObjectSelectG 'MSSQL Void Expression)
 -> AnnObjectSelectG 'MSSQL Void Expression)
-> Identity (AnnObjectSelectG 'MSSQL Void Expression)
-> AnnObjectSelectG 'MSSQL Void Expression
forall a b. (a -> b) -> a -> b
$
                  (Const Expression 'MSSQL -> Identity Expression)
-> AnnObjectSelectG 'MSSQL Void (Const Expression 'MSSQL)
-> Identity (AnnObjectSelectG 'MSSQL Void Expression)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse (Expression -> Identity Expression
forall a. a -> Identity a
Identity (Expression -> Identity Expression)
-> (Const Expression 'MSSQL -> Expression)
-> Const Expression 'MSSQL
-> Identity Expression
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Const Expression 'MSSQL -> Expression
forall a k (b :: k). Const a b -> a
getConst) AnnObjectSelectG 'MSSQL Void (Const Expression 'MSSQL)
selectionSet
            )
        )
    IR.SourceRelationshipArray AnnSimpleSelectG 'MSSQL Void (Const Expression 'MSSQL)
selectionSet ->
      (Join -> FieldSource)
-> ReaderT EntityAlias FromIr Join
-> ReaderT EntityAlias FromIr FieldSource
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap
        ( \Join
aliasedThing ->
            JsonCardinality -> Aliased Join -> FieldSource
JoinFieldSource JsonCardinality
JsonArray (Aliased :: forall a. a -> Text -> Aliased a
Aliased {Join
aliasedThing :: Join
$sel:aliasedThing:Aliased :: Join
aliasedThing, $sel:aliasedAlias:Aliased :: Text
aliasedAlias = Text
name})
        )
        ( ArraySelectG 'MSSQL Void Expression
-> ReaderT EntityAlias FromIr Join
fromArraySelectG
            ( ArrayRelationSelectG 'MSSQL Void Expression
-> ArraySelectG 'MSSQL Void Expression
forall (b :: BackendType) r v.
ArrayRelationSelectG b r v -> ArraySelectG b r v
IR.ASSimple (ArrayRelationSelectG 'MSSQL Void Expression
 -> ArraySelectG 'MSSQL Void Expression)
-> ArrayRelationSelectG 'MSSQL Void Expression
-> ArraySelectG 'MSSQL Void Expression
forall a b. (a -> b) -> a -> b
$
                AnnSimpleSelectG 'MSSQL Void Expression
-> ArrayRelationSelectG 'MSSQL Void Expression
forall s. s -> AnnRelationSelectG 'MSSQL s
withJoinColumns (AnnSimpleSelectG 'MSSQL Void Expression
 -> ArrayRelationSelectG 'MSSQL Void Expression)
-> AnnSimpleSelectG 'MSSQL Void Expression
-> ArrayRelationSelectG 'MSSQL Void Expression
forall a b. (a -> b) -> a -> b
$
                  Identity (AnnSimpleSelectG 'MSSQL Void Expression)
-> AnnSimpleSelectG 'MSSQL Void Expression
forall a. Identity a -> a
runIdentity (Identity (AnnSimpleSelectG 'MSSQL Void Expression)
 -> AnnSimpleSelectG 'MSSQL Void Expression)
-> Identity (AnnSimpleSelectG 'MSSQL Void Expression)
-> AnnSimpleSelectG 'MSSQL Void Expression
forall a b. (a -> b) -> a -> b
$
                    (Const Expression 'MSSQL -> Identity Expression)
-> AnnSimpleSelectG 'MSSQL Void (Const Expression 'MSSQL)
-> Identity (AnnSimpleSelectG 'MSSQL Void Expression)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse (Expression -> Identity Expression
forall a. a -> Identity a
Identity (Expression -> Identity Expression)
-> (Const Expression 'MSSQL -> Expression)
-> Const Expression 'MSSQL
-> Identity Expression
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Const Expression 'MSSQL -> Expression
forall a k (b :: k). Const a b -> a
getConst) AnnSimpleSelectG 'MSSQL Void (Const Expression 'MSSQL)
selectionSet
            )
        )
    IR.SourceRelationshipArrayAggregate AnnAggregateSelectG 'MSSQL Void (Const Expression 'MSSQL)
selectionSet ->
      (Join -> FieldSource)
-> ReaderT EntityAlias FromIr Join
-> ReaderT EntityAlias FromIr FieldSource
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap
        ( \Join
aliasedThing ->
            JsonCardinality -> Aliased Join -> FieldSource
JoinFieldSource JsonCardinality
JsonArray (Aliased :: forall a. a -> Text -> Aliased a
Aliased {Join
aliasedThing :: Join
$sel:aliasedThing:Aliased :: Join
aliasedThing, $sel:aliasedAlias:Aliased :: Text
aliasedAlias = Text
name})
        )
        ( ArraySelectG 'MSSQL Void Expression
-> ReaderT EntityAlias FromIr Join
fromArraySelectG
            ( ArrayAggregateSelectG 'MSSQL Void Expression
-> ArraySelectG 'MSSQL Void Expression
forall (b :: BackendType) r v.
ArrayAggregateSelectG b r v -> ArraySelectG b r v
IR.ASAggregate (ArrayAggregateSelectG 'MSSQL Void Expression
 -> ArraySelectG 'MSSQL Void Expression)
-> ArrayAggregateSelectG 'MSSQL Void Expression
-> ArraySelectG 'MSSQL Void Expression
forall a b. (a -> b) -> a -> b
$
                AnnAggregateSelectG 'MSSQL Void Expression
-> ArrayAggregateSelectG 'MSSQL Void Expression
forall s. s -> AnnRelationSelectG 'MSSQL s
withJoinColumns (AnnAggregateSelectG 'MSSQL Void Expression
 -> ArrayAggregateSelectG 'MSSQL Void Expression)
-> AnnAggregateSelectG 'MSSQL Void Expression
-> ArrayAggregateSelectG 'MSSQL Void Expression
forall a b. (a -> b) -> a -> b
$
                  Identity (AnnAggregateSelectG 'MSSQL Void Expression)
-> AnnAggregateSelectG 'MSSQL Void Expression
forall a. Identity a -> a
runIdentity (Identity (AnnAggregateSelectG 'MSSQL Void Expression)
 -> AnnAggregateSelectG 'MSSQL Void Expression)
-> Identity (AnnAggregateSelectG 'MSSQL Void Expression)
-> AnnAggregateSelectG 'MSSQL Void Expression
forall a b. (a -> b) -> a -> b
$
                    (Const Expression 'MSSQL -> Identity Expression)
-> AnnAggregateSelectG 'MSSQL Void (Const Expression 'MSSQL)
-> Identity (AnnAggregateSelectG 'MSSQL Void Expression)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse (Expression -> Identity Expression
forall a. a -> Identity a
Identity (Expression -> Identity Expression)
-> (Const Expression 'MSSQL -> Expression)
-> Const Expression 'MSSQL
-> Identity Expression
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Const Expression 'MSSQL -> Expression
forall a k (b :: k). Const a b -> a
getConst) AnnAggregateSelectG 'MSSQL Void (Const Expression 'MSSQL)
selectionSet
            )
        )
  where
    withJoinColumns ::
      s -> IR.AnnRelationSelectG 'MSSQL s
    withJoinColumns :: s -> AnnRelationSelectG 'MSSQL s
withJoinColumns s
annotatedRelationship =
      RelName
-> HashMap (Column 'MSSQL) (Column 'MSSQL)
-> s
-> AnnRelationSelectG 'MSSQL s
forall (b :: BackendType) a.
RelName
-> HashMap (Column b) (Column b) -> a -> AnnRelationSelectG b a
IR.AnnRelationSelectG
        (NonEmptyText -> RelName
IR.RelName (NonEmptyText -> RelName) -> NonEmptyText -> RelName
forall a b. (a -> b) -> a -> b
$ Text -> NonEmptyText
mkNonEmptyTextUnsafe Text
name)
        HashMap (Column 'MSSQL) (Column 'MSSQL)
HashMap ColumnName ColumnName
joinColumns
        s
annotatedRelationship

-- | Top/root-level 'Select'. All descendent/sub-translations are collected to produce a root TSQL.Select.
fromSelectRows :: IR.AnnSelectG 'MSSQL (IR.AnnFieldG 'MSSQL Void) Expression -> FromIr TSQL.Select
fromSelectRows :: AnnSimpleSelectG 'MSSQL Void Expression -> FromIr Select
fromSelectRows AnnSimpleSelectG 'MSSQL Void Expression
annSelectG = do
  From
selectFrom <-
    case SelectFromG 'MSSQL Expression
from of
      IR.FromTable TableName 'MSSQL
qualifiedObject -> TableName -> FromIr From
fromQualifiedTable TableName 'MSSQL
TableName
qualifiedObject
      IR.FromIdentifier FIIdentifier
identifier -> From -> FromIr From
forall (f :: * -> *) a. Applicative f => a -> f a
pure (From -> FromIr From) -> From -> FromIr From
forall a b. (a -> b) -> a -> b
$ Text -> From
FromIdentifier (Text -> From) -> Text -> From
forall a b. (a -> b) -> a -> b
$ FIIdentifier -> Text
IR.unFIIdentifier FIIdentifier
identifier
      IR.FromFunction {} -> NonEmpty Error -> FromIr From
forall e (m :: * -> *) a. MonadValidate e m => e -> m a
refute (NonEmpty Error -> FromIr From) -> NonEmpty Error -> FromIr From
forall a b. (a -> b) -> a -> b
$ Error -> NonEmpty Error
forall (f :: * -> *) a. Applicative f => a -> f a
pure Error
FunctionNotSupported
  Args
    { Maybe (NonEmpty OrderBy)
argsOrderBy :: Args -> Maybe (NonEmpty OrderBy)
argsOrderBy :: Maybe (NonEmpty OrderBy)
argsOrderBy,
      Where
argsWhere :: Args -> Where
argsWhere :: Where
argsWhere,
      [Join]
argsJoins :: Args -> [Join]
argsJoins :: [Join]
argsJoins,
      Top
argsTop :: Args -> Top
argsTop :: Top
argsTop,
      argsDistinct :: Args -> Proxy (Maybe (NonEmpty FieldName))
argsDistinct = Proxy (Maybe (NonEmpty FieldName))
Proxy,
      Maybe Expression
argsOffset :: Args -> Maybe Expression
argsOffset :: Maybe Expression
argsOffset,
      Map TableName EntityAlias
argsExistingJoins :: Args -> Map TableName EntityAlias
argsExistingJoins :: Map TableName EntityAlias
argsExistingJoins
    } <-
    ReaderT EntityAlias FromIr Args -> EntityAlias -> FromIr Args
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT (SelectArgsG 'MSSQL Expression -> ReaderT EntityAlias FromIr Args
fromSelectArgsG SelectArgsG 'MSSQL Expression
args) (From -> EntityAlias
fromAlias From
selectFrom)
  [FieldSource]
fieldSources <-
    ReaderT EntityAlias FromIr [FieldSource]
-> EntityAlias -> FromIr [FieldSource]
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT
      (((FieldName, AnnFieldG 'MSSQL Void Expression)
 -> ReaderT EntityAlias FromIr FieldSource)
-> [(FieldName, AnnFieldG 'MSSQL Void Expression)]
-> ReaderT EntityAlias FromIr [FieldSource]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse (Map TableName EntityAlias
-> (FieldName, AnnFieldG 'MSSQL Void Expression)
-> ReaderT EntityAlias FromIr FieldSource
fromAnnFieldsG Map TableName EntityAlias
argsExistingJoins) [(FieldName, AnnFieldG 'MSSQL Void Expression)]
fields)
      (From -> EntityAlias
fromAlias From
selectFrom)
  Expression
filterExpression <-
    ReaderT EntityAlias FromIr Expression
-> EntityAlias -> FromIr Expression
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT (GBoolExp 'MSSQL (AnnBoolExpFld 'MSSQL Expression)
-> ReaderT EntityAlias FromIr Expression
fromGBoolExp GBoolExp 'MSSQL (AnnBoolExpFld 'MSSQL Expression)
permFilter) (From -> EntityAlias
fromAlias From
selectFrom)
  let selectProjections :: [Projection]
selectProjections = (FieldSource -> Projection) -> [FieldSource] -> [Projection]
forall a b. (a -> b) -> [a] -> [b]
map FieldSource -> Projection
fieldSourceProjections [FieldSource]
fieldSources
  Select -> FromIr Select
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Select -> FromIr Select) -> Select -> FromIr Select
forall a b. (a -> b) -> a -> b
$
    Select
emptySelect
      { $sel:selectOrderBy:Select :: Maybe (NonEmpty OrderBy)
selectOrderBy = Maybe (NonEmpty OrderBy)
argsOrderBy,
        $sel:selectTop:Select :: Top
selectTop = Top
permissionBasedTop Top -> Top -> Top
forall a. Semigroup a => a -> a -> a
<> Top
argsTop,
        [Projection]
selectProjections :: [Projection]
$sel:selectProjections:Select :: [Projection]
selectProjections,
        $sel:selectFrom:Select :: Maybe From
selectFrom = From -> Maybe From
forall a. a -> Maybe a
Just From
selectFrom,
        $sel:selectJoins:Select :: [Join]
selectJoins = [Join]
argsJoins [Join] -> [Join] -> [Join]
forall a. Semigroup a => a -> a -> a
<> (FieldSource -> Maybe Join) -> [FieldSource] -> [Join]
forall (f :: * -> *) a b.
Filterable f =>
(a -> Maybe b) -> f a -> f b
mapMaybe FieldSource -> Maybe Join
fieldSourceJoin [FieldSource]
fieldSources,
        $sel:selectWhere:Select :: Where
selectWhere = Where
argsWhere Where -> Where -> Where
forall a. Semigroup a => a -> a -> a
<> [Expression] -> Where
Where [Expression
filterExpression],
        $sel:selectFor:Select :: For
selectFor =
          ForJson -> For
JsonFor ForJson :: JsonCardinality -> Root -> ForJson
ForJson {$sel:jsonCardinality:ForJson :: JsonCardinality
jsonCardinality = JsonCardinality
JsonArray, $sel:jsonRoot:ForJson :: Root
jsonRoot = Root
NoRoot},
        $sel:selectOffset:Select :: Maybe Expression
selectOffset = Maybe Expression
argsOffset
      }
  where
    IR.AnnSelectG
      { $sel:_asnFields:AnnSelectG :: forall (b :: BackendType) (f :: * -> *) v.
AnnSelectG b f v -> Fields (f v)
_asnFields = [(FieldName, AnnFieldG 'MSSQL Void Expression)]
fields,
        $sel:_asnFrom:AnnSelectG :: forall (b :: BackendType) (f :: * -> *) v.
AnnSelectG b f v -> SelectFromG b v
_asnFrom = SelectFromG 'MSSQL Expression
from,
        $sel:_asnPerm:AnnSelectG :: forall (b :: BackendType) (f :: * -> *) v.
AnnSelectG b f v -> TablePermG b v
_asnPerm = TablePermG 'MSSQL Expression
perm,
        $sel:_asnArgs:AnnSelectG :: forall (b :: BackendType) (f :: * -> *) v.
AnnSelectG b f v -> SelectArgsG b v
_asnArgs = SelectArgsG 'MSSQL Expression
args,
        $sel:_asnNamingConvention:AnnSelectG :: forall (b :: BackendType) (f :: * -> *) v.
AnnSelectG b f v -> Maybe NamingCase
_asnNamingConvention = Maybe NamingCase
_tCase
      } = AnnSimpleSelectG 'MSSQL Void Expression
annSelectG
    IR.TablePerm {$sel:_tpLimit:TablePerm :: forall (b :: BackendType) v. TablePermG b v -> Maybe Int
_tpLimit = Maybe Int
mPermLimit, $sel:_tpFilter:TablePerm :: forall (b :: BackendType) v. TablePermG b v -> AnnBoolExp b v
_tpFilter = GBoolExp 'MSSQL (AnnBoolExpFld 'MSSQL Expression)
permFilter} = TablePermG 'MSSQL Expression
perm
    permissionBasedTop :: Top
permissionBasedTop =
      Top -> (Int -> Top) -> Maybe Int -> Top
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Top
NoTop Int -> Top
Top Maybe Int
mPermLimit

mkNodesSelect :: Args -> Where -> Expression -> Top -> From -> [(Int, (IR.FieldName, [FieldSource]))] -> [(Int, Projection)]
mkNodesSelect :: Args
-> Where
-> Expression
-> Top
-> From
-> [(Int, (FieldName, [FieldSource]))]
-> [(Int, Projection)]
mkNodesSelect Args {[Join]
Maybe (NonEmpty OrderBy)
Maybe Expression
Proxy (Maybe (NonEmpty FieldName))
Map TableName EntityAlias
Top
Where
argsExistingJoins :: Map TableName EntityAlias
argsDistinct :: Proxy (Maybe (NonEmpty FieldName))
argsOffset :: Maybe Expression
argsTop :: Top
argsJoins :: [Join]
argsOrderBy :: Maybe (NonEmpty OrderBy)
argsWhere :: Where
argsExistingJoins :: Args -> Map TableName EntityAlias
argsOffset :: Args -> Maybe Expression
argsDistinct :: Args -> Proxy (Maybe (NonEmpty FieldName))
argsTop :: Args -> Top
argsJoins :: Args -> [Join]
argsWhere :: Args -> Where
argsOrderBy :: Args -> Maybe (NonEmpty OrderBy)
..} Where
foreignKeyConditions Expression
filterExpression Top
permissionBasedTop From
selectFrom [(Int, (FieldName, [FieldSource]))]
nodes =
  [ ( Int
index,
      Aliased Expression -> Projection
ExpressionProjection (Aliased Expression -> Projection)
-> Aliased Expression -> Projection
forall a b. (a -> b) -> a -> b
$
        Aliased :: forall a. a -> Text -> Aliased a
Aliased
          { $sel:aliasedThing:Aliased :: Expression
aliasedThing =
              Select -> Expression
SelectExpression (Select -> Expression) -> Select -> Expression
forall a b. (a -> b) -> a -> b
$
                Select
emptySelect
                  { $sel:selectProjections:Select :: [Projection]
selectProjections = (FieldSource -> Projection) -> [FieldSource] -> [Projection]
forall a b. (a -> b) -> [a] -> [b]
map FieldSource -> Projection
fieldSourceProjections [FieldSource]
fieldSources,
                    $sel:selectTop:Select :: Top
selectTop = Top
permissionBasedTop Top -> Top -> Top
forall a. Semigroup a => a -> a -> a
<> Top
argsTop,
                    $sel:selectFrom:Select :: Maybe From
selectFrom = From -> Maybe From
forall (f :: * -> *) a. Applicative f => a -> f a
pure From
selectFrom,
                    $sel:selectJoins:Select :: [Join]
selectJoins = [Join]
argsJoins [Join] -> [Join] -> [Join]
forall a. Semigroup a => a -> a -> a
<> (FieldSource -> Maybe Join) -> [FieldSource] -> [Join]
forall (f :: * -> *) a b.
Filterable f =>
(a -> Maybe b) -> f a -> f b
mapMaybe FieldSource -> Maybe Join
fieldSourceJoin [FieldSource]
fieldSources,
                    $sel:selectWhere:Select :: Where
selectWhere = Where
argsWhere Where -> Where -> Where
forall a. Semigroup a => a -> a -> a
<> [Expression] -> Where
Where [Expression
filterExpression] Where -> Where -> Where
forall a. Semigroup a => a -> a -> a
<> Where
foreignKeyConditions,
                    $sel:selectFor:Select :: For
selectFor =
                      ForJson -> For
JsonFor ForJson :: JsonCardinality -> Root -> ForJson
ForJson {$sel:jsonCardinality:ForJson :: JsonCardinality
jsonCardinality = JsonCardinality
JsonArray, $sel:jsonRoot:ForJson :: Root
jsonRoot = Root
NoRoot},
                    $sel:selectOrderBy:Select :: Maybe (NonEmpty OrderBy)
selectOrderBy = Maybe (NonEmpty OrderBy)
argsOrderBy,
                    $sel:selectOffset:Select :: Maybe Expression
selectOffset = Maybe Expression
argsOffset
                  },
            $sel:aliasedAlias:Aliased :: Text
aliasedAlias = FieldName -> Text
IR.getFieldNameTxt FieldName
fieldName
          }
    )
    | (Int
index, (FieldName
fieldName, [FieldSource]
fieldSources)) <- [(Int, (FieldName, [FieldSource]))]
nodes
  ]

--
-- The idea here is that LIMIT/OFFSET and aggregates don't mix
-- well. Therefore we have a nested query:
--
-- select sum(*), .. FROM (select * from x offset o limit l) p
--
-- That's why @projections@ appears on the outer, and is a
-- @StarProjection@ for the inner. But the joins, conditions, top,
-- offset are on the inner.
--
mkAggregateSelect :: Args -> Where -> Expression -> From -> [(Int, (IR.FieldName, [Projection]))] -> [(Int, Projection)]
mkAggregateSelect :: Args
-> Where
-> Expression
-> From
-> [(Int, (FieldName, [Projection]))]
-> [(Int, Projection)]
mkAggregateSelect Args {[Join]
Maybe (NonEmpty OrderBy)
Maybe Expression
Proxy (Maybe (NonEmpty FieldName))
Map TableName EntityAlias
Top
Where
argsExistingJoins :: Map TableName EntityAlias
argsDistinct :: Proxy (Maybe (NonEmpty FieldName))
argsOffset :: Maybe Expression
argsTop :: Top
argsJoins :: [Join]
argsOrderBy :: Maybe (NonEmpty OrderBy)
argsWhere :: Where
argsExistingJoins :: Args -> Map TableName EntityAlias
argsOffset :: Args -> Maybe Expression
argsDistinct :: Args -> Proxy (Maybe (NonEmpty FieldName))
argsTop :: Args -> Top
argsJoins :: Args -> [Join]
argsWhere :: Args -> Where
argsOrderBy :: Args -> Maybe (NonEmpty OrderBy)
..} Where
foreignKeyConditions Expression
filterExpression From
selectFrom [(Int, (FieldName, [Projection]))]
aggregates =
  [ ( Int
index,
      Aliased Expression -> Projection
ExpressionProjection (Aliased Expression -> Projection)
-> Aliased Expression -> Projection
forall a b. (a -> b) -> a -> b
$
        Aliased :: forall a. a -> Text -> Aliased a
Aliased
          { $sel:aliasedThing:Aliased :: Expression
aliasedThing =
              JsonCardinality -> Expression -> Expression
safeJsonQueryExpression JsonCardinality
JsonSingleton (Expression -> Expression) -> Expression -> Expression
forall a b. (a -> b) -> a -> b
$
                Select -> Expression
SelectExpression (Select -> Expression) -> Select -> Expression
forall a b. (a -> b) -> a -> b
$
                  Select
emptySelect
                    { $sel:selectProjections:Select :: [Projection]
selectProjections = [Projection]
projections,
                      $sel:selectTop:Select :: Top
selectTop = Top
NoTop,
                      $sel:selectFrom:Select :: Maybe From
selectFrom =
                        From -> Maybe From
forall (f :: * -> *) a. Applicative f => a -> f a
pure (From -> Maybe From) -> From -> Maybe From
forall a b. (a -> b) -> a -> b
$
                          Aliased Select -> From
FromSelect
                            Aliased :: forall a. a -> Text -> Aliased a
Aliased
                              { $sel:aliasedAlias:Aliased :: Text
aliasedAlias = Text
aggSubselectName,
                                $sel:aliasedThing:Aliased :: Select
aliasedThing =
                                  Select
emptySelect
                                    { $sel:selectProjections:Select :: [Projection]
selectProjections = Projection -> [Projection]
forall (f :: * -> *) a. Applicative f => a -> f a
pure Projection
StarProjection,
                                      $sel:selectTop:Select :: Top
selectTop = Top
argsTop,
                                      $sel:selectFrom:Select :: Maybe From
selectFrom = From -> Maybe From
forall (f :: * -> *) a. Applicative f => a -> f a
pure From
selectFrom,
                                      $sel:selectJoins:Select :: [Join]
selectJoins = [Join]
argsJoins,
                                      $sel:selectWhere:Select :: Where
selectWhere = Where
argsWhere Where -> Where -> Where
forall a. Semigroup a => a -> a -> a
<> [Expression] -> Where
Where [Expression
filterExpression] Where -> Where -> Where
forall a. Semigroup a => a -> a -> a
<> Where
foreignKeyConditions,
                                      $sel:selectFor:Select :: For
selectFor = For
NoFor,
                                      $sel:selectOrderBy:Select :: Maybe (NonEmpty OrderBy)
selectOrderBy = Maybe (NonEmpty OrderBy)
forall a. Monoid a => a
mempty,
                                      $sel:selectOffset:Select :: Maybe Expression
selectOffset = Maybe Expression
argsOffset
                                    }
                              },
                      $sel:selectJoins:Select :: [Join]
selectJoins = [Join]
forall a. Monoid a => a
mempty,
                      $sel:selectWhere:Select :: Where
selectWhere = Where
forall a. Monoid a => a
mempty,
                      $sel:selectFor:Select :: For
selectFor =
                        ForJson -> For
JsonFor
                          ForJson :: JsonCardinality -> Root -> ForJson
ForJson
                            { $sel:jsonCardinality:ForJson :: JsonCardinality
jsonCardinality = JsonCardinality
JsonSingleton,
                              $sel:jsonRoot:ForJson :: Root
jsonRoot = Root
NoRoot
                            },
                      $sel:selectOrderBy:Select :: Maybe (NonEmpty OrderBy)
selectOrderBy = Maybe (NonEmpty OrderBy)
forall a. Monoid a => a
mempty,
                      $sel:selectOffset:Select :: Maybe Expression
selectOffset = Maybe Expression
forall a. Maybe a
Nothing
                    },
            $sel:aliasedAlias:Aliased :: Text
aliasedAlias = FieldName -> Text
IR.getFieldNameTxt FieldName
fieldName
          }
    )
    | (Int
index, (FieldName
fieldName, [Projection]
projections)) <- [(Int, (FieldName, [Projection]))]
aggregates
  ]

fromSelectAggregate ::
  Maybe (EntityAlias, HashMap ColumnName ColumnName) ->
  IR.AnnSelectG 'MSSQL (IR.TableAggregateFieldG 'MSSQL Void) Expression ->
  FromIr TSQL.Select
fromSelectAggregate :: Maybe (EntityAlias, HashMap ColumnName ColumnName)
-> AnnAggregateSelectG 'MSSQL Void Expression -> FromIr Select
fromSelectAggregate
  Maybe (EntityAlias, HashMap ColumnName ColumnName)
mparentRelationship
  IR.AnnSelectG
    { $sel:_asnFields:AnnSelectG :: forall (b :: BackendType) (f :: * -> *) v.
AnnSelectG b f v -> Fields (f v)
_asnFields = ([Int]
-> Fields (TableAggregateFieldG 'MSSQL Void Expression)
-> [(Int,
     (FieldName, TableAggregateFieldG 'MSSQL Void Expression))]
forall a b. [a] -> [b] -> [(a, b)]
zip [Int
0 ..] -> [(Int, (FieldName, TableAggregateFieldG 'MSSQL Void Expression))]
fields),
      $sel:_asnFrom:AnnSelectG :: forall (b :: BackendType) (f :: * -> *) v.
AnnSelectG b f v -> SelectFromG b v
_asnFrom = SelectFromG 'MSSQL Expression
from,
      $sel:_asnPerm:AnnSelectG :: forall (b :: BackendType) (f :: * -> *) v.
AnnSelectG b f v -> TablePermG b v
_asnPerm = IR.TablePerm {$sel:_tpLimit:TablePerm :: forall (b :: BackendType) v. TablePermG b v -> Maybe Int
_tpLimit = (Top -> (Int -> Top) -> Maybe Int -> Top
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Top
NoTop Int -> Top
Top -> Top
permissionBasedTop), $sel:_tpFilter:TablePerm :: forall (b :: BackendType) v. TablePermG b v -> AnnBoolExp b v
_tpFilter = GBoolExp 'MSSQL (AnnBoolExpFld 'MSSQL Expression)
permFilter},
      $sel:_asnArgs:AnnSelectG :: forall (b :: BackendType) (f :: * -> *) v.
AnnSelectG b f v -> SelectArgsG b v
_asnArgs = SelectArgsG 'MSSQL Expression
args,
      $sel:_asnNamingConvention:AnnSelectG :: forall (b :: BackendType) (f :: * -> *) v.
AnnSelectG b f v -> Maybe NamingCase
_asnNamingConvention = Maybe NamingCase
_tCase
    } =
    do
      From
selectFrom <- case SelectFromG 'MSSQL Expression
from of
        IR.FromTable TableName 'MSSQL
qualifiedObject -> TableName -> FromIr From
fromQualifiedTable TableName 'MSSQL
TableName
qualifiedObject
        IR.FromIdentifier FIIdentifier
identifier -> From -> FromIr From
forall (f :: * -> *) a. Applicative f => a -> f a
pure (From -> FromIr From) -> From -> FromIr From
forall a b. (a -> b) -> a -> b
$ Text -> From
FromIdentifier (Text -> From) -> Text -> From
forall a b. (a -> b) -> a -> b
$ FIIdentifier -> Text
IR.unFIIdentifier FIIdentifier
identifier
        IR.FromFunction {} -> NonEmpty Error -> FromIr From
forall e (m :: * -> *) a. MonadValidate e m => e -> m a
refute (NonEmpty Error -> FromIr From) -> NonEmpty Error -> FromIr From
forall a b. (a -> b) -> a -> b
$ Error -> NonEmpty Error
forall (f :: * -> *) a. Applicative f => a -> f a
pure Error
FunctionNotSupported
      -- Below: When we're actually a RHS of a query (of CROSS APPLY),
      -- then we'll have a LHS table that we're joining on. So we get the
      -- conditions expressions from the field mappings. The LHS table is
      -- the entityAlias, and the RHS table is selectFrom.
      Where
mforeignKeyConditions <- (Maybe [Expression] -> Where)
-> FromIr (Maybe [Expression]) -> FromIr Where
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ([Expression] -> Where
Where ([Expression] -> Where)
-> (Maybe [Expression] -> [Expression])
-> Maybe [Expression]
-> Where
forall b c a. (b -> c) -> (a -> b) -> a -> c
. [Expression] -> Maybe [Expression] -> [Expression]
forall a. a -> Maybe a -> a
fromMaybe []) (FromIr (Maybe [Expression]) -> FromIr Where)
-> FromIr (Maybe [Expression]) -> FromIr Where
forall a b. (a -> b) -> a -> b
$
        Maybe (EntityAlias, HashMap ColumnName ColumnName)
-> ((EntityAlias, HashMap ColumnName ColumnName)
    -> FromIr [Expression])
-> FromIr (Maybe [Expression])
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
t a -> (a -> f b) -> f (t b)
for Maybe (EntityAlias, HashMap ColumnName ColumnName)
mparentRelationship (((EntityAlias, HashMap ColumnName ColumnName)
  -> FromIr [Expression])
 -> FromIr (Maybe [Expression]))
-> ((EntityAlias, HashMap ColumnName ColumnName)
    -> FromIr [Expression])
-> FromIr (Maybe [Expression])
forall a b. (a -> b) -> a -> b
$
          \(EntityAlias
entityAlias, HashMap ColumnName ColumnName
mapping) ->
            ReaderT EntityAlias FromIr [Expression]
-> EntityAlias -> FromIr [Expression]
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT (From
-> HashMap ColumnName ColumnName
-> ReaderT EntityAlias FromIr [Expression]
fromMapping From
selectFrom HashMap ColumnName ColumnName
mapping) EntityAlias
entityAlias
      Expression
filterExpression <- ReaderT EntityAlias FromIr Expression
-> EntityAlias -> FromIr Expression
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT (GBoolExp 'MSSQL (AnnBoolExpFld 'MSSQL Expression)
-> ReaderT EntityAlias FromIr Expression
fromGBoolExp GBoolExp 'MSSQL (AnnBoolExpFld 'MSSQL Expression)
permFilter) (From -> EntityAlias
fromAlias From
selectFrom)
      args' :: Args
args'@Args {Map TableName EntityAlias
argsExistingJoins :: Map TableName EntityAlias
argsExistingJoins :: Args -> Map TableName EntityAlias
argsExistingJoins} <-
        ReaderT EntityAlias FromIr Args -> EntityAlias -> FromIr Args
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT (SelectArgsG 'MSSQL Expression -> ReaderT EntityAlias FromIr Args
fromSelectArgsG SelectArgsG 'MSSQL Expression
args) (From -> EntityAlias
fromAlias From
selectFrom)
      -- Although aggregates, exps and nodes could be handled in one list,
      -- we need to separately treat the subselect expressions
      [(Int, Projection)]
expss :: [(Int, Projection)] <- (ReaderT EntityAlias FromIr [(Int, Projection)]
 -> EntityAlias -> FromIr [(Int, Projection)])
-> EntityAlias
-> ReaderT EntityAlias FromIr [(Int, Projection)]
-> FromIr [(Int, Projection)]
forall a b c. (a -> b -> c) -> b -> a -> c
flip ReaderT EntityAlias FromIr [(Int, Projection)]
-> EntityAlias -> FromIr [(Int, Projection)]
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT (From -> EntityAlias
fromAlias From
selectFrom) (ReaderT EntityAlias FromIr [(Int, Projection)]
 -> FromIr [(Int, Projection)])
-> ReaderT EntityAlias FromIr [(Int, Projection)]
-> FromIr [(Int, Projection)]
forall a b. (a -> b) -> a -> b
$ [ReaderT EntityAlias FromIr (Int, Projection)]
-> ReaderT EntityAlias FromIr [(Int, Projection)]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence ([ReaderT EntityAlias FromIr (Int, Projection)]
 -> ReaderT EntityAlias FromIr [(Int, Projection)])
-> [ReaderT EntityAlias FromIr (Int, Projection)]
-> ReaderT EntityAlias FromIr [(Int, Projection)]
forall a b. (a -> b) -> a -> b
$ ((Int, (FieldName, TableAggregateFieldG 'MSSQL Void Expression))
 -> Maybe (ReaderT EntityAlias FromIr (Int, Projection)))
-> [(Int,
     (FieldName, TableAggregateFieldG 'MSSQL Void Expression))]
-> [ReaderT EntityAlias FromIr (Int, Projection)]
forall (f :: * -> *) a b.
Filterable f =>
(a -> Maybe b) -> f a -> f b
mapMaybe (Int, (FieldName, TableAggregateFieldG 'MSSQL Void Expression))
-> Maybe (ReaderT EntityAlias FromIr (Int, Projection))
fromTableExpFieldG [(Int, (FieldName, TableAggregateFieldG 'MSSQL Void Expression))]
fields
      [(Int, (FieldName, [FieldSource]))]
nodes :: [(Int, (IR.FieldName, [FieldSource]))] <-
        (ReaderT EntityAlias FromIr [(Int, (FieldName, [FieldSource]))]
 -> EntityAlias -> FromIr [(Int, (FieldName, [FieldSource]))])
-> EntityAlias
-> ReaderT EntityAlias FromIr [(Int, (FieldName, [FieldSource]))]
-> FromIr [(Int, (FieldName, [FieldSource]))]
forall a b c. (a -> b -> c) -> b -> a -> c
flip ReaderT EntityAlias FromIr [(Int, (FieldName, [FieldSource]))]
-> EntityAlias -> FromIr [(Int, (FieldName, [FieldSource]))]
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT (From -> EntityAlias
fromAlias From
selectFrom) (ReaderT EntityAlias FromIr [(Int, (FieldName, [FieldSource]))]
 -> FromIr [(Int, (FieldName, [FieldSource]))])
-> ReaderT EntityAlias FromIr [(Int, (FieldName, [FieldSource]))]
-> FromIr [(Int, (FieldName, [FieldSource]))]
forall a b. (a -> b) -> a -> b
$ [ReaderT EntityAlias FromIr (Int, (FieldName, [FieldSource]))]
-> ReaderT EntityAlias FromIr [(Int, (FieldName, [FieldSource]))]
forall (t :: * -> *) (m :: * -> *) a.
(Traversable t, Monad m) =>
t (m a) -> m (t a)
sequence ([ReaderT EntityAlias FromIr (Int, (FieldName, [FieldSource]))]
 -> ReaderT EntityAlias FromIr [(Int, (FieldName, [FieldSource]))])
-> [ReaderT EntityAlias FromIr (Int, (FieldName, [FieldSource]))]
-> ReaderT EntityAlias FromIr [(Int, (FieldName, [FieldSource]))]
forall a b. (a -> b) -> a -> b
$ ((Int, (FieldName, TableAggregateFieldG 'MSSQL Void Expression))
 -> Maybe
      (ReaderT EntityAlias FromIr (Int, (FieldName, [FieldSource]))))
-> [(Int,
     (FieldName, TableAggregateFieldG 'MSSQL Void Expression))]
-> [ReaderT EntityAlias FromIr (Int, (FieldName, [FieldSource]))]
forall (f :: * -> *) a b.
Filterable f =>
(a -> Maybe b) -> f a -> f b
mapMaybe (Map TableName EntityAlias
-> (Int, (FieldName, TableAggregateFieldG 'MSSQL Void Expression))
-> Maybe
     (ReaderT EntityAlias FromIr (Int, (FieldName, [FieldSource])))
fromTableNodesFieldG Map TableName EntityAlias
argsExistingJoins) [(Int, (FieldName, TableAggregateFieldG 'MSSQL Void Expression))]
fields
      let [(Int, (FieldName, [Projection]))]
aggregates :: [(Int, (IR.FieldName, [Projection]))] = ((Int, (FieldName, TableAggregateFieldG 'MSSQL Void Expression))
 -> Maybe (Int, (FieldName, [Projection])))
-> [(Int,
     (FieldName, TableAggregateFieldG 'MSSQL Void Expression))]
-> [(Int, (FieldName, [Projection]))]
forall (f :: * -> *) a b.
Filterable f =>
(a -> Maybe b) -> f a -> f b
mapMaybe (Int, (FieldName, TableAggregateFieldG 'MSSQL Void Expression))
-> Maybe (Int, (FieldName, [Projection]))
fromTableAggFieldG [(Int, (FieldName, TableAggregateFieldG 'MSSQL Void Expression))]
fields
      Select -> FromIr Select
forall (f :: * -> *) a. Applicative f => a -> f a
pure
        Select
emptySelect
          { $sel:selectProjections:Select :: [Projection]
selectProjections =
              ((Int, Projection) -> Projection)
-> [(Int, Projection)] -> [Projection]
forall a b. (a -> b) -> [a] -> [b]
map (Int, Projection) -> Projection
forall a b. (a, b) -> b
snd ([(Int, Projection)] -> [Projection])
-> [(Int, Projection)] -> [Projection]
forall a b. (a -> b) -> a -> b
$
                ((Int, Projection) -> (Int, Projection) -> Ordering)
-> [(Int, Projection)] -> [(Int, Projection)]
forall a. (a -> a -> Ordering) -> [a] -> [a]
sortBy (((Int, Projection) -> Int)
-> (Int, Projection) -> (Int, Projection) -> Ordering
forall a b. Ord a => (b -> a) -> b -> b -> Ordering
comparing (Int, Projection) -> Int
forall a b. (a, b) -> a
fst) ([(Int, Projection)] -> [(Int, Projection)])
-> [(Int, Projection)] -> [(Int, Projection)]
forall a b. (a -> b) -> a -> b
$
                  [(Int, Projection)]
expss
                    [(Int, Projection)] -> [(Int, Projection)] -> [(Int, Projection)]
forall a. Semigroup a => a -> a -> a
<> Args
-> Where
-> Expression
-> Top
-> From
-> [(Int, (FieldName, [FieldSource]))]
-> [(Int, Projection)]
mkNodesSelect Args
args' Where
mforeignKeyConditions Expression
filterExpression Top
permissionBasedTop From
selectFrom [(Int, (FieldName, [FieldSource]))]
nodes
                    [(Int, Projection)] -> [(Int, Projection)] -> [(Int, Projection)]
forall a. Semigroup a => a -> a -> a
<> Args
-> Where
-> Expression
-> From
-> [(Int, (FieldName, [Projection]))]
-> [(Int, Projection)]
mkAggregateSelect Args
args' Where
mforeignKeyConditions Expression
filterExpression From
selectFrom [(Int, (FieldName, [Projection]))]
aggregates,
            $sel:selectTop:Select :: Top
selectTop = Top
NoTop,
            $sel:selectFrom:Select :: Maybe From
selectFrom =
              From -> Maybe From
forall (f :: * -> *) a. Applicative f => a -> f a
pure (From -> Maybe From) -> From -> Maybe From
forall a b. (a -> b) -> a -> b
$
                Aliased OpenJson -> From
FromOpenJson (Aliased OpenJson -> From) -> Aliased OpenJson -> From
forall a b. (a -> b) -> a -> b
$
                  Aliased :: forall a. a -> Text -> Aliased a
Aliased
                    { $sel:aliasedThing:Aliased :: OpenJson
aliasedThing =
                        OpenJson :: Expression -> Maybe (NonEmpty JsonFieldSpec) -> OpenJson
OpenJson
                          { $sel:openJsonExpression:OpenJson :: Expression
openJsonExpression = Value -> Expression
ValueExpression (Value -> Expression) -> Value -> Expression
forall a b. (a -> b) -> a -> b
$ Text -> Value
ODBC.TextValue Text
"[0]",
                            $sel:openJsonWith:OpenJson :: Maybe (NonEmpty JsonFieldSpec)
openJsonWith = Maybe (NonEmpty JsonFieldSpec)
forall a. Maybe a
Nothing
                          },
                      $sel:aliasedAlias:Aliased :: Text
aliasedAlias = Text
existsFieldName
                    },
            $sel:selectJoins:Select :: [Join]
selectJoins = [Join]
forall a. Monoid a => a
mempty, -- JOINs and WHEREs are only relevant in subselects
            $sel:selectWhere:Select :: Where
selectWhere = Where
forall a. Monoid a => a
mempty,
            $sel:selectFor:Select :: For
selectFor = ForJson -> For
JsonFor ForJson :: JsonCardinality -> Root -> ForJson
ForJson {$sel:jsonCardinality:ForJson :: JsonCardinality
jsonCardinality = JsonCardinality
JsonSingleton, $sel:jsonRoot:ForJson :: Root
jsonRoot = Root
NoRoot},
            $sel:selectOrderBy:Select :: Maybe (NonEmpty OrderBy)
selectOrderBy = Maybe (NonEmpty OrderBy)
forall a. Maybe a
Nothing,
            $sel:selectOffset:Select :: Maybe Expression
selectOffset = Maybe Expression
forall a. Maybe a
Nothing
          }

--------------------------------------------------------------------------------
-- GraphQL Args

data Args = Args
  { Args -> Where
argsWhere :: Where,
    Args -> Maybe (NonEmpty OrderBy)
argsOrderBy :: Maybe (NonEmpty OrderBy),
    Args -> [Join]
argsJoins :: [Join],
    Args -> Top
argsTop :: Top,
    Args -> Maybe Expression
argsOffset :: Maybe Expression,
    Args -> Proxy (Maybe (NonEmpty FieldName))
argsDistinct :: Proxy (Maybe (NonEmpty FieldName)),
    Args -> Map TableName EntityAlias
argsExistingJoins :: Map TableName EntityAlias
  }
  deriving (Int -> Args -> ShowS
[Args] -> ShowS
Args -> String
(Int -> Args -> ShowS)
-> (Args -> String) -> ([Args] -> ShowS) -> Show Args
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [Args] -> ShowS
$cshowList :: [Args] -> ShowS
show :: Args -> String
$cshow :: Args -> String
showsPrec :: Int -> Args -> ShowS
$cshowsPrec :: Int -> Args -> ShowS
Show)

fromSelectArgsG :: IR.SelectArgsG 'MSSQL Expression -> ReaderT EntityAlias FromIr Args
fromSelectArgsG :: SelectArgsG 'MSSQL Expression -> ReaderT EntityAlias FromIr Args
fromSelectArgsG SelectArgsG 'MSSQL Expression
selectArgsG = do
  let argsOffset :: Maybe Expression
argsOffset = Value -> Expression
ValueExpression (Value -> Expression) -> (Int64 -> Value) -> Int64 -> Expression
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Value
ODBC.IntValue (Int -> Value) -> (Int64 -> Int) -> Int64 -> Value
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int64 -> Int
forall a b. (Integral a, Num b) => a -> b
fromIntegral (Int64 -> Expression) -> Maybe Int64 -> Maybe Expression
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Maybe Int64
moffset
  Where
argsWhere <-
    ReaderT EntityAlias FromIr Where
-> (GBoolExp 'MSSQL (AnnBoolExpFld 'MSSQL Expression)
    -> ReaderT EntityAlias FromIr Where)
-> Maybe (GBoolExp 'MSSQL (AnnBoolExpFld 'MSSQL Expression))
-> ReaderT EntityAlias FromIr Where
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (Where -> ReaderT EntityAlias FromIr Where
forall (f :: * -> *) a. Applicative f => a -> f a
pure Where
forall a. Monoid a => a
mempty) ((Expression -> Where)
-> ReaderT EntityAlias FromIr Expression
-> ReaderT EntityAlias FromIr Where
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap ([Expression] -> Where
Where ([Expression] -> Where)
-> (Expression -> [Expression]) -> Expression -> Where
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Expression -> [Expression]
forall (f :: * -> *) a. Applicative f => a -> f a
pure) (ReaderT EntityAlias FromIr Expression
 -> ReaderT EntityAlias FromIr Where)
-> (GBoolExp 'MSSQL (AnnBoolExpFld 'MSSQL Expression)
    -> ReaderT EntityAlias FromIr Expression)
-> GBoolExp 'MSSQL (AnnBoolExpFld 'MSSQL Expression)
-> ReaderT EntityAlias FromIr Where
forall b c a. (b -> c) -> (a -> b) -> a -> c
. GBoolExp 'MSSQL (AnnBoolExpFld 'MSSQL Expression)
-> ReaderT EntityAlias FromIr Expression
fromGBoolExp) Maybe (GBoolExp 'MSSQL (AnnBoolExpFld 'MSSQL Expression))
mannBoolExp
  Top
argsTop <-
    ReaderT EntityAlias FromIr Top
-> (Int -> ReaderT EntityAlias FromIr Top)
-> Maybe Int
-> ReaderT EntityAlias FromIr Top
forall b a. b -> (a -> b) -> Maybe a -> b
maybe (Top -> ReaderT EntityAlias FromIr Top
forall (f :: * -> *) a. Applicative f => a -> f a
pure Top
forall a. Monoid a => a
mempty) (Top -> ReaderT EntityAlias FromIr Top
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Top -> ReaderT EntityAlias FromIr Top)
-> (Int -> Top) -> Int -> ReaderT EntityAlias FromIr Top
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Int -> Top
Top) Maybe Int
mlimit
  -- Not supported presently, per Vamshi:
  --
  -- > It is hardly used and we don't have to go to great lengths to support it.
  --
  -- But placeholdering the code so that when it's ready to be used,
  -- you can just drop the Proxy wrapper.
  let argsDistinct :: Proxy t
argsDistinct = Proxy t
forall k (t :: k). Proxy t
Proxy
  ([OrderBy]
argsOrderBy, Seq UnfurledJoin
joins) <-
    WriterT (Seq UnfurledJoin) (ReaderT EntityAlias FromIr) [OrderBy]
-> ReaderT EntityAlias FromIr ([OrderBy], Seq UnfurledJoin)
forall w (m :: * -> *) a. WriterT w m a -> m (a, w)
runWriterT ((AnnotatedOrderByItemG 'MSSQL Expression
 -> WriterT (Seq UnfurledJoin) (ReaderT EntityAlias FromIr) OrderBy)
-> [AnnotatedOrderByItemG 'MSSQL Expression]
-> WriterT
     (Seq UnfurledJoin) (ReaderT EntityAlias FromIr) [OrderBy]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse AnnotatedOrderByItemG 'MSSQL Expression
-> WriterT (Seq UnfurledJoin) (ReaderT EntityAlias FromIr) OrderBy
fromAnnotatedOrderByItemG ([AnnotatedOrderByItemG 'MSSQL Expression]
-> (NonEmpty (AnnotatedOrderByItemG 'MSSQL Expression)
    -> [AnnotatedOrderByItemG 'MSSQL Expression])
-> Maybe (NonEmpty (AnnotatedOrderByItemG 'MSSQL Expression))
-> [AnnotatedOrderByItemG 'MSSQL Expression]
forall b a. b -> (a -> b) -> Maybe a -> b
maybe [] NonEmpty (AnnotatedOrderByItemG 'MSSQL Expression)
-> [AnnotatedOrderByItemG 'MSSQL Expression]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList Maybe (NonEmpty (AnnotatedOrderByItemG 'MSSQL Expression))
orders))
  -- Any object-relation joins that we generated, we record their
  -- generated names into a mapping.
  let argsExistingJoins :: Map TableName EntityAlias
argsExistingJoins =
        [(TableName, EntityAlias)] -> Map TableName EntityAlias
forall k a. Ord k => [(k, a)] -> Map k a
M.fromList ((UnfurledJoin -> Maybe (TableName, EntityAlias))
-> [UnfurledJoin] -> [(TableName, EntityAlias)]
forall (f :: * -> *) a b.
Filterable f =>
(a -> Maybe b) -> f a -> f b
mapMaybe UnfurledJoin -> Maybe (TableName, EntityAlias)
unfurledObjectTableAlias (Seq UnfurledJoin -> [UnfurledJoin]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList Seq UnfurledJoin
joins))
  Args -> ReaderT EntityAlias FromIr Args
forall (f :: * -> *) a. Applicative f => a -> f a
pure
    Args :: Where
-> Maybe (NonEmpty OrderBy)
-> [Join]
-> Top
-> Maybe Expression
-> Proxy (Maybe (NonEmpty FieldName))
-> Map TableName EntityAlias
-> Args
Args
      { argsJoins :: [Join]
argsJoins = Seq Join -> [Join]
forall (t :: * -> *) a. Foldable t => t a -> [a]
toList ((UnfurledJoin -> Join) -> Seq UnfurledJoin -> Seq Join
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap UnfurledJoin -> Join
unfurledJoin Seq UnfurledJoin
joins),
        argsOrderBy :: Maybe (NonEmpty OrderBy)
argsOrderBy = [OrderBy] -> Maybe (NonEmpty OrderBy)
forall a. [a] -> Maybe (NonEmpty a)
nonEmpty [OrderBy]
argsOrderBy,
        Maybe Expression
Proxy (Maybe (NonEmpty FieldName))
Map TableName EntityAlias
Top
Where
forall t. Proxy t
argsExistingJoins :: Map TableName EntityAlias
argsDistinct :: forall t. Proxy t
argsTop :: Top
argsWhere :: Where
argsOffset :: Maybe Expression
argsExistingJoins :: Map TableName EntityAlias
argsOffset :: Maybe Expression
argsDistinct :: Proxy (Maybe (NonEmpty FieldName))
argsTop :: Top
argsWhere :: Where
..
      }
  where
    IR.SelectArgs
      { $sel:_saWhere:SelectArgs :: forall (b :: BackendType) v.
SelectArgsG b v -> Maybe (AnnBoolExp b v)
_saWhere = Maybe (GBoolExp 'MSSQL (AnnBoolExpFld 'MSSQL Expression))
mannBoolExp,
        $sel:_saLimit:SelectArgs :: forall (b :: BackendType) v. SelectArgsG b v -> Maybe Int
_saLimit = Maybe Int
mlimit,
        $sel:_saOffset:SelectArgs :: forall (b :: BackendType) v. SelectArgsG b v -> Maybe Int64
_saOffset = Maybe Int64
moffset,
        $sel:_saOrderBy:SelectArgs :: forall (b :: BackendType) v.
SelectArgsG b v -> Maybe (NonEmpty (AnnotatedOrderByItemG b v))
_saOrderBy = Maybe (NonEmpty (AnnotatedOrderByItemG 'MSSQL Expression))
orders
      } = SelectArgsG 'MSSQL Expression
selectArgsG

--------------------------------------------------------------------------------
-- Conversion functions
fromQualifiedTable :: TableName -> FromIr From
fromQualifiedTable :: TableName -> FromIr From
fromQualifiedTable schemadTableName :: TableName
schemadTableName@(TableName {Text
$sel:tableName:TableName :: TableName -> Text
tableName :: Text
tableName}) = do
  Text
alias <- NameTemplate -> FromIr Text
generateAlias (Text -> NameTemplate
TableTemplate Text
tableName)
  From -> FromIr From
forall (f :: * -> *) a. Applicative f => a -> f a
pure
    ( Aliased TableName -> From
FromQualifiedTable
        ( Aliased :: forall a. a -> Text -> Aliased a
Aliased
            { $sel:aliasedThing:Aliased :: TableName
aliasedThing = TableName
schemadTableName,
              $sel:aliasedAlias:Aliased :: Text
aliasedAlias = Text
alias
            }
        )
    )

--------------------------------------------------------------------------------
-- Sources of projected fields
--
-- Because in the IR, a field projected can be a foreign object, we
-- have to both generate a projection AND on the side generate a join.
--
-- So a @FieldSource@ couples the idea of the projected thing and the
-- source of it (via 'Aliased').

data FieldSource
  = ExpressionFieldSource (Aliased Expression)
  | JoinFieldSource JsonCardinality (Aliased Join)
  deriving (FieldSource -> FieldSource -> Bool
(FieldSource -> FieldSource -> Bool)
-> (FieldSource -> FieldSource -> Bool) -> Eq FieldSource
forall a. (a -> a -> Bool) -> (a -> a -> Bool) -> Eq a
/= :: FieldSource -> FieldSource -> Bool
$c/= :: FieldSource -> FieldSource -> Bool
== :: FieldSource -> FieldSource -> Bool
$c== :: FieldSource -> FieldSource -> Bool
Eq, Int -> FieldSource -> ShowS
[FieldSource] -> ShowS
FieldSource -> String
(Int -> FieldSource -> ShowS)
-> (FieldSource -> String)
-> ([FieldSource] -> ShowS)
-> Show FieldSource
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [FieldSource] -> ShowS
$cshowList :: [FieldSource] -> ShowS
show :: FieldSource -> String
$cshow :: FieldSource -> String
showsPrec :: Int -> FieldSource -> ShowS
$cshowsPrec :: Int -> FieldSource -> ShowS
Show)

-- | Get FieldSource from a TAFExp type table aggregate field
fromTableExpFieldG :: -- TODO: Convert function to be similar to Nodes function
  (Int, (IR.FieldName, IR.TableAggregateFieldG 'MSSQL Void Expression)) ->
  Maybe (ReaderT EntityAlias FromIr (Int, Projection))
fromTableExpFieldG :: (Int, (FieldName, TableAggregateFieldG 'MSSQL Void Expression))
-> Maybe (ReaderT EntityAlias FromIr (Int, Projection))
fromTableExpFieldG = \case
  (Int
index, (IR.FieldName Text
name, IR.TAFExp Text
text)) ->
    ReaderT EntityAlias FromIr (Int, Projection)
-> Maybe (ReaderT EntityAlias FromIr (Int, Projection))
forall a. a -> Maybe a
Just (ReaderT EntityAlias FromIr (Int, Projection)
 -> Maybe (ReaderT EntityAlias FromIr (Int, Projection)))
-> ReaderT EntityAlias FromIr (Int, Projection)
-> Maybe (ReaderT EntityAlias FromIr (Int, Projection))
forall a b. (a -> b) -> a -> b
$
      (Int, Projection) -> ReaderT EntityAlias FromIr (Int, Projection)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ((Int, Projection) -> ReaderT EntityAlias FromIr (Int, Projection))
-> (Int, Projection)
-> ReaderT EntityAlias FromIr (Int, Projection)
forall a b. (a -> b) -> a -> b
$
        ( Int
index,
          FieldSource -> Projection
fieldSourceProjections (FieldSource -> Projection) -> FieldSource -> Projection
forall a b. (a -> b) -> a -> b
$
            Aliased Expression -> FieldSource
ExpressionFieldSource
              Aliased :: forall a. a -> Text -> Aliased a
Aliased
                { $sel:aliasedThing:Aliased :: Expression
aliasedThing = Value -> Expression
TSQL.ValueExpression (Text -> Value
ODBC.TextValue Text
text),
                  $sel:aliasedAlias:Aliased :: Text
aliasedAlias = Text
name
                }
        )
  (Int, (FieldName, TableAggregateFieldG 'MSSQL Void Expression))
_ -> Maybe (ReaderT EntityAlias FromIr (Int, Projection))
forall a. Maybe a
Nothing

fromTableAggFieldG ::
  (Int, (IR.FieldName, IR.TableAggregateFieldG 'MSSQL Void Expression)) ->
  Maybe (Int, (IR.FieldName, [Projection]))
fromTableAggFieldG :: (Int, (FieldName, TableAggregateFieldG 'MSSQL Void Expression))
-> Maybe (Int, (FieldName, [Projection]))
fromTableAggFieldG = \case
  (Int
index, (FieldName
fieldName, IR.TAFAgg ([(FieldName, AggregateField 'MSSQL)]
aggregateFields :: [(IR.FieldName, IR.AggregateField 'MSSQL)]))) ->
    (Int, (FieldName, [Projection]))
-> Maybe (Int, (FieldName, [Projection]))
forall a. a -> Maybe a
Just ((Int, (FieldName, [Projection]))
 -> Maybe (Int, (FieldName, [Projection])))
-> (Int, (FieldName, [Projection]))
-> Maybe (Int, (FieldName, [Projection]))
forall a b. (a -> b) -> a -> b
$
      let aggregates :: [Projection]
aggregates =
            [(FieldName, AggregateField 'MSSQL)]
aggregateFields [(FieldName, AggregateField 'MSSQL)]
-> ((FieldName, AggregateField 'MSSQL) -> Projection)
-> [Projection]
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> \(FieldName
fieldName', AggregateField 'MSSQL
aggregateField) ->
              Text -> AggregateField 'MSSQL -> Projection
fromAggregateField (FieldName -> Text
IR.getFieldNameTxt FieldName
fieldName') AggregateField 'MSSQL
aggregateField
       in (Int
index, (FieldName
fieldName, [Projection]
aggregates))
  (Int, (FieldName, TableAggregateFieldG 'MSSQL Void Expression))
_ -> Maybe (Int, (FieldName, [Projection]))
forall a. Maybe a
Nothing

fromTableNodesFieldG ::
  Map TableName EntityAlias ->
  (Int, (IR.FieldName, IR.TableAggregateFieldG 'MSSQL Void Expression)) ->
  Maybe (ReaderT EntityAlias FromIr (Int, (IR.FieldName, [FieldSource])))
fromTableNodesFieldG :: Map TableName EntityAlias
-> (Int, (FieldName, TableAggregateFieldG 'MSSQL Void Expression))
-> Maybe
     (ReaderT EntityAlias FromIr (Int, (FieldName, [FieldSource])))
fromTableNodesFieldG Map TableName EntityAlias
argsExistingJoins = \case
  (Int
index, (FieldName
fieldName, IR.TAFNodes () ([(FieldName, AnnFieldG 'MSSQL Void Expression)]
annFieldsG :: [(IR.FieldName, IR.AnnFieldG 'MSSQL Void Expression)]))) -> ReaderT EntityAlias FromIr (Int, (FieldName, [FieldSource]))
-> Maybe
     (ReaderT EntityAlias FromIr (Int, (FieldName, [FieldSource])))
forall a. a -> Maybe a
Just do
    [FieldSource]
fieldSources' <- Map TableName EntityAlias
-> (FieldName, AnnFieldG 'MSSQL Void Expression)
-> ReaderT EntityAlias FromIr FieldSource
fromAnnFieldsG Map TableName EntityAlias
argsExistingJoins ((FieldName, AnnFieldG 'MSSQL Void Expression)
 -> ReaderT EntityAlias FromIr FieldSource)
-> [(FieldName, AnnFieldG 'MSSQL Void Expression)]
-> ReaderT EntityAlias FromIr [FieldSource]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
`traverse` [(FieldName, AnnFieldG 'MSSQL Void Expression)]
annFieldsG
    (Int, (FieldName, [FieldSource]))
-> ReaderT EntityAlias FromIr (Int, (FieldName, [FieldSource]))
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Int
index, (FieldName
fieldName, [FieldSource]
fieldSources'))
  (Int, (FieldName, TableAggregateFieldG 'MSSQL Void Expression))
_ -> Maybe
  (ReaderT EntityAlias FromIr (Int, (FieldName, [FieldSource])))
forall a. Maybe a
Nothing

fromAggregateField :: Text -> IR.AggregateField 'MSSQL -> Projection
fromAggregateField :: Text -> AggregateField 'MSSQL -> Projection
fromAggregateField Text
alias AggregateField 'MSSQL
aggregateField =
  case AggregateField 'MSSQL
aggregateField of
    IR.AFExp Text
text -> Aliased Aggregate -> Projection
AggregateProjection (Aliased Aggregate -> Projection)
-> Aliased Aggregate -> Projection
forall a b. (a -> b) -> a -> b
$ Aggregate -> Text -> Aliased Aggregate
forall a. a -> Text -> Aliased a
Aliased (Text -> Aggregate
TextAggregate Text
text) Text
alias
    IR.AFCount CountType 'MSSQL
countType -> Aliased Aggregate -> Projection
AggregateProjection (Aliased Aggregate -> Projection)
-> (Countable FieldName -> Aliased Aggregate)
-> Countable FieldName
-> Projection
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Aggregate -> Text -> Aliased Aggregate)
-> Text -> Aggregate -> Aliased Aggregate
forall a b c. (a -> b -> c) -> b -> a -> c
flip Aggregate -> Text -> Aliased Aggregate
forall a. a -> Text -> Aliased a
Aliased Text
alias (Aggregate -> Aliased Aggregate)
-> (Countable FieldName -> Aggregate)
-> Countable FieldName
-> Aliased Aggregate
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Countable FieldName -> Aggregate
CountAggregate (Countable FieldName -> Projection)
-> Countable FieldName -> Projection
forall a b. (a -> b) -> a -> b
$ case CountType 'MSSQL
countType of
      CountType 'MSSQL
StarCountable -> Countable FieldName
forall name. Countable name
StarCountable
      NonNullFieldCountable name -> FieldName -> Countable FieldName
forall name. name -> Countable name
NonNullFieldCountable (FieldName -> Countable FieldName)
-> FieldName -> Countable FieldName
forall a b. (a -> b) -> a -> b
$ ColumnName -> FieldName
columnFieldAggEntity ColumnName
name
      DistinctCountable name -> FieldName -> Countable FieldName
forall name. name -> Countable name
DistinctCountable (FieldName -> Countable FieldName)
-> FieldName -> Countable FieldName
forall a b. (a -> b) -> a -> b
$ ColumnName -> FieldName
columnFieldAggEntity ColumnName
name
    IR.AFOp IR.AggregateOp {$sel:_aoOp:AggregateOp :: forall (b :: BackendType). AggregateOp b -> Text
_aoOp = Text
op, $sel:_aoFields:AggregateOp :: forall (b :: BackendType). AggregateOp b -> ColumnFields b
_aoFields = ColumnFields 'MSSQL
fields} ->
      let [Projection]
projections :: [Projection] =
            ColumnFields 'MSSQL
fields ColumnFields 'MSSQL
-> ((FieldName, ColFld 'MSSQL) -> Projection) -> [Projection]
forall (f :: * -> *) a b. Functor f => f a -> (a -> b) -> f b
<&> \(FieldName
fieldName, ColFld 'MSSQL
columnField) ->
              case ColFld 'MSSQL
columnField of
                IR.CFCol Column 'MSSQL
column ColumnType 'MSSQL
_columnType ->
                  let fname :: FieldName
fname = ColumnName -> FieldName
columnFieldAggEntity Column 'MSSQL
ColumnName
column
                   in Aliased Aggregate -> Projection
AggregateProjection (Aliased Aggregate -> Projection)
-> Aliased Aggregate -> Projection
forall a b. (a -> b) -> a -> b
$ Aggregate -> Text -> Aliased Aggregate
forall a. a -> Text -> Aliased a
Aliased (Text -> [Expression] -> Aggregate
OpAggregate Text
op [FieldName -> Expression
ColumnExpression FieldName
fname]) (FieldName -> Text
IR.getFieldNameTxt FieldName
fieldName)
                IR.CFExp Text
text ->
                  Aliased Expression -> Projection
ExpressionProjection (Aliased Expression -> Projection)
-> Aliased Expression -> Projection
forall a b. (a -> b) -> a -> b
$ Expression -> Text -> Aliased Expression
forall a. a -> Text -> Aliased a
Aliased (Value -> Expression
ValueExpression (Text -> Value
ODBC.TextValue Text
text)) (FieldName -> Text
IR.getFieldNameTxt FieldName
fieldName)
       in Aliased Expression -> Projection
ExpressionProjection (Aliased Expression -> Projection)
-> Aliased Expression -> Projection
forall a b. (a -> b) -> a -> b
$
            (Expression -> Text -> Aliased Expression)
-> Text -> Expression -> Aliased Expression
forall a b c. (a -> b -> c) -> b -> a -> c
flip Expression -> Text -> Aliased Expression
forall a. a -> Text -> Aliased a
Aliased Text
alias (Expression -> Aliased Expression)
-> Expression -> Aliased Expression
forall a b. (a -> b) -> a -> b
$
              JsonCardinality -> Expression -> Expression
safeJsonQueryExpression JsonCardinality
JsonSingleton (Expression -> Expression) -> Expression -> Expression
forall a b. (a -> b) -> a -> b
$
                Select -> Expression
SelectExpression (Select -> Expression) -> Select -> Expression
forall a b. (a -> b) -> a -> b
$
                  Select
emptySelect
                    { $sel:selectProjections:Select :: [Projection]
selectProjections = [Projection]
projections,
                      $sel:selectFor:Select :: For
selectFor = ForJson -> For
JsonFor (ForJson -> For) -> ForJson -> For
forall a b. (a -> b) -> a -> b
$ JsonCardinality -> Root -> ForJson
ForJson JsonCardinality
JsonSingleton Root
NoRoot
                    }
  where
    columnFieldAggEntity :: ColumnName -> FieldName
columnFieldAggEntity ColumnName
col = ColumnName -> EntityAlias -> FieldName
columnNameToFieldName ColumnName
col (EntityAlias -> FieldName) -> EntityAlias -> FieldName
forall a b. (a -> b) -> a -> b
$ Text -> EntityAlias
EntityAlias Text
aggSubselectName

-- | The main sources of fields, either constants, fields or via joins.
fromAnnFieldsG ::
  Map TableName EntityAlias ->
  (IR.FieldName, IR.AnnFieldG 'MSSQL Void Expression) ->
  ReaderT EntityAlias FromIr FieldSource
fromAnnFieldsG :: Map TableName EntityAlias
-> (FieldName, AnnFieldG 'MSSQL Void Expression)
-> ReaderT EntityAlias FromIr FieldSource
fromAnnFieldsG Map TableName EntityAlias
existingJoins (IR.FieldName Text
name, AnnFieldG 'MSSQL Void Expression
field) =
  case AnnFieldG 'MSSQL Void Expression
field of
    IR.AFColumn AnnColumnField 'MSSQL Expression
annColumnField -> do
      Expression
expression <- AnnColumnField 'MSSQL Expression
-> ReaderT EntityAlias FromIr Expression
fromAnnColumnField AnnColumnField 'MSSQL Expression
annColumnField
      FieldSource -> ReaderT EntityAlias FromIr FieldSource
forall (f :: * -> *) a. Applicative f => a -> f a
pure
        ( Aliased Expression -> FieldSource
ExpressionFieldSource
            Aliased :: forall a. a -> Text -> Aliased a
Aliased {$sel:aliasedThing:Aliased :: Expression
aliasedThing = Expression
expression, $sel:aliasedAlias:Aliased :: Text
aliasedAlias = Text
name}
        )
    IR.AFExpression Text
text ->
      FieldSource -> ReaderT EntityAlias FromIr FieldSource
forall (f :: * -> *) a. Applicative f => a -> f a
pure
        ( Aliased Expression -> FieldSource
ExpressionFieldSource
            Aliased :: forall a. a -> Text -> Aliased a
Aliased
              { $sel:aliasedThing:Aliased :: Expression
aliasedThing = Value -> Expression
TSQL.ValueExpression (Text -> Value
ODBC.TextValue Text
text),
                $sel:aliasedAlias:Aliased :: Text
aliasedAlias = Text
name
              }
        )
    IR.AFObjectRelation ObjectRelationSelectG 'MSSQL Void Expression
objectRelationSelectG ->
      (Join -> FieldSource)
-> ReaderT EntityAlias FromIr Join
-> ReaderT EntityAlias FromIr FieldSource
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap
        ( \Join
aliasedThing ->
            JsonCardinality -> Aliased Join -> FieldSource
JoinFieldSource JsonCardinality
JsonSingleton (Aliased :: forall a. a -> Text -> Aliased a
Aliased {Join
aliasedThing :: Join
$sel:aliasedThing:Aliased :: Join
aliasedThing, $sel:aliasedAlias:Aliased :: Text
aliasedAlias = Text
name})
        )
        (Map TableName EntityAlias
-> ObjectRelationSelectG 'MSSQL Void Expression
-> ReaderT EntityAlias FromIr Join
fromObjectRelationSelectG Map TableName EntityAlias
existingJoins ObjectRelationSelectG 'MSSQL Void Expression
objectRelationSelectG)
    IR.AFArrayRelation ArraySelectG 'MSSQL Void Expression
arraySelectG ->
      (Join -> FieldSource)
-> ReaderT EntityAlias FromIr Join
-> ReaderT EntityAlias FromIr FieldSource
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap
        ( \Join
aliasedThing ->
            JsonCardinality -> Aliased Join -> FieldSource
JoinFieldSource JsonCardinality
JsonArray (Aliased :: forall a. a -> Text -> Aliased a
Aliased {Join
aliasedThing :: Join
$sel:aliasedThing:Aliased :: Join
aliasedThing, $sel:aliasedAlias:Aliased :: Text
aliasedAlias = Text
name})
        )
        (ArraySelectG 'MSSQL Void Expression
-> ReaderT EntityAlias FromIr Join
fromArraySelectG ArraySelectG 'MSSQL Void Expression
arraySelectG)

-- | Here is where we project a field as a column expression. If
-- number stringification is on, then we wrap it in a
-- 'ToStringExpression' so that it's casted when being projected.
fromAnnColumnField ::
  IR.AnnColumnField 'MSSQL Expression ->
  ReaderT EntityAlias FromIr Expression
fromAnnColumnField :: AnnColumnField 'MSSQL Expression
-> ReaderT EntityAlias FromIr Expression
fromAnnColumnField AnnColumnField 'MSSQL Expression
annColumnField = do
  FieldName
fieldName <- ColumnName -> ReaderT EntityAlias FromIr FieldName
fromColumn Column 'MSSQL
ColumnName
column
  -- TODO: Handle stringifying large numbers
  {-(IR.isScalarColumnWhere isBigNum typ && stringifyNumbers == IR.StringifyNumbers)-}

  -- for geometry and geography values, the automatic json encoding on sql
  -- server would fail. So we need to convert it to a format the json encoding
  -- handles. Ideally we want this representation to be GeoJSON but sql server
  -- doesn't have any functions to convert to GeoJSON format. So we return it in
  -- WKT format
  if ColumnType 'MSSQL
typ ColumnType 'MSSQL -> ColumnType 'MSSQL -> Bool
forall a. Eq a => a -> a -> Bool
== (ScalarType 'MSSQL -> ColumnType 'MSSQL
forall (b :: BackendType). ScalarType b -> ColumnType b
IR.ColumnScalar ScalarType 'MSSQL
ScalarType
GeometryType) Bool -> Bool -> Bool
|| ColumnType 'MSSQL
typ ColumnType 'MSSQL -> ColumnType 'MSSQL -> Bool
forall a. Eq a => a -> a -> Bool
== (ScalarType 'MSSQL -> ColumnType 'MSSQL
forall (b :: BackendType). ScalarType b -> ColumnType b
IR.ColumnScalar ScalarType 'MSSQL
ScalarType
GeographyType)
    then Expression -> ReaderT EntityAlias FromIr Expression
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Expression -> ReaderT EntityAlias FromIr Expression)
-> Expression -> ReaderT EntityAlias FromIr Expression
forall a b. (a -> b) -> a -> b
$ Expression -> MethodApplicationExpression -> Expression
MethodApplicationExpression (FieldName -> Expression
ColumnExpression FieldName
fieldName) MethodApplicationExpression
MethExpSTAsText
    else case Maybe (AnnColumnCaseBoolExp 'MSSQL Expression)
caseBoolExpMaybe of
      Maybe (AnnColumnCaseBoolExp 'MSSQL Expression)
Nothing -> Expression -> ReaderT EntityAlias FromIr Expression
forall (f :: * -> *) a. Applicative f => a -> f a
pure (FieldName -> Expression
ColumnExpression FieldName
fieldName)
      Just AnnColumnCaseBoolExp 'MSSQL Expression
ex -> do
        Expression
ex' <- GBoolExp 'MSSQL (AnnBoolExpFld 'MSSQL Expression)
-> ReaderT EntityAlias FromIr Expression
fromGBoolExp (AnnColumnCaseBoolExp 'MSSQL Expression
-> GBoolExp 'MSSQL (AnnBoolExpFld 'MSSQL Expression)
coerce AnnColumnCaseBoolExp 'MSSQL Expression
ex)
        let nullValue :: Expression
nullValue = Value -> Expression
ValueExpression Value
ODBC.NullValue
        Expression -> ReaderT EntityAlias FromIr Expression
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Expression -> Expression -> Expression -> Expression
ConditionalExpression Expression
ex' (FieldName -> Expression
ColumnExpression FieldName
fieldName) Expression
nullValue)
  where
    IR.AnnColumnField
      { $sel:_acfColumn:AnnColumnField :: forall (b :: BackendType) v. AnnColumnField b v -> Column b
_acfColumn = Column 'MSSQL
column,
        $sel:_acfType:AnnColumnField :: forall (b :: BackendType) v. AnnColumnField b v -> ColumnType b
_acfType = ColumnType 'MSSQL
typ,
        $sel:_acfAsText:AnnColumnField :: forall (b :: BackendType) v. AnnColumnField b v -> Bool
_acfAsText = Bool
_asText :: Bool,
        $sel:_acfArguments:AnnColumnField :: forall (b :: BackendType) v.
AnnColumnField b v -> Maybe (ScalarSelectionArguments b)
_acfArguments = _ :: Maybe Void,
        $sel:_acfCaseBoolExpression:AnnColumnField :: forall (b :: BackendType) v.
AnnColumnField b v -> Maybe (AnnColumnCaseBoolExp b v)
_acfCaseBoolExpression = Maybe (AnnColumnCaseBoolExp 'MSSQL Expression)
caseBoolExpMaybe
      } = AnnColumnField 'MSSQL Expression
annColumnField

-- | This is where a field name "foo" is resolved to a fully qualified
-- field name [table].[foo]. The table name comes from EntityAlias in
-- the ReaderT.
fromColumn :: ColumnName -> ReaderT EntityAlias FromIr FieldName
fromColumn :: ColumnName -> ReaderT EntityAlias FromIr FieldName
fromColumn ColumnName
column = ColumnName -> EntityAlias -> FieldName
columnNameToFieldName ColumnName
column (EntityAlias -> FieldName)
-> ReaderT EntityAlias FromIr EntityAlias
-> ReaderT EntityAlias FromIr FieldName
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReaderT EntityAlias FromIr EntityAlias
forall r (m :: * -> *). MonadReader r m => m r
ask

--  entityAlias <- ask
--  pure (columnNameToFieldName column entityAlias -- FieldName {fieldName = columnName column, fieldNameEntity = entityAliasText}
--       )

fieldSourceProjections :: FieldSource -> Projection
fieldSourceProjections :: FieldSource -> Projection
fieldSourceProjections =
  \case
    ExpressionFieldSource Aliased Expression
aliasedExpression ->
      Aliased Expression -> Projection
ExpressionProjection Aliased Expression
aliasedExpression
    JoinFieldSource JsonCardinality
cardinality Aliased Join
aliasedJoin ->
      Aliased Expression -> Projection
ExpressionProjection
        ( Aliased Join
aliasedJoin
            { $sel:aliasedThing:Aliased :: Expression
aliasedThing =
                -- Basically a cast, to ensure that SQL Server won't
                -- double-encode the JSON but will "pass it through"
                -- untouched.
                JsonCardinality -> Expression -> Expression
safeJsonQueryExpression
                  JsonCardinality
cardinality
                  ( FieldName -> Expression
ColumnExpression
                      ( JoinAlias -> FieldName
joinAliasToField
                          (Join -> JoinAlias
joinJoinAlias (Aliased Join -> Join
forall a. Aliased a -> a
aliasedThing Aliased Join
aliasedJoin))
                      )
                  )
            }
        )

joinAliasToField :: JoinAlias -> FieldName
joinAliasToField :: JoinAlias -> FieldName
joinAliasToField JoinAlias {Maybe Text
Text
$sel:joinAliasField:JoinAlias :: JoinAlias -> Maybe Text
$sel:joinAliasEntity:JoinAlias :: JoinAlias -> Text
joinAliasField :: Maybe Text
joinAliasEntity :: Text
..} =
  FieldName :: Text -> Text -> FieldName
FieldName
    { $sel:fieldNameEntity:FieldName :: Text
fieldNameEntity = Text
joinAliasEntity,
      $sel:fieldName:FieldName :: Text
fieldName = Text -> Maybe Text -> Text
forall a. a -> Maybe a -> a
fromMaybe (String -> Text
forall a. HasCallStack => String -> a
error String
"TODO: Eliminate this case. joinAliasToField") Maybe Text
joinAliasField
    }

fieldSourceJoin :: FieldSource -> Maybe Join
fieldSourceJoin :: FieldSource -> Maybe Join
fieldSourceJoin =
  \case
    JoinFieldSource JsonCardinality
_ Aliased Join
aliasedJoin -> Join -> Maybe Join
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Aliased Join -> Join
forall a. Aliased a -> a
aliasedThing Aliased Join
aliasedJoin)
    ExpressionFieldSource {} -> Maybe Join
forall a. Maybe a
Nothing

--------------------------------------------------------------------------------
-- Joins

fromObjectRelationSelectG ::
  Map TableName EntityAlias ->
  IR.ObjectRelationSelectG 'MSSQL Void Expression ->
  ReaderT EntityAlias FromIr Join
fromObjectRelationSelectG :: Map TableName EntityAlias
-> ObjectRelationSelectG 'MSSQL Void Expression
-> ReaderT EntityAlias FromIr Join
fromObjectRelationSelectG Map TableName EntityAlias
existingJoins ObjectRelationSelectG 'MSSQL Void Expression
annRelationSelectG = do
  Either EntityAlias From
eitherAliasOrFrom <- FromIr (Either EntityAlias From)
-> ReaderT EntityAlias FromIr (Either EntityAlias From)
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (Map TableName EntityAlias
-> TableName -> FromIr (Either EntityAlias From)
lookupTableFrom Map TableName EntityAlias
existingJoins TableName
tableFrom)
  let EntityAlias
entityAlias :: EntityAlias = (EntityAlias -> EntityAlias)
-> (From -> EntityAlias) -> Either EntityAlias From -> EntityAlias
forall a c b. (a -> c) -> (b -> c) -> Either a b -> c
either EntityAlias -> EntityAlias
forall a. a -> a
id From -> EntityAlias
fromAlias Either EntityAlias From
eitherAliasOrFrom
  [FieldSource]
fieldSources <-
    (EntityAlias -> EntityAlias)
-> ReaderT EntityAlias FromIr [FieldSource]
-> ReaderT EntityAlias FromIr [FieldSource]
forall r (m :: * -> *) a. MonadReader r m => (r -> r) -> m a -> m a
local
      (EntityAlias -> EntityAlias -> EntityAlias
forall a b. a -> b -> a
const EntityAlias
entityAlias)
      (((FieldName, AnnFieldG 'MSSQL Void Expression)
 -> ReaderT EntityAlias FromIr FieldSource)
-> [(FieldName, AnnFieldG 'MSSQL Void Expression)]
-> ReaderT EntityAlias FromIr [FieldSource]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse (Map TableName EntityAlias
-> (FieldName, AnnFieldG 'MSSQL Void Expression)
-> ReaderT EntityAlias FromIr FieldSource
fromAnnFieldsG Map TableName EntityAlias
forall a. Monoid a => a
mempty) [(FieldName, AnnFieldG 'MSSQL Void Expression)]
fields)
  let selectProjections :: [Projection]
selectProjections = (FieldSource -> Projection) -> [FieldSource] -> [Projection]
forall a b. (a -> b) -> [a] -> [b]
map FieldSource -> Projection
fieldSourceProjections [FieldSource]
fieldSources
  JoinAlias
joinJoinAlias <-
    do
      Text
fieldName <- FromIr Text -> ReaderT EntityAlias FromIr Text
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (RelName -> FromIr Text
fromRelName RelName
_aarRelationshipName)
      Text
alias <- FromIr Text -> ReaderT EntityAlias FromIr Text
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (NameTemplate -> FromIr Text
generateAlias (Text -> NameTemplate
ObjectRelationTemplate Text
fieldName))
      JoinAlias -> ReaderT EntityAlias FromIr JoinAlias
forall (f :: * -> *) a. Applicative f => a -> f a
pure
        JoinAlias :: Text -> Maybe Text -> JoinAlias
JoinAlias
          { $sel:joinAliasEntity:JoinAlias :: Text
joinAliasEntity = Text
alias,
            $sel:joinAliasField:JoinAlias :: Maybe Text
joinAliasField = Text -> Maybe Text
forall (f :: * -> *) a. Applicative f => a -> f a
pure Text
jsonFieldName
          }
  let selectFor :: For
selectFor =
        ForJson -> For
JsonFor ForJson :: JsonCardinality -> Root -> ForJson
ForJson {$sel:jsonCardinality:ForJson :: JsonCardinality
jsonCardinality = JsonCardinality
JsonSingleton, $sel:jsonRoot:ForJson :: Root
jsonRoot = Root
NoRoot}
  Expression
filterExpression <- (EntityAlias -> EntityAlias)
-> ReaderT EntityAlias FromIr Expression
-> ReaderT EntityAlias FromIr Expression
forall r (m :: * -> *) a. MonadReader r m => (r -> r) -> m a -> m a
local (EntityAlias -> EntityAlias -> EntityAlias
forall a b. a -> b -> a
const EntityAlias
entityAlias) (GBoolExp 'MSSQL (AnnBoolExpFld 'MSSQL Expression)
-> ReaderT EntityAlias FromIr Expression
fromGBoolExp GBoolExp 'MSSQL (AnnBoolExpFld 'MSSQL Expression)
tableFilter)
  case Either EntityAlias From
eitherAliasOrFrom of
    Right From
selectFrom -> do
      [Expression]
foreignKeyConditions <- From
-> HashMap ColumnName ColumnName
-> ReaderT EntityAlias FromIr [Expression]
fromMapping From
selectFrom HashMap ColumnName ColumnName
mapping
      Join -> ReaderT EntityAlias FromIr Join
forall (f :: * -> *) a. Applicative f => a -> f a
pure
        Join :: JoinSource -> JoinAlias -> Join
Join
          { JoinAlias
joinJoinAlias :: JoinAlias
$sel:joinJoinAlias:Join :: JoinAlias
joinJoinAlias,
            $sel:joinSource:Join :: JoinSource
joinSource =
              Select -> JoinSource
JoinSelect
                Select
emptySelect
                  { $sel:selectOrderBy:Select :: Maybe (NonEmpty OrderBy)
selectOrderBy = Maybe (NonEmpty OrderBy)
forall a. Maybe a
Nothing,
                    $sel:selectTop:Select :: Top
selectTop = Top
NoTop,
                    [Projection]
selectProjections :: [Projection]
$sel:selectProjections:Select :: [Projection]
selectProjections,
                    $sel:selectFrom:Select :: Maybe From
selectFrom = From -> Maybe From
forall a. a -> Maybe a
Just From
selectFrom,
                    $sel:selectJoins:Select :: [Join]
selectJoins = (FieldSource -> Maybe Join) -> [FieldSource] -> [Join]
forall (f :: * -> *) a b.
Filterable f =>
(a -> Maybe b) -> f a -> f b
mapMaybe FieldSource -> Maybe Join
fieldSourceJoin [FieldSource]
fieldSources,
                    $sel:selectWhere:Select :: Where
selectWhere =
                      [Expression] -> Where
Where ([Expression]
foreignKeyConditions [Expression] -> [Expression] -> [Expression]
forall a. Semigroup a => a -> a -> a
<> [Expression
filterExpression]),
                    For
selectFor :: For
$sel:selectFor:Select :: For
selectFor,
                    $sel:selectOffset:Select :: Maybe Expression
selectOffset = Maybe Expression
forall a. Maybe a
Nothing
                  }
          }
    Left EntityAlias
_entityAlias ->
      Join -> ReaderT EntityAlias FromIr Join
forall (f :: * -> *) a. Applicative f => a -> f a
pure
        Join :: JoinSource -> JoinAlias -> Join
Join
          { JoinAlias
joinJoinAlias :: JoinAlias
$sel:joinJoinAlias:Join :: JoinAlias
joinJoinAlias,
            $sel:joinSource:Join :: JoinSource
joinSource =
              Reselect -> JoinSource
JoinReselect
                Reselect :: [Projection] -> For -> Where -> Reselect
Reselect
                  { $sel:reselectProjections:Reselect :: [Projection]
reselectProjections = [Projection]
selectProjections,
                    $sel:reselectFor:Reselect :: For
reselectFor = For
selectFor,
                    $sel:reselectWhere:Reselect :: Where
reselectWhere = [Expression] -> Where
Where [Expression
filterExpression]
                  }
          }
  where
    IR.AnnObjectSelectG
      { $sel:_aosFields:AnnObjectSelectG :: forall (b :: BackendType) r v.
AnnObjectSelectG b r v -> AnnFieldsG b r v
_aosFields = [(FieldName, AnnFieldG 'MSSQL Void Expression)]
fields :: IR.AnnFieldsG 'MSSQL Void Expression,
        $sel:_aosTableFrom:AnnObjectSelectG :: forall (b :: BackendType) r v.
AnnObjectSelectG b r v -> TableName b
_aosTableFrom = tableFrom :: TableName,
        $sel:_aosTableFilter:AnnObjectSelectG :: forall (b :: BackendType) r v.
AnnObjectSelectG b r v -> AnnBoolExp b v
_aosTableFilter = GBoolExp 'MSSQL (AnnBoolExpFld 'MSSQL Expression)
tableFilter :: IR.AnnBoolExp 'MSSQL Expression
      } = AnnObjectSelectG 'MSSQL Void Expression
annObjectSelectG
    IR.AnnRelationSelectG
      { RelName
$sel:_aarRelationshipName:AnnRelationSelectG :: forall (b :: BackendType) a. AnnRelationSelectG b a -> RelName
_aarRelationshipName :: RelName
_aarRelationshipName,
        $sel:_aarColumnMapping:AnnRelationSelectG :: forall (b :: BackendType) a.
AnnRelationSelectG b a -> HashMap (Column b) (Column b)
_aarColumnMapping = mapping :: HashMap ColumnName ColumnName,
        $sel:_aarAnnSelect:AnnRelationSelectG :: forall (b :: BackendType) a. AnnRelationSelectG b a -> a
_aarAnnSelect = AnnObjectSelectG 'MSSQL Void Expression
annObjectSelectG :: IR.AnnObjectSelectG 'MSSQL Void Expression
      } = ObjectRelationSelectG 'MSSQL Void Expression
annRelationSelectG

lookupTableFrom ::
  Map TableName EntityAlias ->
  TableName ->
  FromIr (Either EntityAlias From)
lookupTableFrom :: Map TableName EntityAlias
-> TableName -> FromIr (Either EntityAlias From)
lookupTableFrom Map TableName EntityAlias
existingJoins TableName
tableFrom = do
  case TableName -> Map TableName EntityAlias -> Maybe EntityAlias
forall k a. Ord k => k -> Map k a -> Maybe a
M.lookup TableName
tableFrom Map TableName EntityAlias
existingJoins of
    Just EntityAlias
entityAlias -> Either EntityAlias From -> FromIr (Either EntityAlias From)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (EntityAlias -> Either EntityAlias From
forall a b. a -> Either a b
Left EntityAlias
entityAlias)
    Maybe EntityAlias
Nothing -> (From -> Either EntityAlias From)
-> FromIr From -> FromIr (Either EntityAlias From)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap From -> Either EntityAlias From
forall a b. b -> Either a b
Right (TableName -> FromIr From
fromQualifiedTable TableName
tableFrom)

fromArraySelectG :: IR.ArraySelectG 'MSSQL Void Expression -> ReaderT EntityAlias FromIr Join
fromArraySelectG :: ArraySelectG 'MSSQL Void Expression
-> ReaderT EntityAlias FromIr Join
fromArraySelectG =
  \case
    IR.ASSimple ArrayRelationSelectG 'MSSQL Void Expression
arrayRelationSelectG ->
      ArrayRelationSelectG 'MSSQL Void Expression
-> ReaderT EntityAlias FromIr Join
fromArrayRelationSelectG ArrayRelationSelectG 'MSSQL Void Expression
arrayRelationSelectG
    IR.ASAggregate ArrayAggregateSelectG 'MSSQL Void Expression
arrayAggregateSelectG ->
      ArrayAggregateSelectG 'MSSQL Void Expression
-> ReaderT EntityAlias FromIr Join
fromArrayAggregateSelectG ArrayAggregateSelectG 'MSSQL Void Expression
arrayAggregateSelectG

fromArrayAggregateSelectG ::
  IR.AnnRelationSelectG 'MSSQL (IR.AnnAggregateSelectG 'MSSQL Void Expression) ->
  ReaderT EntityAlias FromIr Join
fromArrayAggregateSelectG :: ArrayAggregateSelectG 'MSSQL Void Expression
-> ReaderT EntityAlias FromIr Join
fromArrayAggregateSelectG ArrayAggregateSelectG 'MSSQL Void Expression
annRelationSelectG = do
  Text
fieldName <- FromIr Text -> ReaderT EntityAlias FromIr Text
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (RelName -> FromIr Text
fromRelName RelName
_aarRelationshipName)
  Select
joinSelect <- do
    EntityAlias
lhsEntityAlias <- ReaderT EntityAlias FromIr EntityAlias
forall r (m :: * -> *). MonadReader r m => m r
ask
    -- With this, the foreign key relations are injected automatically
    -- at the right place by fromSelectAggregate.
    FromIr Select -> ReaderT EntityAlias FromIr Select
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (Maybe (EntityAlias, HashMap ColumnName ColumnName)
-> AnnAggregateSelectG 'MSSQL Void Expression -> FromIr Select
fromSelectAggregate ((EntityAlias, HashMap ColumnName ColumnName)
-> Maybe (EntityAlias, HashMap ColumnName ColumnName)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (EntityAlias
lhsEntityAlias, HashMap ColumnName ColumnName
mapping)) AnnAggregateSelectG 'MSSQL Void Expression
annSelectG)
  Text
alias <- FromIr Text -> ReaderT EntityAlias FromIr Text
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (NameTemplate -> FromIr Text
generateAlias (Text -> NameTemplate
ArrayAggregateTemplate Text
fieldName))
  Join -> ReaderT EntityAlias FromIr Join
forall (f :: * -> *) a. Applicative f => a -> f a
pure
    Join :: JoinSource -> JoinAlias -> Join
Join
      { $sel:joinJoinAlias:Join :: JoinAlias
joinJoinAlias =
          JoinAlias :: Text -> Maybe Text -> JoinAlias
JoinAlias
            { $sel:joinAliasEntity:JoinAlias :: Text
joinAliasEntity = Text
alias,
              $sel:joinAliasField:JoinAlias :: Maybe Text
joinAliasField = Text -> Maybe Text
forall (f :: * -> *) a. Applicative f => a -> f a
pure Text
jsonFieldName
            },
        $sel:joinSource:Join :: JoinSource
joinSource = Select -> JoinSource
JoinSelect Select
joinSelect
      }
  where
    IR.AnnRelationSelectG
      { RelName
_aarRelationshipName :: RelName
$sel:_aarRelationshipName:AnnRelationSelectG :: forall (b :: BackendType) a. AnnRelationSelectG b a -> RelName
_aarRelationshipName,
        $sel:_aarColumnMapping:AnnRelationSelectG :: forall (b :: BackendType) a.
AnnRelationSelectG b a -> HashMap (Column b) (Column b)
_aarColumnMapping = mapping :: HashMap ColumnName ColumnName,
        $sel:_aarAnnSelect:AnnRelationSelectG :: forall (b :: BackendType) a. AnnRelationSelectG b a -> a
_aarAnnSelect = AnnAggregateSelectG 'MSSQL Void Expression
annSelectG
      } = ArrayAggregateSelectG 'MSSQL Void Expression
annRelationSelectG

fromArrayRelationSelectG :: IR.ArrayRelationSelectG 'MSSQL Void Expression -> ReaderT EntityAlias FromIr Join
fromArrayRelationSelectG :: ArrayRelationSelectG 'MSSQL Void Expression
-> ReaderT EntityAlias FromIr Join
fromArrayRelationSelectG ArrayRelationSelectG 'MSSQL Void Expression
annRelationSelectG = do
  Text
fieldName <- FromIr Text -> ReaderT EntityAlias FromIr Text
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (RelName -> FromIr Text
fromRelName RelName
_aarRelationshipName)
  Select
sel <- FromIr Select -> ReaderT EntityAlias FromIr Select
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (AnnSimpleSelectG 'MSSQL Void Expression -> FromIr Select
fromSelectRows AnnSimpleSelectG 'MSSQL Void Expression
annSelectG)
  Select
joinSelect <-
    do
      [Expression]
foreignKeyConditions <- Select
-> HashMap ColumnName ColumnName
-> ReaderT EntityAlias FromIr [Expression]
selectFromMapping Select
sel HashMap ColumnName ColumnName
mapping
      Select -> ReaderT EntityAlias FromIr Select
forall (f :: * -> *) a. Applicative f => a -> f a
pure
        Select
sel {$sel:selectWhere:Select :: Where
selectWhere = [Expression] -> Where
Where [Expression]
foreignKeyConditions Where -> Where -> Where
forall a. Semigroup a => a -> a -> a
<> Select -> Where
selectWhere Select
sel}
  Text
alias <- FromIr Text -> ReaderT EntityAlias FromIr Text
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (NameTemplate -> FromIr Text
generateAlias (Text -> NameTemplate
ArrayRelationTemplate Text
fieldName))
  Join -> ReaderT EntityAlias FromIr Join
forall (f :: * -> *) a. Applicative f => a -> f a
pure
    Join :: JoinSource -> JoinAlias -> Join
Join
      { $sel:joinJoinAlias:Join :: JoinAlias
joinJoinAlias =
          JoinAlias :: Text -> Maybe Text -> JoinAlias
JoinAlias
            { $sel:joinAliasEntity:JoinAlias :: Text
joinAliasEntity = Text
alias,
              $sel:joinAliasField:JoinAlias :: Maybe Text
joinAliasField = Text -> Maybe Text
forall (f :: * -> *) a. Applicative f => a -> f a
pure Text
jsonFieldName
            },
        $sel:joinSource:Join :: JoinSource
joinSource = Select -> JoinSource
JoinSelect Select
joinSelect
      }
  where
    IR.AnnRelationSelectG
      { RelName
_aarRelationshipName :: RelName
$sel:_aarRelationshipName:AnnRelationSelectG :: forall (b :: BackendType) a. AnnRelationSelectG b a -> RelName
_aarRelationshipName,
        $sel:_aarColumnMapping:AnnRelationSelectG :: forall (b :: BackendType) a.
AnnRelationSelectG b a -> HashMap (Column b) (Column b)
_aarColumnMapping = mapping :: HashMap ColumnName ColumnName,
        $sel:_aarAnnSelect:AnnRelationSelectG :: forall (b :: BackendType) a. AnnRelationSelectG b a -> a
_aarAnnSelect = AnnSimpleSelectG 'MSSQL Void Expression
annSelectG
      } = ArrayRelationSelectG 'MSSQL Void Expression
annRelationSelectG

fromRelName :: IR.RelName -> FromIr Text
fromRelName :: RelName -> FromIr Text
fromRelName RelName
relName =
  Text -> FromIr Text
forall (f :: * -> *) a. Applicative f => a -> f a
pure (RelName -> Text
IR.relNameToTxt RelName
relName)

-- | The context given by the reader is of the previous/parent
-- "remote" table. The WHERE that we're generating goes in the child,
-- "local" query. The @From@ passed in as argument is the local table.
--
-- We should hope to see e.g. "post.category = category.id" for a
-- local table of post and a remote table of category.
--
-- The left/right columns in @HashMap ColumnName ColumnName@ corresponds
-- to the left/right of @select ... join ...@. Therefore left=remote,
-- right=local in this context.
fromMapping ::
  From ->
  HashMap ColumnName ColumnName ->
  ReaderT EntityAlias FromIr [Expression]
fromMapping :: From
-> HashMap ColumnName ColumnName
-> ReaderT EntityAlias FromIr [Expression]
fromMapping From
localFrom =
  ((ColumnName, ColumnName) -> ReaderT EntityAlias FromIr Expression)
-> [(ColumnName, ColumnName)]
-> ReaderT EntityAlias FromIr [Expression]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse
    ( \(ColumnName
remoteColumn, ColumnName
localColumn) -> do
        FieldName
localFieldName <- (EntityAlias -> EntityAlias)
-> ReaderT EntityAlias FromIr FieldName
-> ReaderT EntityAlias FromIr FieldName
forall r (m :: * -> *) a. MonadReader r m => (r -> r) -> m a -> m a
local (EntityAlias -> EntityAlias -> EntityAlias
forall a b. a -> b -> a
const (From -> EntityAlias
fromAlias From
localFrom)) (ColumnName -> ReaderT EntityAlias FromIr FieldName
fromColumn ColumnName
localColumn)
        FieldName
remoteFieldName <- ColumnName -> ReaderT EntityAlias FromIr FieldName
fromColumn ColumnName
remoteColumn
        Expression -> ReaderT EntityAlias FromIr Expression
forall (f :: * -> *) a. Applicative f => a -> f a
pure
          ( Op -> Expression -> Expression -> Expression
OpExpression
              Op
TSQL.EQ'
              (FieldName -> Expression
ColumnExpression FieldName
localFieldName)
              (FieldName -> Expression
ColumnExpression FieldName
remoteFieldName)
          )
    )
    ([(ColumnName, ColumnName)]
 -> ReaderT EntityAlias FromIr [Expression])
-> (HashMap ColumnName ColumnName -> [(ColumnName, ColumnName)])
-> HashMap ColumnName ColumnName
-> ReaderT EntityAlias FromIr [Expression]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HashMap ColumnName ColumnName -> [(ColumnName, ColumnName)]
forall k v. HashMap k v -> [(k, v)]
HM.toList

selectFromMapping ::
  Select ->
  HashMap ColumnName ColumnName ->
  ReaderT EntityAlias FromIr [Expression]
selectFromMapping :: Select
-> HashMap ColumnName ColumnName
-> ReaderT EntityAlias FromIr [Expression]
selectFromMapping Select {$sel:selectFrom:Select :: Select -> Maybe From
selectFrom = Maybe From
Nothing} = ReaderT EntityAlias FromIr [Expression]
-> HashMap ColumnName ColumnName
-> ReaderT EntityAlias FromIr [Expression]
forall a b. a -> b -> a
const ([Expression] -> ReaderT EntityAlias FromIr [Expression]
forall (f :: * -> *) a. Applicative f => a -> f a
pure [])
selectFromMapping Select {$sel:selectFrom:Select :: Select -> Maybe From
selectFrom = Just From
from} = From
-> HashMap ColumnName ColumnName
-> ReaderT EntityAlias FromIr [Expression]
fromMapping From
from

-- | A version of @JSON_QUERY(..)@ that returns a proper json literal, rather
-- than SQL null, which does not compose properly with @FOR JSON@ clauses.
safeJsonQueryExpression :: JsonCardinality -> Expression -> Expression
safeJsonQueryExpression :: JsonCardinality -> Expression -> Expression
safeJsonQueryExpression JsonCardinality
expectedType Expression
jsonQuery =
  FunctionApplicationExpression -> Expression
FunctionApplicationExpression (Expression -> Expression -> FunctionApplicationExpression
FunExpISNULL (Expression -> Expression
JsonQueryExpression Expression
jsonQuery) Expression
jsonTypeExpression)
  where
    jsonTypeExpression :: Expression
jsonTypeExpression = case JsonCardinality
expectedType of
      JsonCardinality
JsonSingleton -> Expression
nullExpression
      JsonCardinality
JsonArray -> Expression
emptyArrayExpression

--------------------------------------------------------------------------------
-- Constants

data UnfurledJoin = UnfurledJoin
  { UnfurledJoin -> Join
unfurledJoin :: Join,
    -- | Recorded if we joined onto an object relation.
    UnfurledJoin -> Maybe (TableName, EntityAlias)
unfurledObjectTableAlias :: Maybe (TableName, EntityAlias)
  }
  deriving (Int -> UnfurledJoin -> ShowS
[UnfurledJoin] -> ShowS
UnfurledJoin -> String
(Int -> UnfurledJoin -> ShowS)
-> (UnfurledJoin -> String)
-> ([UnfurledJoin] -> ShowS)
-> Show UnfurledJoin
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [UnfurledJoin] -> ShowS
$cshowList :: [UnfurledJoin] -> ShowS
show :: UnfurledJoin -> String
$cshow :: UnfurledJoin -> String
showsPrec :: Int -> UnfurledJoin -> ShowS
$cshowsPrec :: Int -> UnfurledJoin -> ShowS
Show)

fromAnnotatedOrderByItemG ::
  IR.AnnotatedOrderByItemG 'MSSQL Expression ->
  WriterT (Seq UnfurledJoin) (ReaderT EntityAlias FromIr) OrderBy
fromAnnotatedOrderByItemG :: AnnotatedOrderByItemG 'MSSQL Expression
-> WriterT (Seq UnfurledJoin) (ReaderT EntityAlias FromIr) OrderBy
fromAnnotatedOrderByItemG IR.OrderByItemG {Maybe (BasicOrderType 'MSSQL)
obiType :: forall (b :: BackendType) a.
OrderByItemG b a -> Maybe (BasicOrderType b)
obiType :: Maybe (BasicOrderType 'MSSQL)
obiType, obiColumn :: forall (b :: BackendType) a. OrderByItemG b a -> a
obiColumn = AnnotatedOrderByElement 'MSSQL Expression
obiColumn, Maybe (NullsOrderType 'MSSQL)
obiNulls :: forall (b :: BackendType) a.
OrderByItemG b a -> Maybe (NullsOrderType b)
obiNulls :: Maybe (NullsOrderType 'MSSQL)
obiNulls} = do
  (FieldName
orderByFieldName, Maybe ScalarType
orderByType) <- AnnotatedOrderByElement 'MSSQL Expression
-> WriterT
     (Seq UnfurledJoin)
     (ReaderT EntityAlias FromIr)
     (FieldName, Maybe ScalarType)
unfurlAnnotatedOrderByElement AnnotatedOrderByElement 'MSSQL Expression
obiColumn
  let orderByNullsOrder :: NullsOrder
orderByNullsOrder = NullsOrder -> Maybe NullsOrder -> NullsOrder
forall a. a -> Maybe a -> a
fromMaybe NullsOrder
NullsAnyOrder Maybe (NullsOrderType 'MSSQL)
Maybe NullsOrder
obiNulls
      orderByOrder :: Order
orderByOrder = Order -> Maybe Order -> Order
forall a. a -> Maybe a -> a
fromMaybe Order
AscOrder Maybe (BasicOrderType 'MSSQL)
Maybe Order
obiType
  OrderBy
-> WriterT (Seq UnfurledJoin) (ReaderT EntityAlias FromIr) OrderBy
forall (f :: * -> *) a. Applicative f => a -> f a
pure OrderBy :: FieldName -> Order -> NullsOrder -> Maybe ScalarType -> OrderBy
OrderBy {Maybe ScalarType
FieldName
NullsOrder
Order
$sel:orderByType:OrderBy :: Maybe ScalarType
$sel:orderByNullsOrder:OrderBy :: NullsOrder
$sel:orderByOrder:OrderBy :: Order
$sel:orderByFieldName:OrderBy :: FieldName
orderByOrder :: Order
orderByNullsOrder :: NullsOrder
orderByType :: Maybe ScalarType
orderByFieldName :: FieldName
..}

-- | Unfurl the nested set of object relations (tell'd in the writer)
-- that are terminated by field name (IR.AOCColumn and
-- IR.AOCArrayAggregation).
unfurlAnnotatedOrderByElement ::
  IR.AnnotatedOrderByElement 'MSSQL Expression ->
  WriterT (Seq UnfurledJoin) (ReaderT EntityAlias FromIr) (FieldName, Maybe TSQL.ScalarType)
unfurlAnnotatedOrderByElement :: AnnotatedOrderByElement 'MSSQL Expression
-> WriterT
     (Seq UnfurledJoin)
     (ReaderT EntityAlias FromIr)
     (FieldName, Maybe ScalarType)
unfurlAnnotatedOrderByElement =
  \case
    IR.AOCColumn ColumnInfo 'MSSQL
columnInfo -> do
      FieldName
fieldName <- ReaderT EntityAlias FromIr FieldName
-> WriterT
     (Seq UnfurledJoin) (ReaderT EntityAlias FromIr) FieldName
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (ColumnInfo 'MSSQL -> ReaderT EntityAlias FromIr FieldName
fromColumnInfo ColumnInfo 'MSSQL
columnInfo)
      (FieldName, Maybe ScalarType)
-> WriterT
     (Seq UnfurledJoin)
     (ReaderT EntityAlias FromIr)
     (FieldName, Maybe ScalarType)
forall (f :: * -> *) a. Applicative f => a -> f a
pure
        ( FieldName
fieldName,
          case ColumnInfo 'MSSQL -> ColumnType 'MSSQL
forall (b :: BackendType). ColumnInfo b -> ColumnType b
IR.ciType ColumnInfo 'MSSQL
columnInfo of
            IR.ColumnScalar ScalarType 'MSSQL
t -> ScalarType -> Maybe ScalarType
forall a. a -> Maybe a
Just ScalarType 'MSSQL
ScalarType
t
            -- Above: It is of interest to us whether the type is
            -- text/ntext/image. See ToQuery for more explanation.
            ColumnType 'MSSQL
_ -> Maybe ScalarType
forall a. Maybe a
Nothing
        )
    IR.AOCObjectRelation IR.RelInfo {riMapping :: forall (b :: BackendType).
RelInfo b -> HashMap (Column b) (Column b)
riMapping = HashMap (Column 'MSSQL) (Column 'MSSQL)
mapping, riRTable :: forall (b :: BackendType). RelInfo b -> TableName b
riRTable = TableName 'MSSQL
table} GBoolExp 'MSSQL (AnnBoolExpFld 'MSSQL Expression)
annBoolExp AnnotatedOrderByElement 'MSSQL Expression
annOrderByElementG -> do
      From
selectFrom <- ReaderT EntityAlias FromIr From
-> WriterT (Seq UnfurledJoin) (ReaderT EntityAlias FromIr) From
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (FromIr From -> ReaderT EntityAlias FromIr From
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (TableName -> FromIr From
fromQualifiedTable TableName 'MSSQL
TableName
table))
      Text
joinAliasEntity <-
        ReaderT EntityAlias FromIr Text
-> WriterT (Seq UnfurledJoin) (ReaderT EntityAlias FromIr) Text
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (FromIr Text -> ReaderT EntityAlias FromIr Text
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (NameTemplate -> FromIr Text
generateAlias (Text -> NameTemplate
ForOrderAlias (TableName -> Text
tableNameText TableName 'MSSQL
TableName
table))))
      [Expression]
foreignKeyConditions <- ReaderT EntityAlias FromIr [Expression]
-> WriterT
     (Seq UnfurledJoin) (ReaderT EntityAlias FromIr) [Expression]
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (From
-> HashMap ColumnName ColumnName
-> ReaderT EntityAlias FromIr [Expression]
fromMapping From
selectFrom HashMap (Column 'MSSQL) (Column 'MSSQL)
HashMap ColumnName ColumnName
mapping)
      -- TODO: Because these object relations are re-used by regular
      -- object mapping queries, this WHERE may be unnecessarily
      -- restrictive. But I actually don't know from where such an
      -- expression arises in the source GraphQL syntax.
      --
      -- Worst case scenario, we could put the WHERE in the key of the
      -- Map in 'argsExistingJoins'. That would guarantee only equal
      -- selects are re-used.
      Expression
whereExpression <-
        ReaderT EntityAlias FromIr Expression
-> WriterT
     (Seq UnfurledJoin) (ReaderT EntityAlias FromIr) Expression
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift ((EntityAlias -> EntityAlias)
-> ReaderT EntityAlias FromIr Expression
-> ReaderT EntityAlias FromIr Expression
forall r (m :: * -> *) a. MonadReader r m => (r -> r) -> m a -> m a
local (EntityAlias -> EntityAlias -> EntityAlias
forall a b. a -> b -> a
const (From -> EntityAlias
fromAlias From
selectFrom)) (GBoolExp 'MSSQL (AnnBoolExpFld 'MSSQL Expression)
-> ReaderT EntityAlias FromIr Expression
fromGBoolExp GBoolExp 'MSSQL (AnnBoolExpFld 'MSSQL Expression)
annBoolExp))
      Seq UnfurledJoin
-> WriterT (Seq UnfurledJoin) (ReaderT EntityAlias FromIr) ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell
        ( UnfurledJoin -> Seq UnfurledJoin
forall (f :: * -> *) a. Applicative f => a -> f a
pure
            UnfurledJoin :: Join -> Maybe (TableName, EntityAlias) -> UnfurledJoin
UnfurledJoin
              { unfurledJoin :: Join
unfurledJoin =
                  Join :: JoinSource -> JoinAlias -> Join
Join
                    { $sel:joinSource:Join :: JoinSource
joinSource =
                        Select -> JoinSource
JoinSelect
                          Select
emptySelect
                            { $sel:selectTop:Select :: Top
selectTop = Top
NoTop,
                              $sel:selectProjections:Select :: [Projection]
selectProjections = [Projection
StarProjection],
                              $sel:selectFrom:Select :: Maybe From
selectFrom = From -> Maybe From
forall a. a -> Maybe a
Just From
selectFrom,
                              $sel:selectJoins:Select :: [Join]
selectJoins = [],
                              $sel:selectWhere:Select :: Where
selectWhere =
                                [Expression] -> Where
Where ([Expression]
foreignKeyConditions [Expression] -> [Expression] -> [Expression]
forall a. Semigroup a => a -> a -> a
<> [Expression
whereExpression]),
                              $sel:selectFor:Select :: For
selectFor = For
NoFor,
                              $sel:selectOrderBy:Select :: Maybe (NonEmpty OrderBy)
selectOrderBy = Maybe (NonEmpty OrderBy)
forall a. Maybe a
Nothing,
                              $sel:selectOffset:Select :: Maybe Expression
selectOffset = Maybe Expression
forall a. Maybe a
Nothing
                            },
                      $sel:joinJoinAlias:Join :: JoinAlias
joinJoinAlias =
                        JoinAlias :: Text -> Maybe Text -> JoinAlias
JoinAlias {Text
joinAliasEntity :: Text
$sel:joinAliasEntity:JoinAlias :: Text
joinAliasEntity, $sel:joinAliasField:JoinAlias :: Maybe Text
joinAliasField = Maybe Text
forall a. Maybe a
Nothing}
                    },
                unfurledObjectTableAlias :: Maybe (TableName, EntityAlias)
unfurledObjectTableAlias = (TableName, EntityAlias) -> Maybe (TableName, EntityAlias)
forall a. a -> Maybe a
Just (TableName 'MSSQL
TableName
table, Text -> EntityAlias
EntityAlias Text
joinAliasEntity)
              }
        )
      (EntityAlias -> EntityAlias)
-> WriterT
     (Seq UnfurledJoin)
     (ReaderT EntityAlias FromIr)
     (FieldName, Maybe ScalarType)
-> WriterT
     (Seq UnfurledJoin)
     (ReaderT EntityAlias FromIr)
     (FieldName, Maybe ScalarType)
forall r (m :: * -> *) a. MonadReader r m => (r -> r) -> m a -> m a
local
        (EntityAlias -> EntityAlias -> EntityAlias
forall a b. a -> b -> a
const (Text -> EntityAlias
EntityAlias Text
joinAliasEntity))
        (AnnotatedOrderByElement 'MSSQL Expression
-> WriterT
     (Seq UnfurledJoin)
     (ReaderT EntityAlias FromIr)
     (FieldName, Maybe ScalarType)
unfurlAnnotatedOrderByElement AnnotatedOrderByElement 'MSSQL Expression
annOrderByElementG)
    IR.AOCArrayAggregation IR.RelInfo {riMapping :: forall (b :: BackendType).
RelInfo b -> HashMap (Column b) (Column b)
riMapping = HashMap (Column 'MSSQL) (Column 'MSSQL)
mapping, riRTable :: forall (b :: BackendType). RelInfo b -> TableName b
riRTable = TableName 'MSSQL
tableName} GBoolExp 'MSSQL (AnnBoolExpFld 'MSSQL Expression)
annBoolExp AnnotatedAggregateOrderBy 'MSSQL
annAggregateOrderBy -> do
      From
selectFrom <- ReaderT EntityAlias FromIr From
-> WriterT (Seq UnfurledJoin) (ReaderT EntityAlias FromIr) From
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (FromIr From -> ReaderT EntityAlias FromIr From
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (TableName -> FromIr From
fromQualifiedTable TableName 'MSSQL
TableName
tableName))
      let alias :: Text
alias = Text
aggFieldName
      Text
joinAliasEntity <-
        ReaderT EntityAlias FromIr Text
-> WriterT (Seq UnfurledJoin) (ReaderT EntityAlias FromIr) Text
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (FromIr Text -> ReaderT EntityAlias FromIr Text
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (NameTemplate -> FromIr Text
generateAlias (Text -> NameTemplate
ForOrderAlias (TableName -> Text
tableNameText TableName 'MSSQL
TableName
tableName))))
      [Expression]
foreignKeyConditions <- ReaderT EntityAlias FromIr [Expression]
-> WriterT
     (Seq UnfurledJoin) (ReaderT EntityAlias FromIr) [Expression]
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift (From
-> HashMap ColumnName ColumnName
-> ReaderT EntityAlias FromIr [Expression]
fromMapping From
selectFrom HashMap (Column 'MSSQL) (Column 'MSSQL)
HashMap ColumnName ColumnName
mapping)
      Expression
whereExpression <-
        ReaderT EntityAlias FromIr Expression
-> WriterT
     (Seq UnfurledJoin) (ReaderT EntityAlias FromIr) Expression
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift ((EntityAlias -> EntityAlias)
-> ReaderT EntityAlias FromIr Expression
-> ReaderT EntityAlias FromIr Expression
forall r (m :: * -> *) a. MonadReader r m => (r -> r) -> m a -> m a
local (EntityAlias -> EntityAlias -> EntityAlias
forall a b. a -> b -> a
const (From -> EntityAlias
fromAlias From
selectFrom)) (GBoolExp 'MSSQL (AnnBoolExpFld 'MSSQL Expression)
-> ReaderT EntityAlias FromIr Expression
fromGBoolExp GBoolExp 'MSSQL (AnnBoolExpFld 'MSSQL Expression)
annBoolExp))
      Aggregate
aggregate <-
        ReaderT EntityAlias FromIr Aggregate
-> WriterT
     (Seq UnfurledJoin) (ReaderT EntityAlias FromIr) Aggregate
forall (t :: (* -> *) -> * -> *) (m :: * -> *) a.
(MonadTrans t, Monad m) =>
m a -> t m a
lift
          ( (EntityAlias -> EntityAlias)
-> ReaderT EntityAlias FromIr Aggregate
-> ReaderT EntityAlias FromIr Aggregate
forall r (m :: * -> *) a. MonadReader r m => (r -> r) -> m a -> m a
local
              (EntityAlias -> EntityAlias -> EntityAlias
forall a b. a -> b -> a
const (From -> EntityAlias
fromAlias From
selectFrom))
              ( case AnnotatedAggregateOrderBy 'MSSQL
annAggregateOrderBy of
                  AnnotatedAggregateOrderBy 'MSSQL
IR.AAOCount -> Aggregate -> ReaderT EntityAlias FromIr Aggregate
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Countable FieldName -> Aggregate
CountAggregate Countable FieldName
forall name. Countable name
StarCountable)
                  IR.AAOOp Text
text ColumnInfo 'MSSQL
columnInfo -> do
                    FieldName
fieldName <- ColumnInfo 'MSSQL -> ReaderT EntityAlias FromIr FieldName
fromColumnInfo ColumnInfo 'MSSQL
columnInfo
                    Aggregate -> ReaderT EntityAlias FromIr Aggregate
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> [Expression] -> Aggregate
OpAggregate Text
text (Expression -> [Expression]
forall (f :: * -> *) a. Applicative f => a -> f a
pure (FieldName -> Expression
ColumnExpression FieldName
fieldName)))
              )
          )
      Seq UnfurledJoin
-> WriterT (Seq UnfurledJoin) (ReaderT EntityAlias FromIr) ()
forall w (m :: * -> *). MonadWriter w m => w -> m ()
tell
        ( UnfurledJoin -> Seq UnfurledJoin
forall (f :: * -> *) a. Applicative f => a -> f a
pure
            ( UnfurledJoin :: Join -> Maybe (TableName, EntityAlias) -> UnfurledJoin
UnfurledJoin
                { unfurledJoin :: Join
unfurledJoin =
                    Join :: JoinSource -> JoinAlias -> Join
Join
                      { $sel:joinSource:Join :: JoinSource
joinSource =
                          Select -> JoinSource
JoinSelect
                            Select
emptySelect
                              { $sel:selectTop:Select :: Top
selectTop = Top
NoTop,
                                $sel:selectProjections:Select :: [Projection]
selectProjections =
                                  [ Aliased Aggregate -> Projection
AggregateProjection
                                      Aliased :: forall a. a -> Text -> Aliased a
Aliased
                                        { $sel:aliasedThing:Aliased :: Aggregate
aliasedThing = Aggregate
aggregate,
                                          $sel:aliasedAlias:Aliased :: Text
aliasedAlias = Text
alias
                                        }
                                  ],
                                $sel:selectFrom:Select :: Maybe From
selectFrom = From -> Maybe From
forall a. a -> Maybe a
Just From
selectFrom,
                                $sel:selectJoins:Select :: [Join]
selectJoins = [],
                                $sel:selectWhere:Select :: Where
selectWhere =
                                  [Expression] -> Where
Where
                                    ([Expression]
foreignKeyConditions [Expression] -> [Expression] -> [Expression]
forall a. Semigroup a => a -> a -> a
<> [Expression
whereExpression]),
                                $sel:selectFor:Select :: For
selectFor = For
NoFor,
                                $sel:selectOrderBy:Select :: Maybe (NonEmpty OrderBy)
selectOrderBy = Maybe (NonEmpty OrderBy)
forall a. Maybe a
Nothing,
                                $sel:selectOffset:Select :: Maybe Expression
selectOffset = Maybe Expression
forall a. Maybe a
Nothing
                              },
                        $sel:joinJoinAlias:Join :: JoinAlias
joinJoinAlias =
                          JoinAlias :: Text -> Maybe Text -> JoinAlias
JoinAlias {Text
joinAliasEntity :: Text
$sel:joinAliasEntity:JoinAlias :: Text
joinAliasEntity, $sel:joinAliasField:JoinAlias :: Maybe Text
joinAliasField = Maybe Text
forall a. Maybe a
Nothing}
                      },
                  unfurledObjectTableAlias :: Maybe (TableName, EntityAlias)
unfurledObjectTableAlias = Maybe (TableName, EntityAlias)
forall a. Maybe a
Nothing
                }
            )
        )
      (FieldName, Maybe ScalarType)
-> WriterT
     (Seq UnfurledJoin)
     (ReaderT EntityAlias FromIr)
     (FieldName, Maybe ScalarType)
forall (f :: * -> *) a. Applicative f => a -> f a
pure
        ( FieldName :: Text -> Text -> FieldName
FieldName {$sel:fieldNameEntity:FieldName :: Text
fieldNameEntity = Text
joinAliasEntity, $sel:fieldName:FieldName :: Text
fieldName = Text
alias},
          Maybe ScalarType
forall a. Maybe a
Nothing
        )

tableNameText :: TableName -> Text
tableNameText :: TableName -> Text
tableNameText (TableName {Text
tableName :: Text
$sel:tableName:TableName :: TableName -> Text
tableName}) = Text
tableName

fromColumnInfo :: IR.ColumnInfo 'MSSQL -> ReaderT EntityAlias FromIr FieldName
fromColumnInfo :: ColumnInfo 'MSSQL -> ReaderT EntityAlias FromIr FieldName
fromColumnInfo IR.ColumnInfo {ciColumn :: forall (b :: BackendType). ColumnInfo b -> Column b
ciColumn = Column 'MSSQL
column} =
  ColumnName -> EntityAlias -> FieldName
columnNameToFieldName Column 'MSSQL
ColumnName
column (EntityAlias -> FieldName)
-> ReaderT EntityAlias FromIr EntityAlias
-> ReaderT EntityAlias FromIr FieldName
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> ReaderT EntityAlias FromIr EntityAlias
forall r (m :: * -> *). MonadReader r m => m r
ask