{-# LANGUAGE CPP #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE CPP #-}
module Database.Beam.Query.Combinators
(
coalesce_, fromMaybe_, position_
, charLength_, octetLength_, bitLength_
, currentTimestamp_
, lower_, upper_
, trim_
, if_, then_, else_
, then_'
, (<-.), current_
, HaskellLiteralForQExpr
, SqlValable(..), SqlValableTable
, default_
, all_, values_
, allFromView_, join_, join_'
, guard_, guard_', filter_, filter_'
, related_, relatedBy_, relatedBy_'
, leftJoin_, leftJoin_'
, perhaps_, outerJoin_, outerJoin_'
, subselect_, references_
, nub_
, SqlJustable(..)
, SqlDeconstructMaybe(..)
, SqlOrderable
, QIfCond, QIfElse
, (<|>.)
, limit_, offset_
, as_
, exists_, unique_, distinct_, subquery_
, union_, unionAll_
, intersect_, intersectAll_
, except_, exceptAll_
, over_, frame_, bounds_, unbounded_, nrows_, fromBound_
, noBounds_, noOrder_, noPartition_
, partitionBy_, orderPartitionBy_, withWindow_
, orderBy_, asc_, desc_, nullsFirst_, nullsLast_
) where
import Database.Beam.Backend.Types
import Database.Beam.Backend.SQL
import Database.Beam.Query.Internal
import Database.Beam.Query.Ord
import Database.Beam.Query.Operator
import Database.Beam.Query.Types
import Database.Beam.Schema.Tables
import Control.Monad.Identity
import Control.Monad.Free
import Control.Applicative
#if !MIN_VERSION_base(4, 11, 0)
import Control.Monad.Writer hiding ((<>))
import Data.Semigroup
#endif
import Data.Maybe
import Data.Proxy
import Data.Time (LocalTime)
import GHC.Generics
all_ :: ( Database be db, BeamSqlBackend be )
=> DatabaseEntity be db (TableEntity table)
-> Q be db s (table (QExpr be s))
all_ (DatabaseEntity dt@(DatabaseTable {})) =
Q $ liftF (QAll (\_ -> fromTable (tableNamed (tableName (dbTableSchema dt) (dbTableCurrentName dt))) . Just . (,Nothing))
(tableFieldsToExpressions (dbTableSettings dt))
(\_ -> Nothing) snd)
allFromView_ :: ( Database be db, Beamable table
, BeamSqlBackend be )
=> DatabaseEntity be db (ViewEntity table)
-> Q be db s (table (QExpr be s))
allFromView_ (DatabaseEntity vw) =
Q $ liftF (QAll (\_ -> fromTable (tableNamed (tableName (dbViewSchema vw) (dbViewCurrentName vw))) . Just . (,Nothing))
(tableFieldsToExpressions (dbViewSettings vw))
(\_ -> Nothing) snd)
values_ :: forall be db s a
. ( Projectible be a
, BeamSqlBackend be )
=> [ a ] -> Q be db s a
values_ rows =
Q $ liftF (QAll (\tblPfx -> fromTable (tableFromValues (map (\row -> project (Proxy @be) row tblPfx) rows)) . Just . (,Just fieldNames))
(\tblNm' -> fst $ mkFieldNames (qualifiedField tblNm'))
(\_ -> Nothing) snd)
where
fieldNames = snd $ mkFieldNames @be @a unqualifiedField
join_ :: ( Database be db, Table table, BeamSqlBackend be )
=> DatabaseEntity be db (TableEntity table)
-> (table (QExpr be s) -> QExpr be s Bool)
-> Q be db s (table (QExpr be s))
join_ tbl mkOn = join_' tbl (sqlBool_ . mkOn)
join_' :: ( Database be db, Table table, BeamSqlBackend be )
=> DatabaseEntity be db (TableEntity table)
-> (table (QExpr be s) -> QExpr be s SqlBool)
-> Q be db s (table (QExpr be s))
join_' (DatabaseEntity tbl@(DatabaseTable {})) mkOn =
Q $ liftF (QAll (\_ -> fromTable (tableNamed (tableName (dbTableSchema tbl) (dbTableCurrentName tbl))) . Just . (, Nothing))
(tableFieldsToExpressions (dbTableSettings tbl))
(\tbl' -> let QExpr on = mkOn tbl' in Just on) snd)
perhaps_ :: forall s r be db.
( Projectible be r, BeamSqlBackend be
, ThreadRewritable (QNested s) r
, Retaggable (QExpr be s) (WithRewrittenThread (QNested s) s r) )
=> Q be db (QNested s) r
-> Q be db s (Retag Nullable (WithRewrittenThread (QNested s) s r))
perhaps_ (Q sub) =
Q $ liftF (QArbitraryJoin
sub leftJoin
(\_ -> Nothing)
(\r -> retag (\(Columnar' (QExpr e) :: Columnar' (QExpr be s) a) ->
Columnar' (QExpr e) :: Columnar' (Nullable (QExpr be s)) a) $
rewriteThread (Proxy @s) r))
outerJoin_ :: forall s a b be db.
( BeamSqlBackend be, BeamSqlBackendSupportsOuterJoin be
, Projectible be a, Projectible be b
, ThreadRewritable (QNested s) a, ThreadRewritable (QNested s) b
, Retaggable (QExpr be s) (WithRewrittenThread (QNested s) s a)
, Retaggable (QExpr be s) (WithRewrittenThread (QNested s) s b)
)
=> Q be db (QNested s) a
-> Q be db (QNested s) b
-> ( (WithRewrittenThread (QNested s) s a, WithRewrittenThread (QNested s) s b) -> QExpr be s Bool )
-> Q be db s ( Retag Nullable (WithRewrittenThread (QNested s) s a)
, Retag Nullable (WithRewrittenThread (QNested s) s b) )
outerJoin_ a b on_ = outerJoin_' a b (sqlBool_ . on_)
outerJoin_' :: forall s a b be db.
( BeamSqlBackend be, BeamSqlBackendSupportsOuterJoin be
, Projectible be a, Projectible be b
, ThreadRewritable (QNested s) a, ThreadRewritable (QNested s) b
, Retaggable (QExpr be s) (WithRewrittenThread (QNested s) s a)
, Retaggable (QExpr be s) (WithRewrittenThread (QNested s) s b)
)
=> Q be db (QNested s) a
-> Q be db (QNested s) b
-> ( (WithRewrittenThread (QNested s) s a, WithRewrittenThread (QNested s) s b) -> QExpr be s SqlBool )
-> Q be db s ( Retag Nullable (WithRewrittenThread (QNested s) s a)
, Retag Nullable (WithRewrittenThread (QNested s) s b) )
outerJoin_' (Q a) (Q b) on_ =
Q $ liftF (QTwoWayJoin a b outerJoin
(\(a', b') ->
let QExpr e = on_ (rewriteThread (Proxy @s) a', rewriteThread (Proxy @s) b')
in Just e)
(\(a', b') ->
let retag' :: (ThreadRewritable (QNested s) x, Retaggable (QExpr be s) (WithRewrittenThread (QNested s) s x))
=> x -> Retag Nullable (WithRewrittenThread (QNested s) s x)
retag' = retag (\(Columnar' (QExpr e) :: Columnar' (QExpr be s) x) ->
Columnar' (QExpr e) :: Columnar' (Nullable (QExpr be s)) x) .
rewriteThread (Proxy @s)
in ( retag' a', retag' b' )))
leftJoin_ :: forall s r be db.
( BeamSqlBackend be, Projectible be r
, ThreadRewritable (QNested s) r
, Retaggable (QExpr be s) (WithRewrittenThread (QNested s) s r) )
=> Q be db (QNested s) r
-> (WithRewrittenThread (QNested s) s r -> QExpr be s Bool)
-> Q be db s (Retag Nullable (WithRewrittenThread (QNested s) s r))
leftJoin_ sub on_ = leftJoin_' sub (sqlBool_ . on_)
leftJoin_' :: forall s r be db.
( BeamSqlBackend be, Projectible be r
, ThreadRewritable (QNested s) r
, Retaggable (QExpr be s) (WithRewrittenThread (QNested s) s r) )
=> Q be db (QNested s) r
-> (WithRewrittenThread (QNested s) s r -> QExpr be s SqlBool)
-> Q be db s (Retag Nullable (WithRewrittenThread (QNested s) s r))
leftJoin_' (Q sub) on_ =
Q $ liftF (QArbitraryJoin
sub leftJoin
(\r -> let QExpr e = on_ (rewriteThread (Proxy @s) r) in Just e)
(\r -> retag (\(Columnar' (QExpr e) :: Columnar' (QExpr be s) a) ->
Columnar' (QExpr e) :: Columnar' (Nullable (QExpr be s)) a) $
rewriteThread (Proxy @s) r))
subselect_ :: forall s r be db.
( ThreadRewritable (QNested s) r
, Projectible be r )
=> Q be db (QNested s) r
-> Q be db s (WithRewrittenThread (QNested s) s r)
subselect_ (Q q') =
Q (liftF (QSubSelect q' (rewriteThread (Proxy @s))))
guard_ :: forall be db s
. BeamSqlBackend be
=> QExpr be s Bool -> Q be db s ()
guard_ = guard_' . sqlBool_
guard_' :: forall be db s
. BeamSqlBackend be
=> QExpr be s SqlBool -> Q be db s ()
guard_' (QExpr guardE') = Q (liftF (QGuard guardE' ()))
filter_ :: forall r be db s
. BeamSqlBackend be
=> (r -> QExpr be s Bool)
-> Q be db s r -> Q be db s r
filter_ mkExpr clause = clause >>= \x -> guard_ (mkExpr x) >> pure x
filter_' :: forall r be db s
. BeamSqlBackend be
=> (r -> QExpr be s SqlBool)
-> Q be db s r -> Q be db s r
filter_' mkExpr clause = clause >>= \x -> guard_' (mkExpr x) >> pure x
related_ :: forall be db rel s
. ( Database be db, Table rel, BeamSqlBackend be
, HasTableEquality be (PrimaryKey rel)
)
=> DatabaseEntity be db (TableEntity rel)
-> PrimaryKey rel (QExpr be s)
-> Q be db s (rel (QExpr be s))
related_ relTbl relKey =
join_ relTbl (\rel -> relKey ==. primaryKey rel)
relatedBy_ :: forall be db rel s
. ( Database be db, Table rel, BeamSqlBackend be )
=> DatabaseEntity be db (TableEntity rel)
-> (rel (QExpr be s) -> QExpr be s Bool)
-> Q be db s (rel (QExpr be s))
relatedBy_ = join_
relatedBy_' :: forall be db rel s
. ( Database be db, Table rel, BeamSqlBackend be )
=> DatabaseEntity be db (TableEntity rel)
-> (rel (QExpr be s) -> QExpr be s SqlBool)
-> Q be db s (rel (QExpr be s))
relatedBy_' = join_'
references_ :: ( Table t, BeamSqlBackend be
, HasTableEquality be (PrimaryKey t) )
=> PrimaryKey t (QGenExpr ctxt be s) -> t (QGenExpr ctxt be s) -> QGenExpr ctxt be s Bool
references_ fk tbl = fk ==. pk tbl
nub_ :: ( BeamSqlBackend be, Projectible be r )
=> Q be db s r -> Q be db s r
nub_ (Q sub) = Q $ liftF (QDistinct (\_ _ -> setQuantifierDistinct) sub id)
limit_ :: forall s a be db
. ( Projectible be a
, ThreadRewritable (QNested s) a )
=> Integer -> Q be db (QNested s) a -> Q be db s (WithRewrittenThread (QNested s) s a)
limit_ limit' (Q q) =
Q (liftF (QLimit limit' q (rewriteThread (Proxy @s))))
offset_ :: forall s a be db
. ( Projectible be a
, ThreadRewritable (QNested s) a )
=> Integer -> Q be db (QNested s) a -> Q be db s (WithRewrittenThread (QNested s) s a)
offset_ offset' (Q q) =
Q (liftF (QOffset offset' q (rewriteThread (Proxy @s))))
exists_ :: ( BeamSqlBackend be, HasQBuilder be, Projectible be a)
=> Q be db s a -> QExpr be s Bool
exists_ q = QExpr (\tbl -> existsE (buildSqlQuery tbl q))
unique_ :: ( BeamSqlBackend be, HasQBuilder be, Projectible be a)
=> Q be db s a -> QExpr be s Bool
unique_ q = QExpr (\tbl -> uniqueE (buildSqlQuery tbl q))
distinct_ :: ( BeamSqlBackend be, BeamSql99ExpressionBackend be, HasQBuilder be, Projectible be a)
=> Q be db s a -> QExpr be s Bool
distinct_ q = QExpr (\tbl -> distinctE (buildSqlQuery tbl q))
subquery_ :: ( BeamSqlBackend be, HasQBuilder be, Projectible be (QExpr be s a) )
=> Q be db s (QExpr be s a)
-> QGenExpr ctxt be s a
subquery_ q =
QExpr (\tbl -> subqueryE (buildSqlQuery tbl q))
charLength_ :: ( BeamSqlBackend be, BeamSqlBackendIsString be text )
=> QGenExpr context be s text -> QGenExpr context be s Int
charLength_ (QExpr s) = QExpr (charLengthE <$> s)
octetLength_ :: ( BeamSqlBackend be, BeamSqlBackendIsString be text )
=> QGenExpr context be s text -> QGenExpr context be s Int
octetLength_ (QExpr s) = QExpr (octetLengthE <$> s)
bitLength_ :: BeamSqlBackend be
=> QGenExpr context be s SqlBitString -> QGenExpr context be s Int
bitLength_ (QExpr x) = QExpr (bitLengthE <$> x)
currentTimestamp_ :: BeamSqlBackend be => QGenExpr ctxt be s LocalTime
currentTimestamp_ = QExpr (pure currentTimestampE)
position_ :: ( BeamSqlBackendIsString be text
, BeamSqlBackend be, Integral b )
=> QExpr be s text -> QExpr be s text -> QExpr be s b
position_ (QExpr needle) (QExpr haystack) =
QExpr (liftA2 likeE needle haystack)
lower_ :: ( BeamSqlBackendIsString be text
, BeamSqlBackend be )
=> QGenExpr context be s text -> QGenExpr context be s text
lower_ (QExpr s) = QExpr (lowerE <$> s)
upper_ :: ( BeamSqlBackendIsString be text
, BeamSqlBackend be )
=> QGenExpr context be s text -> QGenExpr context be s text
upper_ (QExpr s) = QExpr (upperE <$> s)
trim_ :: ( BeamSqlBackendIsString be text
, BeamSqlBackend be )
=> QGenExpr context be s text -> QGenExpr context be s text
trim_ (QExpr s) = QExpr (trimE <$> s)
allE :: BeamSqlBackend be
=> [ QGenExpr context be s Bool ] -> QGenExpr context be s Bool
allE es = fromMaybe (QExpr (pure (valueE (sqlValueSyntax True)))) $
foldl (\expr x ->
Just $ maybe x (\e -> e &&. x) expr)
Nothing es
current_ :: BeamSqlBackend be => QField s ty -> QExpr be s ty
current_ (QField False _ nm) = QExpr (pure (fieldE (unqualifiedField nm)))
current_ (QField True tbl nm) = QExpr (pure (fieldE (qualifiedField tbl nm)))
infix 4 <-.
class BeamSqlBackend be =>
SqlUpdatable be s lhs rhs | rhs -> be, lhs -> s
, rhs -> s, lhs s be -> rhs
, rhs -> lhs where
(<-.) :: lhs
-> rhs
-> QAssignment be s
instance BeamSqlBackend be => SqlUpdatable be s (QField s a) (QExpr be s a) where
QField _ _ nm <-. QExpr expr =
QAssignment [(unqualifiedField nm, expr "t")]
instance (BeamSqlBackend be, Beamable tbl) => SqlUpdatable be s (tbl (QField s)) (tbl (QExpr be s)) where
lhs <-. rhs =
QAssignment $
allBeamValues (\(Columnar' (Const assignments)) -> assignments) $
runIdentity $
zipBeamFieldsM (\(Columnar' (QField _ _ f) :: Columnar' (QField s) t) (Columnar' (QExpr e)) ->
pure (Columnar' (Const (unqualifiedField f, e "t")) :: Columnar' (Const (BeamSqlBackendFieldNameSyntax be, BeamSqlBackendExpressionSyntax be)) t)) lhs rhs
instance (BeamSqlBackend be, Beamable tbl) => SqlUpdatable be s (tbl (Nullable (QField s))) (tbl (Nullable (QExpr be s))) where
lhs <-. rhs =
let lhs' = changeBeamRep (\(Columnar' (QField q tblName fieldName') :: Columnar' (Nullable (QField s)) a) ->
Columnar' (QField q tblName fieldName') :: Columnar' (QField s) a) lhs
rhs' = changeBeamRep (\(Columnar' (QExpr e) :: Columnar' (Nullable (QExpr be s)) a) ->
Columnar' (QExpr e) :: Columnar' (QExpr be s) a) rhs
in lhs' <-. rhs'
union_ :: forall be db s a
. ( BeamSqlBackend be, Projectible be a
, ThreadRewritable (QNested s) a )
=> Q be db (QNested s) a -> Q be db (QNested s) a
-> Q be db s (WithRewrittenThread (QNested s) s a)
union_ (Q a) (Q b) = Q (liftF (QSetOp (unionTables False) a b (rewriteThread (Proxy @s))))
unionAll_ :: forall be db s a.
( BeamSqlBackend be, Projectible be a
, ThreadRewritable (QNested s) a)
=> Q be db (QNested s) a -> Q be db (QNested s) a
-> Q be db s (WithRewrittenThread (QNested s) s a)
unionAll_ (Q a) (Q b) = Q (liftF (QSetOp (unionTables True) a b (rewriteThread (Proxy @s))))
intersect_ :: forall be db s a.
( BeamSqlBackend be, Projectible be a
, ThreadRewritable (QNested s) a)
=> Q be db (QNested s) a -> Q be db (QNested s) a
-> Q be db s (WithRewrittenThread (QNested s) s a)
intersect_ (Q a) (Q b) = Q (liftF (QSetOp (intersectTables False) a b (rewriteThread (Proxy @s))))
intersectAll_ :: forall be db s a.
( BeamSqlBackend be, Projectible be a
, ThreadRewritable (QNested s) a)
=> Q be db (QNested s) a -> Q be db (QNested s) a
-> Q be db s (WithRewrittenThread (QNested s) s a)
intersectAll_ (Q a) (Q b) = Q (liftF (QSetOp (intersectTables True) a b (rewriteThread (Proxy @s))))
except_ :: forall be db s a.
( BeamSqlBackend be, Projectible be a
, ThreadRewritable (QNested s) a)
=> Q be db (QNested s) a -> Q be db (QNested s) a
-> Q be db s (WithRewrittenThread (QNested s) s a)
except_ (Q a) (Q b) = Q (liftF (QSetOp (exceptTable False) a b (rewriteThread (Proxy @s))))
exceptAll_ :: forall be db s a.
( BeamSqlBackend be, Projectible be a
, ThreadRewritable (QNested s) a)
=> Q be db (QNested s) a -> Q be db (QNested s) a
-> Q be db s (WithRewrittenThread (QNested s) s a)
exceptAll_ (Q a) (Q b) = Q (liftF (QSetOp (exceptTable True) a b (rewriteThread (Proxy @s))))
as_ :: forall a ctxt be s. QGenExpr ctxt be s a -> QGenExpr ctxt be s a
as_ = id
type family HaskellLiteralForQExpr x = a
type instance HaskellLiteralForQExpr (QGenExpr context be s a) = a
type instance HaskellLiteralForQExpr (table (QGenExpr context be s)) = table Identity
type instance HaskellLiteralForQExpr (table (Nullable f)) = HaskellLiteralForQExpr_AddNullable (HaskellLiteralForQExpr (table f))
type family HaskellLiteralForQExpr_AddNullable x = a
type instance HaskellLiteralForQExpr_AddNullable (tbl f) = tbl (Nullable f)
type SqlValableTable be table =
( Beamable table
, FieldsFulfillConstraint (HasSqlValueSyntax (BeamSqlBackendValueSyntax be)) table )
class SqlValable a where
val_ :: HaskellLiteralForQExpr a -> a
instance ( BeamSqlBackendCanSerialize be a, BeamSqlBackend be ) =>
SqlValable (QGenExpr ctxt be s a) where
val_ = QExpr . pure . valueE . sqlValueSyntax
instance ( Beamable table, BeamSqlBackend be
, FieldsFulfillConstraint (BeamSqlBackendCanSerialize be) table ) =>
SqlValable (table (QGenExpr ctxt be s)) where
val_ tbl =
let fields :: table (WithConstraint (BeamSqlBackendCanSerialize be))
fields = to (gWithConstrainedFields (Proxy @(BeamSqlBackendCanSerialize be))
(Proxy @(Rep (table Exposed))) (from tbl))
in changeBeamRep (\(Columnar' (WithConstraint x :: WithConstraint (BeamSqlBackendCanSerialize be) x)) ->
Columnar' (QExpr (pure (valueE (sqlValueSyntax x))))) fields
instance ( Beamable table, BeamSqlBackend be
, FieldsFulfillConstraintNullable (BeamSqlBackendCanSerialize be) table ) =>
SqlValable (table (Nullable (QGenExpr ctxt be s))) where
val_ tbl =
let fields :: table (Nullable (WithConstraint (BeamSqlBackendCanSerialize be)))
fields = to (gWithConstrainedFields (Proxy @(BeamSqlBackendCanSerialize be))
(Proxy @(Rep (table (Nullable Exposed)))) (from tbl))
in changeBeamRep (\(Columnar' (WithConstraint x :: WithConstraint (BeamSqlBackendCanSerialize be) (Maybe x))) ->
Columnar' (QExpr (pure (valueE (sqlValueSyntax x))))) fields
default_ :: BeamSqlBackend be => QGenExpr ctxt be s a
default_ = QExpr (pure defaultE)
noBounds_ :: QFrameBounds be
noBounds_ = QFrameBounds Nothing
fromBound_ :: BeamSql2003ExpressionBackend be
=> QFrameBound be -> QFrameBounds be
fromBound_ start = bounds_ start Nothing
bounds_ :: BeamSql2003ExpressionBackend be
=> QFrameBound be
-> Maybe (QFrameBound be)
-> QFrameBounds be
bounds_ (QFrameBound start) end =
QFrameBounds . Just $
fromToBoundSyntax start
(fmap (\(QFrameBound end') -> end') end)
unbounded_ :: BeamSql2003ExpressionBackend be => QFrameBound be
unbounded_ = QFrameBound unboundedSyntax
nrows_ :: BeamSql2003ExpressionBackend be
=> Int -> QFrameBound be
nrows_ x = QFrameBound (nrowsBoundSyntax x)
noPartition_ :: Maybe (QExpr be s Int)
noPartition_ = Nothing
noOrder_ :: Maybe (QOrd be s Int)
noOrder_ = Nothing
partitionBy_, orderPartitionBy_ :: partition -> Maybe partition
partitionBy_ = Just
orderPartitionBy_ = Just
frame_ :: forall be ordering partition s
. ( BeamSql2003ExpressionBackend be
, SqlOrderable be ordering
, Projectible be partition )
=> Maybe partition
-> Maybe ordering
-> QFrameBounds be
-> QWindow be s
frame_ partition_ ordering_ (QFrameBounds bounds) =
QWindow $ \tblPfx ->
frameSyntax (case maybe [] (flip (project (Proxy @be)) tblPfx) partition_ of
[] -> Nothing
xs -> Just xs)
(case fmap (makeSQLOrdering (Proxy @be)) ordering_ of
Nothing -> Nothing
Just [] -> Nothing
Just xs -> Just (sequenceA xs tblPfx))
bounds
over_ :: BeamSql2003ExpressionBackend be
=> QAgg be s a -> QWindow be s -> QWindowExpr be s a
over_ (QExpr a) (QWindow frame) = QExpr (overE <$> a <*> frame)
withWindow_ :: forall window a s r be db
. ( ProjectibleWithPredicate WindowFrameContext be (WithExprContext (BeamSqlBackendWindowFrameSyntax' be)) window
, Projectible be r, Projectible be a
, ContextRewritable a
, ThreadRewritable (QNested s) (WithRewrittenContext a QValueContext) )
=> (r -> window)
-> (r -> window -> a)
-> Q be db (QNested s) r
-> Q be db s (WithRewrittenThread (QNested s) s (WithRewrittenContext a QValueContext))
withWindow_ mkWindow mkProjection (Q windowOver)=
Q (liftF (QWindowOver mkWindow mkProjection windowOver (rewriteThread (Proxy @s) . rewriteContext (Proxy @QValueContext))))
class SqlOrderable be a | a -> be where
makeSQLOrdering :: Proxy be -> a -> [ WithExprContext (BeamSqlBackendOrderingSyntax be) ]
instance SqlOrderable be (QOrd be s a) where
makeSQLOrdering _ (QOrd x) = [x]
instance SqlOrderable be a => SqlOrderable be [a] where
makeSQLOrdering be = concatMap (makeSQLOrdering be)
instance ( SqlOrderable be a, SqlOrderable be b ) => SqlOrderable be (a, b) where
makeSQLOrdering be (a, b) =
makeSQLOrdering be a <> makeSQLOrdering be b
instance ( SqlOrderable be a, SqlOrderable be b
, SqlOrderable be c ) => SqlOrderable be (a, b, c) where
makeSQLOrdering be (a, b, c) =
makeSQLOrdering be a <> makeSQLOrdering be b <> makeSQLOrdering be c
instance ( SqlOrderable be a, SqlOrderable be b
, SqlOrderable be c, SqlOrderable be d ) => SqlOrderable be (a, b, c, d) where
makeSQLOrdering be (a, b, c, d) =
makeSQLOrdering be a <> makeSQLOrdering be b <> makeSQLOrdering be c <> makeSQLOrdering be d
instance ( SqlOrderable be a, SqlOrderable be b
, SqlOrderable be c, SqlOrderable be d
, SqlOrderable be e ) => SqlOrderable be (a, b, c, d, e) where
makeSQLOrdering be (a, b, c, d, e) =
makeSQLOrdering be a <> makeSQLOrdering be b <> makeSQLOrdering be c <> makeSQLOrdering be d <>
makeSQLOrdering be e
instance ( SqlOrderable be a, SqlOrderable be b
, SqlOrderable be c, SqlOrderable be d
, SqlOrderable be e, SqlOrderable be f ) => SqlOrderable be (a, b, c, d, e, f) where
makeSQLOrdering be (a, b, c, d, e, f) =
makeSQLOrdering be a <> makeSQLOrdering be b <> makeSQLOrdering be c <> makeSQLOrdering be d <>
makeSQLOrdering be e <> makeSQLOrdering be f
instance ( SqlOrderable be a, SqlOrderable be b
, SqlOrderable be c, SqlOrderable be d
, SqlOrderable be e, SqlOrderable be f
, SqlOrderable be g ) => SqlOrderable be (a, b, c, d, e, f, g) where
makeSQLOrdering be (a, b, c, d, e, f, g) =
makeSQLOrdering be a <> makeSQLOrdering be b <> makeSQLOrdering be c <> makeSQLOrdering be d <>
makeSQLOrdering be e <> makeSQLOrdering be f <> makeSQLOrdering be g
instance ( SqlOrderable be a, SqlOrderable be b
, SqlOrderable be c, SqlOrderable be d
, SqlOrderable be e, SqlOrderable be f
, SqlOrderable be g, SqlOrderable be h ) => SqlOrderable be (a, b, c, d, e, f, g, h) where
makeSQLOrdering be (a, b, c, d, e, f, g, h) =
makeSQLOrdering be a <> makeSQLOrdering be b <> makeSQLOrdering be c <> makeSQLOrdering be d <>
makeSQLOrdering be e <> makeSQLOrdering be f <> makeSQLOrdering be g <> makeSQLOrdering be h
orderBy_ :: forall s a ordering be db
. ( Projectible be a, SqlOrderable be ordering
, ThreadRewritable (QNested s) a )
=> (a -> ordering) -> Q be db (QNested s) a -> Q be db s (WithRewrittenThread (QNested s) s a)
orderBy_ orderer (Q q) =
Q (liftF (QOrderBy (sequenceA . makeSQLOrdering (Proxy @be) . orderer) q (rewriteThread (Proxy @s))))
nullsFirst_ :: IsSql2003OrderingElementaryOLAPOperationsSyntax (BeamSqlBackendOrderingSyntax be)
=> QOrd be s a -> QOrd be s a
nullsFirst_ (QOrd e) = QOrd (nullsFirstOrdering <$> e)
nullsLast_ :: IsSql2003OrderingElementaryOLAPOperationsSyntax (BeamSqlBackendOrderingSyntax be)
=> QOrd be s a -> QOrd be s a
nullsLast_ (QOrd e) = QOrd (nullsLastOrdering <$> e)
asc_ :: forall be s a
. BeamSqlBackend be
=> QExpr be s a -> QOrd be s a
asc_ (QExpr e) = QOrd (ascOrdering <$> e)
desc_ :: forall be s a
. BeamSqlBackend be
=> QExpr be s a -> QOrd be s a
desc_ (QExpr e) = QOrd (descOrdering <$> e)
class SqlJustable a b | b -> a where
just_ :: a -> b
nothing_ :: b
instance BeamSqlBackend be =>
SqlJustable (QExpr be s a) (QExpr be s (Maybe a)) where
just_ (QExpr e) = QExpr e
nothing_ = QExpr (pure (valueE (sqlValueSyntax SqlNull)))
instance {-# OVERLAPPING #-} ( Table t, BeamSqlBackend be ) =>
SqlJustable (PrimaryKey t (QExpr be s)) (PrimaryKey t (Nullable (QExpr be s))) where
just_ = changeBeamRep (\(Columnar' q) -> Columnar' (just_ q))
nothing_ = changeBeamRep (\(Columnar' _) -> Columnar' nothing_) (primaryKey (tblSkeleton :: TableSkeleton t))
instance {-# OVERLAPPING #-} ( Table t, BeamSqlBackend be ) =>
SqlJustable (t (QExpr be s)) (t (Nullable (QExpr be s))) where
just_ = changeBeamRep (\(Columnar' q) -> Columnar' (just_ q))
nothing_ = changeBeamRep (\(Columnar' _) -> Columnar' nothing_) (tblSkeleton :: TableSkeleton t)
instance {-# OVERLAPPING #-} Table t => SqlJustable (PrimaryKey t Identity) (PrimaryKey t (Nullable Identity)) where
just_ = changeBeamRep (\(Columnar' q) -> Columnar' (Just q))
nothing_ = changeBeamRep (\(Columnar' _) -> Columnar' Nothing) (primaryKey (tblSkeleton :: TableSkeleton t))
instance {-# OVERLAPPING #-} Table t => SqlJustable (t Identity) (t (Nullable Identity)) where
just_ = changeBeamRep (\(Columnar' q) -> Columnar' (Just q))
nothing_ = changeBeamRep (\(Columnar' _) -> Columnar' Nothing) (tblSkeleton :: TableSkeleton t)
data QIfCond context be s a = QIfCond (QGenExpr context be s SqlBool) (QGenExpr context be s a)
newtype QIfElse context be s a = QIfElse (QGenExpr context be s a)
then_ :: QGenExpr context be s Bool -> QGenExpr context be s a -> QIfCond context be s a
then_ cond res = QIfCond (sqlBool_ cond) res
then_' :: QGenExpr context be s SqlBool -> QGenExpr context be s a -> QIfCond context be s a
then_' cond res = QIfCond cond res
else_ :: QGenExpr context be s a -> QIfElse context be s a
else_ = QIfElse
if_ :: BeamSqlBackend be
=> [ QIfCond context be s a ]
-> QIfElse context be s a
-> QGenExpr context be s a
if_ conds (QIfElse (QExpr elseExpr)) =
QExpr (\tbl -> caseE (map (\(QIfCond (QExpr cond) (QExpr res)) -> (cond tbl, res tbl)) conds) (elseExpr tbl))
coalesce_ :: BeamSqlBackend be
=> [ QGenExpr ctxt be s (Maybe a) ] -> QGenExpr ctxt be s a -> QGenExpr ctxt be s a
coalesce_ qs (QExpr onNull) =
QExpr $ do
onNull' <- onNull
coalesceE . (<> [onNull']) <$> mapM (\(QExpr q) -> q) qs
fromMaybe_ :: BeamSqlBackend be
=> QGenExpr ctxt be s a -> QGenExpr ctxt be s (Maybe a) -> QGenExpr ctxt be s a
fromMaybe_ onNull q = coalesce_ [q] onNull
class BeamSqlBackend be => SqlDeconstructMaybe be a nonNullA s | a s -> be, a -> nonNullA, a -> s, nonNullA -> s where
isJust_ :: a -> QGenExpr ctxt be s Bool
isNothing_ :: a -> QGenExpr ctxt be s Bool
maybe_ :: QGenExpr ctxt be s y -> (nonNullA -> QGenExpr ctxt be s y) -> a -> QGenExpr ctxt be s y
instance BeamSqlBackend be => SqlDeconstructMaybe be (QGenExpr ctxt be s (Maybe x)) (QGenExpr ctxt be s x) s where
isJust_ (QExpr x) = QExpr (isNotNullE <$> x)
isNothing_ (QExpr x) = QExpr (isNullE <$> x)
maybe_ (QExpr onNothing) onJust (QExpr e) =
let QExpr onJust' = onJust (QExpr e)
in QExpr (\tbl -> caseE [(isNotNullE (e tbl), onJust' tbl)] (onNothing tbl))
instance ( BeamSqlBackend be, Beamable t)
=> SqlDeconstructMaybe be (t (Nullable (QGenExpr ctxt be s))) (t (QGenExpr ctxt be s)) s where
isJust_ t = allE (allBeamValues (\(Columnar' e) -> isJust_ e) t)
isNothing_ t = allE (allBeamValues (\(Columnar' e) -> isNothing_ e) t)
maybe_ (QExpr onNothing) onJust tbl =
let QExpr onJust' = onJust (changeBeamRep (\(Columnar' (QExpr e)) -> Columnar' (QExpr e)) tbl)
QExpr cond = isJust_ tbl
in QExpr (\tblPfx -> caseE [(cond tblPfx, onJust' tblPfx)] (onNothing tblPfx))
infixl 3 <|>.
(<|>.) :: ( SqlJustable a (QGenExpr ctxt syntax s y)
, SqlDeconstructMaybe syntax (QGenExpr ctxt syntax s y) a s
)
=> QGenExpr ctxt syntax s y
-> QGenExpr ctxt syntax s y
-> QGenExpr ctxt syntax s y
l <|>. r = maybe_ r just_ l