project-m36-1.0.0: src/lib/ProjectM36/SQL/Select.hs
{-# LANGUAGE TemplateHaskell, TypeFamilies, DeriveTraversable, GeneralizedNewtypeDeriving, DerivingVia, DeriveAnyClass, DeriveGeneric, StandaloneDeriving, FlexibleInstances #-}
module ProjectM36.SQL.Select where
import qualified Data.List.NonEmpty as NE
import Data.Text (Text)
import Data.Functor.Foldable.TH
import Codec.Winery
import GHC.Generics
import Control.DeepSeq
import Data.Hashable
data Query = QuerySelect Select |
QueryValues [[ScalarExpr]] |
QueryTable TableName |
QueryOp QueryOperator Query Query
deriving (Show, Eq, Generic, NFData)
deriving Serialise via WineryVariant Query
data QueryOperator = UnionQueryOperator | IntersectQueryOperator | ExceptQueryOperator
deriving (Show, Eq, Generic, NFData)
deriving Serialise via WineryVariant QueryOperator
data Select = Select { distinctness :: Maybe Distinctness,
projectionClause :: [SelectItem],
tableExpr :: Maybe TableExpr,
withClause :: Maybe WithClause
}
deriving (Show, Eq, Generic, NFData)
deriving Serialise via WineryRecord Select
instance Hashable Select
emptySelect :: Select
emptySelect = Select { distinctness = Nothing,
projectionClause = [],
tableExpr = Nothing,
withClause = Nothing
}
type SelectItem = (ProjectionScalarExpr, Maybe ColumnAlias)
data WithClause = WithClause { isRecursive :: Bool,
withExprs :: NE.NonEmpty WithExpr }
deriving (Show, Eq, Generic, NFData)
deriving Serialise via WineryRecord WithClause
deriving Hashable
data WithExpr = WithExpr WithExprAlias Select
deriving (Show, Eq, Generic, NFData)
deriving Serialise via WineryVariant WithExpr
deriving Hashable
newtype WithExprAlias = WithExprAlias Text
deriving (Show, Eq, Generic)
deriving Serialise via WineryVariant WithExprAlias
deriving newtype NFData
deriving anyclass Hashable
data InFlag = In | NotIn
deriving (Show, Eq, Generic, NFData)
deriving Serialise via WineryVariant InFlag
deriving Hashable
data ComparisonOperator = OpLT | OpGT | OpGTE | OpEQ | OpNE | OpLTE
deriving (Show, Eq, Generic, NFData)
deriving Serialise via WineryVariant ComparisonOperator
instance Hashable ComparisonOperator
data QuantifiedComparisonPredicate = QCAny | QCSome | QCAll
deriving (Show, Eq, Generic, NFData)
deriving Serialise via WineryVariant QuantifiedComparisonPredicate
instance Hashable QuantifiedComparisonPredicate
data TableRef = SimpleTableRef TableName
| InnerJoinTableRef TableRef JoinCondition
| RightOuterJoinTableRef TableRef JoinCondition
| LeftOuterJoinTableRef TableRef JoinCondition
| FullOuterJoinTableRef TableRef JoinCondition
| CrossJoinTableRef TableRef
| NaturalJoinTableRef TableRef
| AliasedTableRef TableRef TableAlias
| QueryTableRef Select
deriving (Show, Eq, Generic, NFData)
deriving Serialise via WineryVariant TableRef
deriving Hashable
-- distinguish between projection attributes which may include an asterisk and scalar expressions (such as in a where clause) where an asterisk is invalid
type ProjectionScalarExpr = ScalarExprBase ColumnProjectionName
deriving via WineryVariant ProjectionScalarExpr instance Serialise ProjectionScalarExpr
type ScalarExpr = ScalarExprBase ColumnName
deriving via WineryVariant ScalarExpr instance Serialise ScalarExpr
data ScalarExprBase n =
IntegerLiteral Integer
| DoubleLiteral Double
| StringLiteral Text
| BooleanLiteral Bool
| NullLiteral
-- | Interval
| Identifier n
| BinaryOperator (ScalarExprBase n) OperatorName (ScalarExprBase n)
| PrefixOperator OperatorName (ScalarExprBase n)
| PostfixOperator (ScalarExprBase n) OperatorName
| BetweenOperator (ScalarExprBase n) (ScalarExprBase n) (ScalarExprBase n)
| FunctionApplication FuncName [ScalarExprBase n]
| CaseExpr { caseWhens :: [(ScalarExprBase n,ScalarExprBase n)],
caseElse :: Maybe (ScalarExprBase n) }
| QuantifiedComparison { qcExpr :: ScalarExprBase n,
qcOperator :: ComparisonOperator,
qcPredicate :: QuantifiedComparisonPredicate,
qcQuery :: Select }
| InExpr InFlag (ScalarExprBase n) InPredicateValue
-- | ExistsSubQuery Select
-- | UniqueSubQuery Select
-- | ScalarSubQuery Select
| BooleanOperatorExpr (ScalarExprBase n) BoolOp (ScalarExprBase n)
| ExistsExpr Select
deriving (Show, Eq, Generic, NFData)
instance (Hashable n, Eq n) => Hashable (ScalarExprBase n)
data BoolOp = AndOp | OrOp
deriving (Eq, Show, Generic, NFData)
deriving Serialise via WineryVariant BoolOp
deriving Hashable
data InPredicateValue = InList [ScalarExpr] | InQueryExpr Select | InScalarExpr ScalarExpr
deriving (Eq, Show, Generic, NFData)
deriving Serialise via WineryVariant InPredicateValue
deriving Hashable
newtype GroupByExpr = GroupByExpr ProjectionScalarExpr
deriving (Show, Eq, Generic)
deriving Serialise via WineryVariant GroupByExpr
deriving newtype Hashable
deriving newtype NFData
newtype HavingExpr = HavingExpr ProjectionScalarExpr
deriving (Show, Eq, Generic)
deriving Serialise via WineryVariant HavingExpr
deriving newtype Hashable
deriving newtype NFData
data SortExpr = SortExpr ScalarExpr (Maybe Direction) (Maybe NullsOrder)
deriving (Show, Eq, Generic, NFData)
deriving Serialise via WineryVariant SortExpr
deriving Hashable
data Direction = Ascending | Descending
deriving (Show, Eq, Generic, NFData)
deriving Serialise via WineryVariant Direction
deriving Hashable
data NullsOrder = NullsFirst | NullsLast
deriving (Show, Eq, Generic, NFData)
deriving Serialise via WineryVariant NullsOrder
deriving Hashable
data JoinType = InnerJoin | RightOuterJoin | LeftOuterJoin | FullOuterJoin | CrossJoin | NaturalJoin
deriving (Show, Eq, Generic, NFData)
deriving Serialise via WineryVariant JoinType
data JoinCondition = JoinOn JoinOnCondition | JoinUsing [UnqualifiedColumnName]
deriving (Show, Eq, Generic, NFData)
deriving Serialise via WineryVariant JoinCondition
deriving Hashable
newtype JoinOnCondition = JoinOnCondition ScalarExpr
deriving (Show, Eq, Generic)
deriving Serialise via WineryVariant JoinOnCondition
deriving newtype NFData
deriving newtype Hashable
newtype ColumnProjectionName = ColumnProjectionName [ProjectionName] --dot-delimited reference
deriving (Show, Eq, Ord, Generic)
deriving Serialise via WineryVariant ColumnProjectionName
deriving newtype NFData
deriving newtype Hashable
data ProjectionName = ProjectionName Text | Asterisk
deriving (Show, Eq, Ord, Generic, NFData)
deriving Serialise via WineryVariant ProjectionName
deriving Hashable
newtype ColumnName = ColumnName [Text]
deriving (Show, Eq, Ord, Generic)
deriving Serialise via WineryVariant ColumnName
deriving newtype Hashable
deriving newtype NFData
newtype UnqualifiedColumnName = UnqualifiedColumnName Text
deriving (Show, Eq, Ord, Generic)
deriving Serialise via WineryVariant UnqualifiedColumnName
deriving newtype (Hashable, NFData)
newtype TableName = TableName [Text]
deriving (Show, Eq, Ord, Generic)
deriving Serialise via WineryVariant TableName
deriving newtype (Hashable, NFData)
newtype OperatorName = OperatorName [Text]
deriving (Show, Eq, Ord, Generic)
deriving Serialise via WineryVariant OperatorName
deriving newtype NFData
instance Hashable OperatorName
newtype ColumnAlias = ColumnAlias { unColumnAlias :: Text }
deriving (Show, Eq, Ord, Generic)
deriving Serialise via WineryVariant ColumnAlias
deriving newtype NFData
deriving newtype Hashable
newtype TableAlias = TableAlias { unTableAlias :: Text }
deriving (Show, Eq, Ord, Generic)
deriving Serialise via WineryVariant TableAlias
deriving newtype (Monoid, Semigroup, NFData)
deriving newtype Hashable
newtype FuncName = FuncName [Text]
deriving (Show, Eq, Generic, Ord)
deriving Serialise via WineryVariant FuncName
deriving newtype NFData
instance Hashable FuncName
data Distinctness = Distinct | All
deriving (Show, Eq, Generic, NFData)
deriving Serialise via WineryVariant Distinctness
instance Hashable Distinctness
newtype RestrictionExpr = RestrictionExpr ScalarExpr
deriving (Show, Eq, Generic)
deriving Serialise via WineryVariant RestrictionExpr
deriving newtype NFData
deriving newtype Hashable
data TableExpr =
TableExpr { fromClause :: [TableRef],
whereClause :: Maybe RestrictionExpr,
groupByClause :: [GroupByExpr],
havingClause :: Maybe HavingExpr,
orderByClause :: [SortExpr],
limitClause :: Maybe Integer,
offsetClause :: Maybe Integer
}
deriving (Show, Eq, Generic, NFData)
deriving Serialise via WineryRecord TableExpr
deriving Hashable
emptyTableExpr :: TableExpr
emptyTableExpr = TableExpr { fromClause = [],
whereClause = Nothing,
groupByClause = [],
havingClause = Nothing,
orderByClause = [],
limitClause = Nothing,
offsetClause = Nothing }
makeBaseFunctor ''ScalarExprBase