{-# LANGUAGE OverloadedStrings #-}
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE DataKinds #-}
{-# LANGUAGE ConstraintKinds #-}
{-# LANGUAGE UndecidableInstances #-}
{-# LANGUAGE TypeOperators #-}
{-# LANGUAGE ExistentialQuantification #-}
{-# LANGUAGE TupleSections #-}
{-# LANGUAGE AllowAmbiguousTypes #-}
{-# LANGUAGE StandaloneDeriving #-}
{-# LANGUAGE DeriveFunctor #-}

module Database.MySQL.Hasqlator.Typed
  ( -- * Database Types
    Table(..), Field(..), Tbl(..), (@@), Nullable (..), JoinType (..),
    
    
    -- * Querying
    Query, 

    -- * Selectors
    Selector, sel, selMaybe,

    -- * Expressions
    Expression, SomeExpression, someExpr, Operator, 
    arg, argMaybe, nullable, cast, unsafeCast,
    op, fun1, fun2, fun3, (=.), (/=.), (>.), (<.), (>=.), (<=.), (&&.), (||.),
    substr, true_, false_,

    -- * Clauses
    from, fromSubQuery, innerJoin, leftJoin, joinSubQuery, leftJoinSubQuery,
    where_, groupBy_, having, orderBy, limit, limitOffset,

    -- * Insertion
    Insertor, insertValues, insertSelect, insertData, skipInsert, into,
    lensInto, insertOne, exprInto, Into,
    
    -- * imported from Database.MySQL.Hasqlator
    H.Getter, H.ToSql, H.FromSql, subQueryExpr, H.Command
  )
where
import Data.Text (Text)
import qualified Data.Text as Text
import Data.Coerce
import qualified Data.ByteString as StrictBS
import Data.Scientific
import Data.Word
import Data.Int
import Data.Time
import Data.String
import qualified Data.DList  as DList
import qualified Data.Map.Strict as Map
import Control.Monad.State
import Control.Monad.Reader
import GHC.Exts (Constraint)
import GHC.TypeLits as TL
import Data.Functor.Contravariant
import Control.Applicative
import qualified GHC.Generics as Generics (from, to)
import GHC.Generics hiding (from, Selector)
import qualified Database.MySQL.Hasqlator as H
import Data.Proxy

data Nullable = Nullable | NotNull
data JoinType = LeftJoined | InnerJoined

type family CheckInsertable (fieldNullable :: Nullable) fieldType a
            :: Constraint where
  CheckInsertable 'Nullable a (Maybe a) = ()
  CheckInsertable 'Nullable a a = ()
  CheckInsertable 'NotNull a a = ()
  CheckInsertable n t ft =
    TypeError ('TL.Text "Cannot insert value of type " ':<>:
               'ShowType t ':<>:
               'TL.Text " into " ':<>:
               'ShowType n ':<>:
               'TL.Text " field of type " ':<>:
               'ShowType ft)

type Insertable nullable field a =
  (CheckInsertable nullable field a, H.ToSql a)

-- | check if field can be used in nullable context
type family CheckExprNullable (expr :: Nullable) (context :: Nullable)
     :: Constraint
  where
    CheckExprNullable 'Nullable 'Nullable = ()
    CheckExprNullable 'Nullable 'NotNull =
      TypeError ('Text "A nullable expression can be only used in a nullable context")
    -- a NotNull expressions can be used in both contexts
    CheckExprNullable 'NotNull _ = ()

-- | check if a field is nullable after being joined
type family JoinNullable (leftJoined :: JoinType) (field :: Nullable)
     :: Nullable
  where
    JoinNullable 'InnerJoined nullable = nullable
    JoinNullable 'LeftJoined _ = 'Nullable

data Field (table :: Symbol) database (nullable :: Nullable) a =
  Field Text Text
 
newtype Expression (nullable :: Nullable) a =
  Expression {Expression nullable a -> QueryInner QueryBuilder
runExpression :: QueryInner H.QueryBuilder }

-- | An expression of any type
newtype SomeExpression =
  SomeExpression { SomeExpression -> QueryInner QueryBuilder
runSomeExpression :: QueryInner H.QueryBuilder }

newtype Selector a = Selector (QueryInner (H.Selector a))

instance Functor Selector where
  fmap :: (a -> b) -> Selector a -> Selector b
fmap a -> b
f (Selector QueryInner (Selector a)
s) = QueryInner (Selector b) -> Selector b
forall a. QueryInner (Selector a) -> Selector a
Selector ((a -> b) -> Selector a -> Selector b
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap a -> b
f (Selector a -> Selector b)
-> QueryInner (Selector a) -> QueryInner (Selector b)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> QueryInner (Selector a)
s)
instance Applicative Selector where
  pure :: a -> Selector a
pure a
x = QueryInner (Selector a) -> Selector a
forall a. QueryInner (Selector a) -> Selector a
Selector (QueryInner (Selector a) -> Selector a)
-> QueryInner (Selector a) -> Selector a
forall a b. (a -> b) -> a -> b
$ Selector a -> QueryInner (Selector a)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Selector a -> QueryInner (Selector a))
-> Selector a -> QueryInner (Selector a)
forall a b. (a -> b) -> a -> b
$ a -> Selector a
forall (f :: * -> *) a. Applicative f => a -> f a
pure a
x
  Selector QueryInner (Selector (a -> b))
a <*> :: Selector (a -> b) -> Selector a -> Selector b
<*> Selector QueryInner (Selector a)
b = QueryInner (Selector b) -> Selector b
forall a. QueryInner (Selector a) -> Selector a
Selector (QueryInner (Selector b) -> Selector b)
-> QueryInner (Selector b) -> Selector b
forall a b. (a -> b) -> a -> b
$ (Selector (a -> b) -> Selector a -> Selector b)
-> QueryInner (Selector (a -> b))
-> QueryInner (Selector a)
-> QueryInner (Selector b)
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 Selector (a -> b) -> Selector a -> Selector b
forall (f :: * -> *) a b. Applicative f => f (a -> b) -> f a -> f b
(<*>) QueryInner (Selector (a -> b))
a QueryInner (Selector a)
b
instance Semigroup a => Semigroup (Selector a) where
  Selector QueryInner (Selector a)
a <> :: Selector a -> Selector a -> Selector a
<> Selector QueryInner (Selector a)
b = QueryInner (Selector a) -> Selector a
forall a. QueryInner (Selector a) -> Selector a
Selector (QueryInner (Selector a) -> Selector a)
-> QueryInner (Selector a) -> Selector a
forall a b. (a -> b) -> a -> b
$ (Selector a -> Selector a -> Selector a)
-> QueryInner (Selector a)
-> QueryInner (Selector a)
-> QueryInner (Selector a)
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 Selector a -> Selector a -> Selector a
forall a. Semigroup a => a -> a -> a
(<>) QueryInner (Selector a)
a QueryInner (Selector a)
b
instance Monoid a => Monoid (Selector a) where
  mempty :: Selector a
mempty = QueryInner (Selector a) -> Selector a
forall a. QueryInner (Selector a) -> Selector a
Selector (QueryInner (Selector a) -> Selector a)
-> QueryInner (Selector a) -> Selector a
forall a b. (a -> b) -> a -> b
$ Selector a -> QueryInner (Selector a)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Selector a
forall a. Monoid a => a
mempty

-- | Remove types of an expression
someExpr :: Expression nullable a -> SomeExpression
someExpr :: Expression nullable a -> SomeExpression
someExpr = Expression nullable a -> SomeExpression
coerce

instance IsString (Expression nullable Text) where
  fromString :: String -> Expression nullable Text
fromString = Text -> Expression nullable Text
forall a (nullable :: Nullable).
ToSql a =>
a -> Expression nullable a
arg (Text -> Expression nullable Text)
-> (String -> Text) -> String -> Expression nullable Text
forall b c a. (b -> c) -> (a -> b) -> a -> c
. String -> Text
forall a. IsString a => String -> a
fromString

instance Semigroup (Expression nullable Text) where
  <> :: Expression nullable Text
-> Expression nullable Text -> Expression nullable Text
(<>) = (QueryBuilder -> QueryBuilder -> QueryBuilder)
-> Expression nullable Text
-> Expression nullable Text
-> Expression nullable Text
forall (nullable :: Nullable) a b c.
(QueryBuilder -> QueryBuilder -> QueryBuilder)
-> Expression nullable a
-> Expression nullable b
-> Expression nullable c
fun2 QueryBuilder -> QueryBuilder -> QueryBuilder
(H.++.)

instance Monoid (Expression nullable Text) where
  mempty :: Expression nullable Text
mempty = Text -> Expression nullable Text
forall a (nullable :: Nullable).
ToSql a =>
a -> Expression nullable a
arg Text
""

instance (Num n, H.ToSql n) => Num (Expression nullable n) where
  + :: Expression nullable n
-> Expression nullable n -> Expression nullable n
(+) = (QueryBuilder -> QueryBuilder -> QueryBuilder) -> Operator n n n
forall a b c.
(QueryBuilder -> QueryBuilder -> QueryBuilder) -> Operator a b c
op QueryBuilder -> QueryBuilder -> QueryBuilder
(H.+.)
  (-) = (QueryBuilder -> QueryBuilder -> QueryBuilder) -> Operator n n n
forall a b c.
(QueryBuilder -> QueryBuilder -> QueryBuilder) -> Operator a b c
op QueryBuilder -> QueryBuilder -> QueryBuilder
(H.-.)
  * :: Expression nullable n
-> Expression nullable n -> Expression nullable n
(*) = (QueryBuilder -> QueryBuilder -> QueryBuilder) -> Operator n n n
forall a b c.
(QueryBuilder -> QueryBuilder -> QueryBuilder) -> Operator a b c
op QueryBuilder -> QueryBuilder -> QueryBuilder
(H.*.)
  negate :: Expression nullable n -> Expression nullable n
negate = (QueryBuilder -> QueryBuilder)
-> Expression nullable n -> Expression nullable n
forall (nullable :: Nullable) a b.
(QueryBuilder -> QueryBuilder)
-> Expression nullable a -> Expression nullable b
fun1 QueryBuilder -> QueryBuilder
H.negate_
  abs :: Expression nullable n -> Expression nullable n
abs = (QueryBuilder -> QueryBuilder)
-> Expression nullable n -> Expression nullable n
forall (nullable :: Nullable) a b.
(QueryBuilder -> QueryBuilder)
-> Expression nullable a -> Expression nullable b
fun1 QueryBuilder -> QueryBuilder
H.abs_
  signum :: Expression nullable n -> Expression nullable n
signum = (QueryBuilder -> QueryBuilder)
-> Expression nullable n -> Expression nullable n
forall (nullable :: Nullable) a b.
(QueryBuilder -> QueryBuilder)
-> Expression nullable a -> Expression nullable b
fun1 QueryBuilder -> QueryBuilder
H.signum_
  fromInteger :: Integer -> Expression nullable n
fromInteger = n -> Expression nullable n
forall a (nullable :: Nullable).
ToSql a =>
a -> Expression nullable a
arg (n -> Expression nullable n)
-> (Integer -> n) -> Integer -> Expression nullable n
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Integer -> n
forall a. Num a => Integer -> a
fromInteger

instance (Fractional n, H.ToSql n)
         => Fractional (Expression nullable n) where
  / :: Expression nullable n
-> Expression nullable n -> Expression nullable n
(/) = (QueryBuilder -> QueryBuilder -> QueryBuilder) -> Operator n n n
forall a b c.
(QueryBuilder -> QueryBuilder -> QueryBuilder) -> Operator a b c
op QueryBuilder -> QueryBuilder -> QueryBuilder
(H./.)
  fromRational :: Rational -> Expression nullable n
fromRational = n -> Expression nullable n
forall a (nullable :: Nullable).
ToSql a =>
a -> Expression nullable a
arg (n -> Expression nullable n)
-> (Rational -> n) -> Rational -> Expression nullable n
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rational -> n
forall a. Fractional a => Rational -> a
fromRational
  
data Table (table :: Symbol) database = Table (Maybe Text) Text

-- | An table alias that can be used inside the Query.  The function
-- inside the newtype can also be applied directly to create an
-- expression from a field.
newtype Tbl table database (joinType :: JoinType) =
  Tbl { Tbl table database joinType
-> forall (fieldNull :: Nullable) (exprNull :: Nullable) a.
   CheckExprNullable (JoinNullable joinType fieldNull) exprNull =>
   Field table database fieldNull a -> Expression exprNull a
getTableAlias ::
          forall fieldNull exprNull a .
          CheckExprNullable (JoinNullable joinType fieldNull) exprNull =>
          Field table database fieldNull a ->
          Expression exprNull a }

newtype Insertor (table :: Symbol) database a = Insertor (H.Insertor a)
  deriving (Semigroup (Insertor table database a)
Insertor table database a
Semigroup (Insertor table database a)
-> Insertor table database a
-> (Insertor table database a
    -> Insertor table database a -> Insertor table database a)
-> ([Insertor table database a] -> Insertor table database a)
-> Monoid (Insertor table database a)
[Insertor table database a] -> Insertor table database a
Insertor table database a
-> Insertor table database a -> Insertor table database a
forall a.
Semigroup a -> a -> (a -> a -> a) -> ([a] -> a) -> Monoid a
forall (table :: Symbol) database a.
Semigroup (Insertor table database a)
forall (table :: Symbol) database a. Insertor table database a
forall (table :: Symbol) database a.
[Insertor table database a] -> Insertor table database a
forall (table :: Symbol) database a.
Insertor table database a
-> Insertor table database a -> Insertor table database a
mconcat :: [Insertor table database a] -> Insertor table database a
$cmconcat :: forall (table :: Symbol) database a.
[Insertor table database a] -> Insertor table database a
mappend :: Insertor table database a
-> Insertor table database a -> Insertor table database a
$cmappend :: forall (table :: Symbol) database a.
Insertor table database a
-> Insertor table database a -> Insertor table database a
mempty :: Insertor table database a
$cmempty :: forall (table :: Symbol) database a. Insertor table database a
$cp1Monoid :: forall (table :: Symbol) database a.
Semigroup (Insertor table database a)
Monoid, b -> Insertor table database a -> Insertor table database a
NonEmpty (Insertor table database a) -> Insertor table database a
Insertor table database a
-> Insertor table database a -> Insertor table database a
(Insertor table database a
 -> Insertor table database a -> Insertor table database a)
-> (NonEmpty (Insertor table database a)
    -> Insertor table database a)
-> (forall b.
    Integral b =>
    b -> Insertor table database a -> Insertor table database a)
-> Semigroup (Insertor table database a)
forall b.
Integral b =>
b -> Insertor table database a -> Insertor table database a
forall a.
(a -> a -> a)
-> (NonEmpty a -> a)
-> (forall b. Integral b => b -> a -> a)
-> Semigroup a
forall (table :: Symbol) database a.
NonEmpty (Insertor table database a) -> Insertor table database a
forall (table :: Symbol) database a.
Insertor table database a
-> Insertor table database a -> Insertor table database a
forall (table :: Symbol) database a b.
Integral b =>
b -> Insertor table database a -> Insertor table database a
stimes :: b -> Insertor table database a -> Insertor table database a
$cstimes :: forall (table :: Symbol) database a b.
Integral b =>
b -> Insertor table database a -> Insertor table database a
sconcat :: NonEmpty (Insertor table database a) -> Insertor table database a
$csconcat :: forall (table :: Symbol) database a.
NonEmpty (Insertor table database a) -> Insertor table database a
<> :: Insertor table database a
-> Insertor table database a -> Insertor table database a
$c<> :: forall (table :: Symbol) database a.
Insertor table database a
-> Insertor table database a -> Insertor table database a
Semigroup, b -> Insertor table database b -> Insertor table database a
(a -> b) -> Insertor table database b -> Insertor table database a
(forall a b.
 (a -> b) -> Insertor table database b -> Insertor table database a)
-> (forall b a.
    b -> Insertor table database b -> Insertor table database a)
-> Contravariant (Insertor table database)
forall b a.
b -> Insertor table database b -> Insertor table database a
forall a b.
(a -> b) -> Insertor table database b -> Insertor table database a
forall (table :: Symbol) database b a.
b -> Insertor table database b -> Insertor table database a
forall (table :: Symbol) database a b.
(a -> b) -> Insertor table database b -> Insertor table database a
forall (f :: * -> *).
(forall a b. (a -> b) -> f b -> f a)
-> (forall b a. b -> f b -> f a) -> Contravariant f
>$ :: b -> Insertor table database b -> Insertor table database a
$c>$ :: forall (table :: Symbol) database b a.
b -> Insertor table database b -> Insertor table database a
contramap :: (a -> b) -> Insertor table database b -> Insertor table database a
$ccontramap :: forall (table :: Symbol) database a b.
(a -> b) -> Insertor table database b -> Insertor table database a
Contravariant)

data ClauseState = ClauseState
  { ClauseState -> QueryClauses
clausesBuild :: H.QueryClauses  -- clauses build so far
  , ClauseState -> Map Text Int
aliases :: Map.Map Text Int   -- map of aliases to times used
  }

emptyClauseState :: ClauseState
emptyClauseState :: ClauseState
emptyClauseState = QueryClauses -> Map Text Int -> ClauseState
ClauseState QueryClauses
forall a. Monoid a => a
mempty Map Text Int
forall k a. Map k a
Map.empty

type QueryInner a = State ClauseState a

newtype Query database a = Query (QueryInner a)
  deriving (a -> Query database b -> Query database a
(a -> b) -> Query database a -> Query database b
(forall a b. (a -> b) -> Query database a -> Query database b)
-> (forall a b. a -> Query database b -> Query database a)
-> Functor (Query database)
forall a b. a -> Query database b -> Query database a
forall a b. (a -> b) -> Query database a -> Query database b
forall database a b. a -> Query database b -> Query database a
forall database a b.
(a -> b) -> Query database a -> Query database b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a -> Query database b -> Query database a
$c<$ :: forall database a b. a -> Query database b -> Query database a
fmap :: (a -> b) -> Query database a -> Query database b
$cfmap :: forall database a b.
(a -> b) -> Query database a -> Query database b
Functor, Functor (Query database)
a -> Query database a
Functor (Query database)
-> (forall a. a -> Query database a)
-> (forall a b.
    Query database (a -> b) -> Query database a -> Query database b)
-> (forall a b c.
    (a -> b -> c)
    -> Query database a -> Query database b -> Query database c)
-> (forall a b.
    Query database a -> Query database b -> Query database b)
-> (forall a b.
    Query database a -> Query database b -> Query database a)
-> Applicative (Query database)
Query database a -> Query database b -> Query database b
Query database a -> Query database b -> Query database a
Query database (a -> b) -> Query database a -> Query database b
(a -> b -> c)
-> Query database a -> Query database b -> Query database c
forall database. Functor (Query database)
forall a. a -> Query database a
forall database a. a -> Query database a
forall a b.
Query database a -> Query database b -> Query database a
forall a b.
Query database a -> Query database b -> Query database b
forall a b.
Query database (a -> b) -> Query database a -> Query database b
forall database a b.
Query database a -> Query database b -> Query database a
forall database a b.
Query database a -> Query database b -> Query database b
forall database a b.
Query database (a -> b) -> Query database a -> Query database b
forall a b c.
(a -> b -> c)
-> Query database a -> Query database b -> Query database c
forall database a b c.
(a -> b -> c)
-> Query database a -> Query database b -> Query database c
forall (f :: * -> *).
Functor f
-> (forall a. a -> f a)
-> (forall a b. f (a -> b) -> f a -> f b)
-> (forall a b c. (a -> b -> c) -> f a -> f b -> f c)
-> (forall a b. f a -> f b -> f b)
-> (forall a b. f a -> f b -> f a)
-> Applicative f
<* :: Query database a -> Query database b -> Query database a
$c<* :: forall database a b.
Query database a -> Query database b -> Query database a
*> :: Query database a -> Query database b -> Query database b
$c*> :: forall database a b.
Query database a -> Query database b -> Query database b
liftA2 :: (a -> b -> c)
-> Query database a -> Query database b -> Query database c
$cliftA2 :: forall database a b c.
(a -> b -> c)
-> Query database a -> Query database b -> Query database c
<*> :: Query database (a -> b) -> Query database a -> Query database b
$c<*> :: forall database a b.
Query database (a -> b) -> Query database a -> Query database b
pure :: a -> Query database a
$cpure :: forall database a. a -> Query database a
$cp1Applicative :: forall database. Functor (Query database)
Applicative, Applicative (Query database)
a -> Query database a
Applicative (Query database)
-> (forall a b.
    Query database a -> (a -> Query database b) -> Query database b)
-> (forall a b.
    Query database a -> Query database b -> Query database b)
-> (forall a. a -> Query database a)
-> Monad (Query database)
Query database a -> (a -> Query database b) -> Query database b
Query database a -> Query database b -> Query database b
forall database. Applicative (Query database)
forall a. a -> Query database a
forall database a. a -> Query database a
forall a b.
Query database a -> Query database b -> Query database b
forall a b.
Query database a -> (a -> Query database b) -> Query database b
forall database a b.
Query database a -> Query database b -> Query database b
forall database a b.
Query database a -> (a -> Query database b) -> Query database b
forall (m :: * -> *).
Applicative m
-> (forall a b. m a -> (a -> m b) -> m b)
-> (forall a b. m a -> m b -> m b)
-> (forall a. a -> m a)
-> Monad m
return :: a -> Query database a
$creturn :: forall database a. a -> Query database a
>> :: Query database a -> Query database b -> Query database b
$c>> :: forall database a b.
Query database a -> Query database b -> Query database b
>>= :: Query database a -> (a -> Query database b) -> Query database b
$c>>= :: forall database a b.
Query database a -> (a -> Query database b) -> Query database b
$cp1Monad :: forall database. Applicative (Query database)
Monad)

instance H.ToQueryBuilder (Query database (H.Selector a)) where
  toQueryBuilder :: Query database (Selector a) -> QueryBuilder
toQueryBuilder (Query QueryInner (Selector a)
query) =
    let (Selector a
selector, ClauseState
clauseState) = QueryInner (Selector a) -> ClauseState -> (Selector a, ClauseState)
forall s a. State s a -> s -> (a, s)
runState QueryInner (Selector a)
query ClauseState
emptyClauseState
    -- TODO: finalize query
    in Query a -> QueryBuilder
forall a. ToQueryBuilder a => a -> QueryBuilder
H.toQueryBuilder (Query a -> QueryBuilder) -> Query a -> QueryBuilder
forall a b. (a -> b) -> a -> b
$ Selector a -> QueryClauses -> Query a
forall a. Selector a -> QueryClauses -> Query a
H.select Selector a
selector (QueryClauses -> Query a) -> QueryClauses -> Query a
forall a b. (a -> b) -> a -> b
$ ClauseState -> QueryClauses
clausesBuild ClauseState
clauseState

type Operator a b c = forall nullable .
                      (Expression nullable a ->
                       Expression nullable b ->
                       Expression nullable c)

infixl 9 @@

-- | Create an expression from an aliased table and a field.
(@@) :: CheckExprNullable (JoinNullable joinType fieldNull) exprNull
     => Tbl table database (joinType :: JoinType)
     -> Field table database fieldNull a
     -> Expression exprNull a
@@ :: Tbl table database joinType
-> Field table database fieldNull a -> Expression exprNull a
(@@) = Tbl table database joinType
-> Field table database fieldNull a -> Expression exprNull a
forall (table :: Symbol) database (joinType :: JoinType).
Tbl table database joinType
-> forall (fieldNull :: Nullable) (exprNull :: Nullable) a.
   CheckExprNullable (JoinNullable joinType fieldNull) exprNull =>
   Field table database fieldNull a -> Expression exprNull a
getTableAlias  
 
mkTableAlias :: Text -> Tbl table database leftJoined
mkTableAlias :: Text -> Tbl table database leftJoined
mkTableAlias Text
tableName = (forall (fieldNull :: Nullable) (exprNull :: Nullable) a.
 CheckExprNullable (JoinNullable leftJoined fieldNull) exprNull =>
 Field table database fieldNull a -> Expression exprNull a)
-> Tbl table database leftJoined
forall (table :: Symbol) database (joinType :: JoinType).
(forall (fieldNull :: Nullable) (exprNull :: Nullable) a.
 CheckExprNullable (JoinNullable joinType fieldNull) exprNull =>
 Field table database fieldNull a -> Expression exprNull a)
-> Tbl table database joinType
Tbl ((forall (fieldNull :: Nullable) (exprNull :: Nullable) a.
  CheckExprNullable (JoinNullable leftJoined fieldNull) exprNull =>
  Field table database fieldNull a -> Expression exprNull a)
 -> Tbl table database leftJoined)
-> (forall (fieldNull :: Nullable) (exprNull :: Nullable) a.
    CheckExprNullable (JoinNullable leftJoined fieldNull) exprNull =>
    Field table database fieldNull a -> Expression exprNull a)
-> Tbl table database leftJoined
forall a b. (a -> b) -> a -> b
$ \(Field Text
_ Text
fieldName) ->
  QueryInner QueryBuilder -> Expression exprNull a
forall (nullable :: Nullable) a.
QueryInner QueryBuilder -> Expression nullable a
Expression (QueryInner QueryBuilder -> Expression exprNull a)
-> QueryInner QueryBuilder -> Expression exprNull a
forall a b. (a -> b) -> a -> b
$ QueryBuilder -> QueryInner QueryBuilder
forall (f :: * -> *) a. Applicative f => a -> f a
pure (QueryBuilder -> QueryInner QueryBuilder)
-> QueryBuilder -> QueryInner QueryBuilder
forall a b. (a -> b) -> a -> b
$ Text -> QueryBuilder
H.rawSql (Text -> QueryBuilder) -> Text -> QueryBuilder
forall a b. (a -> b) -> a -> b
$ Text
tableName Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"." Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
fieldName

data QueryOrdering = Asc SomeExpression | Desc SomeExpression

-- | make a selector from a column
sel :: H.FromSql a
    => Expression 'NotNull a
    -> Selector a
sel :: Expression 'NotNull a -> Selector a
sel (Expression QueryInner QueryBuilder
expr) = QueryInner (Selector a) -> Selector a
forall a. QueryInner (Selector a) -> Selector a
Selector (QueryInner (Selector a) -> Selector a)
-> QueryInner (Selector a) -> Selector a
forall a b. (a -> b) -> a -> b
$ QueryBuilder -> Selector a
forall a. FromSql a => QueryBuilder -> Selector a
H.sel (QueryBuilder -> Selector a)
-> QueryInner QueryBuilder -> QueryInner (Selector a)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> QueryInner QueryBuilder
expr

-- | make a selector from a column that can be null
selMaybe :: H.FromSql (Maybe a)
         => Expression 'Nullable a
         -> Selector (Maybe a)
selMaybe :: Expression 'Nullable a -> Selector (Maybe a)
selMaybe (Expression QueryInner QueryBuilder
expr) = QueryInner (Selector (Maybe a)) -> Selector (Maybe a)
forall a. QueryInner (Selector a) -> Selector a
Selector (QueryInner (Selector (Maybe a)) -> Selector (Maybe a))
-> QueryInner (Selector (Maybe a)) -> Selector (Maybe a)
forall a b. (a -> b) -> a -> b
$ QueryBuilder -> Selector (Maybe a)
forall a. FromSql a => QueryBuilder -> Selector a
H.sel (QueryBuilder -> Selector (Maybe a))
-> QueryInner QueryBuilder -> QueryInner (Selector (Maybe a))
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> QueryInner QueryBuilder
expr

-- | pass an argument
arg :: H.ToSql a => a -> Expression nullable a
arg :: a -> Expression nullable a
arg a
x = QueryInner QueryBuilder -> Expression nullable a
forall (nullable :: Nullable) a.
QueryInner QueryBuilder -> Expression nullable a
Expression (QueryInner QueryBuilder -> Expression nullable a)
-> QueryInner QueryBuilder -> Expression nullable a
forall a b. (a -> b) -> a -> b
$ QueryBuilder -> QueryInner QueryBuilder
forall (f :: * -> *) a. Applicative f => a -> f a
pure (QueryBuilder -> QueryInner QueryBuilder)
-> QueryBuilder -> QueryInner QueryBuilder
forall a b. (a -> b) -> a -> b
$ a -> QueryBuilder
forall a. ToSql a => a -> QueryBuilder
H.arg a
x

-- | pass an argument which can be null
argMaybe :: H.ToSql a => Maybe a -> Expression 'Nullable a
argMaybe :: Maybe a -> Expression 'Nullable a
argMaybe Maybe a
x = QueryInner QueryBuilder -> Expression 'Nullable a
forall (nullable :: Nullable) a.
QueryInner QueryBuilder -> Expression nullable a
Expression (QueryInner QueryBuilder -> Expression 'Nullable a)
-> QueryInner QueryBuilder -> Expression 'Nullable a
forall a b. (a -> b) -> a -> b
$ QueryBuilder -> QueryInner QueryBuilder
forall (f :: * -> *) a. Applicative f => a -> f a
pure (QueryBuilder -> QueryInner QueryBuilder)
-> QueryBuilder -> QueryInner QueryBuilder
forall a b. (a -> b) -> a -> b
$ Maybe a -> QueryBuilder
forall a. ToSql a => a -> QueryBuilder
H.arg Maybe a
x

-- | create an operator
op :: (H.QueryBuilder -> H.QueryBuilder -> H.QueryBuilder)
   -> Operator a b c
op :: (QueryBuilder -> QueryBuilder -> QueryBuilder) -> Operator a b c
op = (QueryBuilder -> QueryBuilder -> QueryBuilder)
-> Expression nullable a
-> Expression nullable b
-> Expression nullable c
forall (nullable :: Nullable) a b c.
(QueryBuilder -> QueryBuilder -> QueryBuilder)
-> Expression nullable a
-> Expression nullable b
-> Expression nullable c
fun2

fun1 :: (H.QueryBuilder -> H.QueryBuilder)
     -> Expression nullable a
     -> Expression nullable b
fun1 :: (QueryBuilder -> QueryBuilder)
-> Expression nullable a -> Expression nullable b
fun1 QueryBuilder -> QueryBuilder
f (Expression QueryInner QueryBuilder
x) = QueryInner QueryBuilder -> Expression nullable b
forall (nullable :: Nullable) a.
QueryInner QueryBuilder -> Expression nullable a
Expression (QueryInner QueryBuilder -> Expression nullable b)
-> QueryInner QueryBuilder -> Expression nullable b
forall a b. (a -> b) -> a -> b
$ QueryBuilder -> QueryBuilder
f (QueryBuilder -> QueryBuilder)
-> QueryInner QueryBuilder -> QueryInner QueryBuilder
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> QueryInner QueryBuilder
x

fun2 :: (H.QueryBuilder -> H.QueryBuilder -> H.QueryBuilder)
     -> Expression nullable a
     -> Expression nullable b
     -> Expression nullable c
fun2 :: (QueryBuilder -> QueryBuilder -> QueryBuilder)
-> Expression nullable a
-> Expression nullable b
-> Expression nullable c
fun2 QueryBuilder -> QueryBuilder -> QueryBuilder
f (Expression QueryInner QueryBuilder
x1) (Expression QueryInner QueryBuilder
x2) = QueryInner QueryBuilder -> Expression nullable c
forall (nullable :: Nullable) a.
QueryInner QueryBuilder -> Expression nullable a
Expression (QueryInner QueryBuilder -> Expression nullable c)
-> QueryInner QueryBuilder -> Expression nullable c
forall a b. (a -> b) -> a -> b
$ (QueryBuilder -> QueryBuilder -> QueryBuilder)
-> QueryInner QueryBuilder
-> QueryInner QueryBuilder
-> QueryInner QueryBuilder
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 QueryBuilder -> QueryBuilder -> QueryBuilder
f QueryInner QueryBuilder
x1 QueryInner QueryBuilder
x2

fun3 :: (H.QueryBuilder -> H.QueryBuilder -> H.QueryBuilder -> H.QueryBuilder)
     -> Expression nullable a
     -> Expression nullable b
     -> Expression nullable c
     -> Expression nullable d
fun3 :: (QueryBuilder -> QueryBuilder -> QueryBuilder -> QueryBuilder)
-> Expression nullable a
-> Expression nullable b
-> Expression nullable c
-> Expression nullable d
fun3 QueryBuilder -> QueryBuilder -> QueryBuilder -> QueryBuilder
f (Expression QueryInner QueryBuilder
x1) (Expression QueryInner QueryBuilder
x2) (Expression QueryInner QueryBuilder
x3) =
  QueryInner QueryBuilder -> Expression nullable d
forall (nullable :: Nullable) a.
QueryInner QueryBuilder -> Expression nullable a
Expression (QueryInner QueryBuilder -> Expression nullable d)
-> QueryInner QueryBuilder -> Expression nullable d
forall a b. (a -> b) -> a -> b
$ (QueryBuilder -> QueryBuilder -> QueryBuilder -> QueryBuilder)
-> QueryInner QueryBuilder
-> QueryInner QueryBuilder
-> QueryInner QueryBuilder
-> QueryInner QueryBuilder
forall (f :: * -> *) a b c d.
Applicative f =>
(a -> b -> c -> d) -> f a -> f b -> f c -> f d
liftA3 QueryBuilder -> QueryBuilder -> QueryBuilder -> QueryBuilder
f QueryInner QueryBuilder
x1 QueryInner QueryBuilder
x2 QueryInner QueryBuilder
x3

substr :: Expression nullable Text -> Expression nullable Int
       -> Expression nullable Int
       -> Expression nullable Text
substr :: Expression nullable Text
-> Expression nullable Int
-> Expression nullable Int
-> Expression nullable Text
substr = (QueryBuilder -> QueryBuilder -> QueryBuilder -> QueryBuilder)
-> Expression nullable Text
-> Expression nullable Int
-> Expression nullable Int
-> Expression nullable Text
forall (nullable :: Nullable) a b c d.
(QueryBuilder -> QueryBuilder -> QueryBuilder -> QueryBuilder)
-> Expression nullable a
-> Expression nullable b
-> Expression nullable c
-> Expression nullable d
fun3 QueryBuilder -> QueryBuilder -> QueryBuilder -> QueryBuilder
H.substr

(=.), (/=.), (>.), (<.), (>=.), (<=.) :: H.ToSql a => Operator a a Bool
=. :: Operator a a Bool
(=.) = (QueryBuilder -> QueryBuilder -> QueryBuilder) -> Operator a a Bool
forall a b c.
(QueryBuilder -> QueryBuilder -> QueryBuilder) -> Operator a b c
op QueryBuilder -> QueryBuilder -> QueryBuilder
(H.=.)
/=. :: Operator a a Bool
(/=.) = (QueryBuilder -> QueryBuilder -> QueryBuilder) -> Operator a a Bool
forall a b c.
(QueryBuilder -> QueryBuilder -> QueryBuilder) -> Operator a b c
op QueryBuilder -> QueryBuilder -> QueryBuilder
(H./=.)
>. :: Operator a a Bool
(>.) = (QueryBuilder -> QueryBuilder -> QueryBuilder) -> Operator a a Bool
forall a b c.
(QueryBuilder -> QueryBuilder -> QueryBuilder) -> Operator a b c
op QueryBuilder -> QueryBuilder -> QueryBuilder
(H.>.)
<. :: Operator a a Bool
(<.) = (QueryBuilder -> QueryBuilder -> QueryBuilder) -> Operator a a Bool
forall a b c.
(QueryBuilder -> QueryBuilder -> QueryBuilder) -> Operator a b c
op QueryBuilder -> QueryBuilder -> QueryBuilder
(H.<.)
>=. :: Operator a a Bool
(>=.) = (QueryBuilder -> QueryBuilder -> QueryBuilder) -> Operator a a Bool
forall a b c.
(QueryBuilder -> QueryBuilder -> QueryBuilder) -> Operator a b c
op QueryBuilder -> QueryBuilder -> QueryBuilder
(H.>=.)
<=. :: Operator a a Bool
(<=.) = (QueryBuilder -> QueryBuilder -> QueryBuilder) -> Operator a a Bool
forall a b c.
(QueryBuilder -> QueryBuilder -> QueryBuilder) -> Operator a b c
op QueryBuilder -> QueryBuilder -> QueryBuilder
(H.<=.)

(||.), (&&.) :: Operator Bool Bool Bool
||. :: Expression nullable Bool
-> Expression nullable Bool -> Expression nullable Bool
(||.) = (QueryBuilder -> QueryBuilder -> QueryBuilder)
-> Operator Bool Bool Bool
forall a b c.
(QueryBuilder -> QueryBuilder -> QueryBuilder) -> Operator a b c
op QueryBuilder -> QueryBuilder -> QueryBuilder
(H.||.)
&&. :: Expression nullable Bool
-> Expression nullable Bool -> Expression nullable Bool
(&&.) = (QueryBuilder -> QueryBuilder -> QueryBuilder)
-> Operator Bool Bool Bool
forall a b c.
(QueryBuilder -> QueryBuilder -> QueryBuilder) -> Operator a b c
op QueryBuilder -> QueryBuilder -> QueryBuilder
(H.&&.)

true_, false_ :: Expression nullable Bool
true_ :: Expression nullable Bool
true_ = QueryInner QueryBuilder -> Expression nullable Bool
forall (nullable :: Nullable) a.
QueryInner QueryBuilder -> Expression nullable a
Expression (QueryInner QueryBuilder -> Expression nullable Bool)
-> QueryInner QueryBuilder -> Expression nullable Bool
forall a b. (a -> b) -> a -> b
$ QueryBuilder -> QueryInner QueryBuilder
forall (f :: * -> *) a. Applicative f => a -> f a
pure (QueryBuilder -> QueryInner QueryBuilder)
-> QueryBuilder -> QueryInner QueryBuilder
forall a b. (a -> b) -> a -> b
$ Text -> QueryBuilder
H.rawSql Text
"true"
false_ :: Expression nullable Bool
false_ = QueryInner QueryBuilder -> Expression nullable Bool
forall (nullable :: Nullable) a.
QueryInner QueryBuilder -> Expression nullable a
Expression (QueryInner QueryBuilder -> Expression nullable Bool)
-> QueryInner QueryBuilder -> Expression nullable Bool
forall a b. (a -> b) -> a -> b
$ QueryBuilder -> QueryInner QueryBuilder
forall (f :: * -> *) a. Applicative f => a -> f a
pure (QueryBuilder -> QueryInner QueryBuilder)
-> QueryBuilder -> QueryInner QueryBuilder
forall a b. (a -> b) -> a -> b
$ Text -> QueryBuilder
H.rawSql Text
"false"

-- | make expression nullable
nullable :: Expression nullable a -> Expression 'Nullable a
nullable :: Expression nullable a -> Expression 'Nullable a
nullable = Expression nullable a -> Expression 'Nullable a
coerce

class Castable a where
  -- | Safe cast.  This uses the SQL CAST function to convert safely
  -- from one type to another.
  cast :: Expression nullable b
       -> Expression nullable a

castTo :: H.QueryBuilder
       -> Expression nullable b
       -> Expression nullable a
castTo :: QueryBuilder -> Expression nullable b -> Expression nullable a
castTo QueryBuilder
tp (Expression QueryInner QueryBuilder
e) = QueryInner QueryBuilder -> Expression nullable a
forall (nullable :: Nullable) a.
QueryInner QueryBuilder -> Expression nullable a
Expression (QueryInner QueryBuilder -> Expression nullable a)
-> QueryInner QueryBuilder -> Expression nullable a
forall a b. (a -> b) -> a -> b
$ do
  QueryBuilder
x <- QueryInner QueryBuilder
e
  QueryBuilder -> QueryInner QueryBuilder
forall (f :: * -> *) a. Applicative f => a -> f a
pure (QueryBuilder -> QueryInner QueryBuilder)
-> QueryBuilder -> QueryInner QueryBuilder
forall a b. (a -> b) -> a -> b
$ Text -> [QueryBuilder] -> QueryBuilder
H.fun Text
"cast" [QueryBuilder
x QueryBuilder -> QueryBuilder -> QueryBuilder
`H.as` QueryBuilder
tp]

instance Castable StrictBS.ByteString where
  cast :: Expression nullable b -> Expression nullable ByteString
cast = QueryBuilder
-> Expression nullable b -> Expression nullable ByteString
forall (nullable :: Nullable) b a.
QueryBuilder -> Expression nullable b -> Expression nullable a
castTo QueryBuilder
"BINARY"

instance Castable Text where
  cast :: Expression nullable b -> Expression nullable Text
cast = QueryBuilder -> Expression nullable b -> Expression nullable Text
forall (nullable :: Nullable) b a.
QueryBuilder -> Expression nullable b -> Expression nullable a
castTo QueryBuilder
"CHAR UNICODE"

instance Castable Day where
  cast :: Expression nullable b -> Expression nullable Day
cast = QueryBuilder -> Expression nullable b -> Expression nullable Day
forall (nullable :: Nullable) b a.
QueryBuilder -> Expression nullable b -> Expression nullable a
castTo QueryBuilder
"DATE"

instance Castable LocalTime where
  cast :: Expression nullable b -> Expression nullable LocalTime
cast = QueryBuilder
-> Expression nullable b -> Expression nullable LocalTime
forall (nullable :: Nullable) b a.
QueryBuilder -> Expression nullable b -> Expression nullable a
castTo QueryBuilder
"DATETIME"

instance Castable Scientific where
  cast :: Expression nullable b -> Expression nullable Scientific
cast = QueryBuilder
-> Expression nullable b -> Expression nullable Scientific
forall (nullable :: Nullable) b a.
QueryBuilder -> Expression nullable b -> Expression nullable a
castTo QueryBuilder
"DECIMAL"

instance Castable Double where
  cast :: Expression nullable b -> Expression nullable Double
cast = QueryBuilder -> Expression nullable b -> Expression nullable Double
forall (nullable :: Nullable) b a.
QueryBuilder -> Expression nullable b -> Expression nullable a
castTo QueryBuilder
"FLOAT[53]"

instance Castable Int where
  cast :: Expression nullable b -> Expression nullable Int
cast = QueryBuilder -> Expression nullable b -> Expression nullable Int
forall (nullable :: Nullable) b a.
QueryBuilder -> Expression nullable b -> Expression nullable a
castTo QueryBuilder
"SIGNED"

instance Castable Int8 where
  cast :: Expression nullable b -> Expression nullable Int8
cast = QueryBuilder -> Expression nullable b -> Expression nullable Int8
forall (nullable :: Nullable) b a.
QueryBuilder -> Expression nullable b -> Expression nullable a
castTo QueryBuilder
"SIGNED"

instance Castable Int16 where
  cast :: Expression nullable b -> Expression nullable Int16
cast = QueryBuilder -> Expression nullable b -> Expression nullable Int16
forall (nullable :: Nullable) b a.
QueryBuilder -> Expression nullable b -> Expression nullable a
castTo QueryBuilder
"SIGNED"

instance Castable Int32 where
  cast :: Expression nullable b -> Expression nullable Int32
cast = QueryBuilder -> Expression nullable b -> Expression nullable Int32
forall (nullable :: Nullable) b a.
QueryBuilder -> Expression nullable b -> Expression nullable a
castTo QueryBuilder
"SIGNED"

instance Castable Int64 where
  cast :: Expression nullable b -> Expression nullable Int64
cast = QueryBuilder -> Expression nullable b -> Expression nullable Int64
forall (nullable :: Nullable) b a.
QueryBuilder -> Expression nullable b -> Expression nullable a
castTo QueryBuilder
"SIGNED"

instance Castable TimeOfDay where
  cast :: Expression nullable b -> Expression nullable TimeOfDay
cast = QueryBuilder
-> Expression nullable b -> Expression nullable TimeOfDay
forall (nullable :: Nullable) b a.
QueryBuilder -> Expression nullable b -> Expression nullable a
castTo QueryBuilder
"TIME"

instance Castable DiffTime where
  cast :: Expression nullable b -> Expression nullable DiffTime
cast = QueryBuilder
-> Expression nullable b -> Expression nullable DiffTime
forall (nullable :: Nullable) b a.
QueryBuilder -> Expression nullable b -> Expression nullable a
castTo QueryBuilder
"TIME"

instance Castable Word where
  cast :: Expression nullable b -> Expression nullable Word
cast = QueryBuilder -> Expression nullable b -> Expression nullable Word
forall (nullable :: Nullable) b a.
QueryBuilder -> Expression nullable b -> Expression nullable a
castTo QueryBuilder
"UNSIGNED"

instance Castable Word8 where
  cast :: Expression nullable b -> Expression nullable Word8
cast = QueryBuilder -> Expression nullable b -> Expression nullable Word8
forall (nullable :: Nullable) b a.
QueryBuilder -> Expression nullable b -> Expression nullable a
castTo QueryBuilder
"UNSIGNED"

instance Castable Word16 where
  cast :: Expression nullable b -> Expression nullable Word16
cast = QueryBuilder -> Expression nullable b -> Expression nullable Word16
forall (nullable :: Nullable) b a.
QueryBuilder -> Expression nullable b -> Expression nullable a
castTo QueryBuilder
"UNSIGNED"

instance Castable Word32 where
  cast :: Expression nullable b -> Expression nullable Word32
cast = QueryBuilder -> Expression nullable b -> Expression nullable Word32
forall (nullable :: Nullable) b a.
QueryBuilder -> Expression nullable b -> Expression nullable a
castTo QueryBuilder
"UNSIGNED"

instance Castable Word64 where
  cast :: Expression nullable b -> Expression nullable Word64
cast = QueryBuilder -> Expression nullable b -> Expression nullable Word64
forall (nullable :: Nullable) b a.
QueryBuilder -> Expression nullable b -> Expression nullable a
castTo QueryBuilder
"UNSIGNED"

-- | Cast the return type of an expression to any other type, without
-- changing the query. Since this library adds static typing on top of
-- SQL, you may sometimes want to use this to get back the lenient
-- behaviour of SQL.  This opens up more possibilies for runtime
-- errors, so it's up to the programmer to ensure type correctness.
unsafeCast :: Expression nullable a -> Expression nullable b
unsafeCast :: Expression nullable a -> Expression nullable b
unsafeCast = Expression nullable a -> Expression nullable b
coerce

fieldText :: Field table database nullable a -> Text
fieldText :: Field table database nullable a -> Text
fieldText (Field Text
table Text
fieldName) = Text
table Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"." Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
fieldName

insertOne :: Insertable fieldNull fieldType a
          => Field table database fieldNull fieldType
          -> Insertor table database a
insertOne :: Field table database fieldNull fieldType
-> Insertor table database a
insertOne = Insertor a -> Insertor table database a
forall (table :: Symbol) database a.
Insertor a -> Insertor table database a
Insertor (Insertor a -> Insertor table database a)
-> (Field table database fieldNull fieldType -> Insertor a)
-> Field table database fieldNull fieldType
-> Insertor table database a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Insertor a
forall a. ToSql a => Text -> Insertor a
H.insertOne(Text -> Insertor a)
-> (Field table database fieldNull fieldType -> Text)
-> Field table database fieldNull fieldType
-> Insertor a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Field table database fieldNull fieldType -> Text
forall (table :: Symbol) database (nullable :: Nullable) a.
Field table database nullable a -> Text
fieldText

genFst :: (a :*: b) () -> a ()
genFst :: (:*:) a b () -> a ()
genFst (a ()
a :*: b ()
_) = a ()
a

genSnd :: (a :*: b) () -> b ()
genSnd :: (:*:) a b () -> b ()
genSnd (a ()
_ :*: b ()
b) = b ()
b

class InsertGeneric table database (fields :: *) (data_ :: *) where
  insertDataGeneric :: fields -> Insertor table database data_

instance (InsertGeneric tbl db (a ()) (c ()),
          InsertGeneric tbl db (b ()) (d ())) =>
         InsertGeneric tbl db ((a :*: b) ()) ((c :*: d) ()) where
  insertDataGeneric :: (:*:) a b () -> Insertor tbl db ((:*:) c d ())
insertDataGeneric (a ()
a :*: b ()
b) =
    ((:*:) c d () -> c ())
-> Insertor tbl db (c ()) -> Insertor tbl db ((:*:) c d ())
forall (f :: * -> *) a b. Contravariant f => (a -> b) -> f b -> f a
contramap (:*:) c d () -> c ()
forall (a :: * -> *) (b :: * -> *). (:*:) a b () -> a ()
genFst (a () -> Insertor tbl db (c ())
forall (table :: Symbol) database fields data_.
InsertGeneric table database fields data_ =>
fields -> Insertor table database data_
insertDataGeneric a ()
a) Insertor tbl db ((:*:) c d ())
-> Insertor tbl db ((:*:) c d ()) -> Insertor tbl db ((:*:) c d ())
forall a. Semigroup a => a -> a -> a
<>
    ((:*:) c d () -> d ())
-> Insertor tbl db (d ()) -> Insertor tbl db ((:*:) c d ())
forall (f :: * -> *) a b. Contravariant f => (a -> b) -> f b -> f a
contramap (:*:) c d () -> d ()
forall (a :: * -> *) (b :: * -> *). (:*:) a b () -> b ()
genSnd (b () -> Insertor tbl db (d ())
forall (table :: Symbol) database fields data_.
InsertGeneric table database fields data_ =>
fields -> Insertor table database data_
insertDataGeneric b ()
b)

instance InsertGeneric tbl db (a ()) (b ()) =>
         InsertGeneric tbl db (M1 m1 m2 a ()) (M1 m3 m4 b ()) where
  insertDataGeneric :: M1 m1 m2 a () -> Insertor tbl db (M1 m3 m4 b ())
insertDataGeneric = (M1 m3 m4 b () -> b ())
-> Insertor tbl db (b ()) -> Insertor tbl db (M1 m3 m4 b ())
forall (f :: * -> *) a b. Contravariant f => (a -> b) -> f b -> f a
contramap M1 m3 m4 b () -> b ()
forall i (c :: Meta) k (f :: k -> *) (p :: k). M1 i c f p -> f p
unM1 (Insertor tbl db (b ()) -> Insertor tbl db (M1 m3 m4 b ()))
-> (M1 m1 m2 a () -> Insertor tbl db (b ()))
-> M1 m1 m2 a ()
-> Insertor tbl db (M1 m3 m4 b ())
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a () -> Insertor tbl db (b ())
forall (table :: Symbol) database fields data_.
InsertGeneric table database fields data_ =>
fields -> Insertor table database data_
insertDataGeneric (a () -> Insertor tbl db (b ()))
-> (M1 m1 m2 a () -> a ())
-> M1 m1 m2 a ()
-> Insertor tbl db (b ())
forall b c a. (b -> c) -> (a -> b) -> a -> c
. M1 m1 m2 a () -> a ()
forall i (c :: Meta) k (f :: k -> *) (p :: k). M1 i c f p -> f p
unM1

instance Insertable fieldNull a b =>
  InsertGeneric tbl db (K1 r (Field tbl db fieldNull a) ()) (K1 r b ()) where
  insertDataGeneric :: K1 r (Field tbl db fieldNull a) () -> Insertor tbl db (K1 r b ())
insertDataGeneric = (K1 r b () -> b)
-> Insertor tbl db b -> Insertor tbl db (K1 r b ())
forall (f :: * -> *) a b. Contravariant f => (a -> b) -> f b -> f a
contramap K1 r b () -> b
forall i c k (p :: k). K1 i c p -> c
unK1 (Insertor tbl db b -> Insertor tbl db (K1 r b ()))
-> (K1 r (Field tbl db fieldNull a) () -> Insertor tbl db b)
-> K1 r (Field tbl db fieldNull a) ()
-> Insertor tbl db (K1 r b ())
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Field tbl db fieldNull a -> Insertor tbl db b
forall (fieldNull :: Nullable) fieldType a (table :: Symbol)
       database.
Insertable fieldNull fieldType a =>
Field table database fieldNull fieldType
-> Insertor table database a
insertOne (Field tbl db fieldNull a -> Insertor tbl db b)
-> (K1 r (Field tbl db fieldNull a) () -> Field tbl db fieldNull a)
-> K1 r (Field tbl db fieldNull a) ()
-> Insertor tbl db b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. K1 r (Field tbl db fieldNull a) () -> Field tbl db fieldNull a
forall i c k (p :: k). K1 i c p -> c
unK1

instance InsertGeneric tbl db (K1 r (Insertor tbl db a) ()) (K1 r a ()) where
  insertDataGeneric :: K1 r (Insertor tbl db a) () -> Insertor tbl db (K1 r a ())
insertDataGeneric = (K1 r a () -> a)
-> Insertor tbl db a -> Insertor tbl db (K1 r a ())
forall (f :: * -> *) a b. Contravariant f => (a -> b) -> f b -> f a
contramap K1 r a () -> a
forall i c k (p :: k). K1 i c p -> c
unK1 (Insertor tbl db a -> Insertor tbl db (K1 r a ()))
-> (K1 r (Insertor tbl db a) () -> Insertor tbl db a)
-> K1 r (Insertor tbl db a) ()
-> Insertor tbl db (K1 r a ())
forall b c a. (b -> c) -> (a -> b) -> a -> c
. K1 r (Insertor tbl db a) () -> Insertor tbl db a
forall i c k (p :: k). K1 i c p -> c
unK1

insertData :: (Generic a, Generic b, InsertGeneric tbl db (Rep a ()) (Rep b ()))
           => a -> Insertor tbl db b
insertData :: a -> Insertor tbl db b
insertData = (b -> Rep b ()) -> Insertor tbl db (Rep b ()) -> Insertor tbl db b
forall (f :: * -> *) a b. Contravariant f => (a -> b) -> f b -> f a
contramap b -> Rep b ()
forall a. Generic a => a -> Rep a ()
from' (Insertor tbl db (Rep b ()) -> Insertor tbl db b)
-> (a -> Insertor tbl db (Rep b ())) -> a -> Insertor tbl db b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Rep a () -> Insertor tbl db (Rep b ())
forall (table :: Symbol) database fields data_.
InsertGeneric table database fields data_ =>
fields -> Insertor table database data_
insertDataGeneric (Rep a () -> Insertor tbl db (Rep b ()))
-> (a -> Rep a ()) -> a -> Insertor tbl db (Rep b ())
forall b c a. (b -> c) -> (a -> b) -> a -> c
. a -> Rep a ()
forall a. Generic a => a -> Rep a ()
from'
  where from' :: Generic a => a -> Rep a ()
        from' :: a -> Rep a ()
from' = a -> Rep a ()
forall a x. Generic a => a -> Rep a x
Generics.from

skipInsert :: Insertor tbl db a
skipInsert :: Insertor tbl db a
skipInsert = Insertor tbl db a
forall a. Monoid a => a
mempty

{-
personInsertor :: Insertor table database Person
personInsertor = insertData (name, age)
-}

into :: Insertable fieldNull fieldType b
        => (a -> b)
        -> Field table database fieldNull fieldType
        -> Insertor table database a
into :: (a -> b)
-> Field table database fieldNull fieldType
-> Insertor table database a
into a -> b
f = Insertor a -> Insertor table database a
forall (table :: Symbol) database a.
Insertor a -> Insertor table database a
Insertor (Insertor a -> Insertor table database a)
-> (Field table database fieldNull fieldType -> Insertor a)
-> Field table database fieldNull fieldType
-> Insertor table database a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (a -> b) -> Text -> Insertor a
forall b a. ToSql b => (a -> b) -> Text -> Insertor a
H.into a -> b
f (Text -> Insertor a)
-> (Field table database fieldNull fieldType -> Text)
-> Field table database fieldNull fieldType
-> Insertor a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Field table database fieldNull fieldType -> Text
forall (table :: Symbol) database (nullable :: Nullable) a.
Field table database nullable a -> Text
fieldText

lensInto :: Insertable fieldNull fieldType b
         => H.Getter a b
         -> Field table database fieldNull fieldType
         -> Insertor table database a
lensInto :: Getter a b
-> Field table database fieldNull fieldType
-> Insertor table database a
lensInto Getter a b
lens Field table database fieldNull fieldType
a = Insertor a -> Insertor table database a
forall (table :: Symbol) database a.
Insertor a -> Insertor table database a
Insertor (Insertor a -> Insertor table database a)
-> Insertor a -> Insertor table database a
forall a b. (a -> b) -> a -> b
$ Getter a b -> Text -> Insertor a
forall b a. ToSql b => Getter a b -> Text -> Insertor a
H.lensInto Getter a b
lens (Text -> Insertor a) -> Text -> Insertor a
forall a b. (a -> b) -> a -> b
$ Field table database fieldNull fieldType -> Text
forall (table :: Symbol) database (nullable :: Nullable) a.
Field table database nullable a -> Text
fieldText Field table database fieldNull fieldType
a

insertValues :: Table table database
             -> Insertor table database a
             -> [a]
             -> H.Command
insertValues :: Table table database -> Insertor table database a -> [a] -> Command
insertValues (Table Maybe Text
_schema Text
tableName) (Insertor Insertor a
i) =
  QueryBuilder -> Insertor a -> [a] -> Command
forall a. QueryBuilder -> Insertor a -> [a] -> Command
H.insertValues (Text -> QueryBuilder
H.rawSql Text
tableName) Insertor a
i

newAlias :: Text -> QueryInner Text
newAlias :: Text -> QueryInner Text
newAlias Text
prefix = do
  ClauseState
clsState <- StateT ClauseState Identity ClauseState
forall s (m :: * -> *). MonadState s m => m s
get
  let newIndex :: Int
newIndex = Int -> Text -> Map Text Int -> Int
forall k a. Ord k => a -> k -> Map k a -> a
Map.findWithDefault Int
0 Text
prefix (ClauseState -> Map Text Int
aliases ClauseState
clsState) Int -> Int -> Int
forall a. Num a => a -> a -> a
+ Int
1
  ClauseState -> StateT ClauseState Identity ()
forall s (m :: * -> *). MonadState s m => s -> m ()
put (ClauseState -> StateT ClauseState Identity ())
-> ClauseState -> StateT ClauseState Identity ()
forall a b. (a -> b) -> a -> b
$ ClauseState
clsState { aliases :: Map Text Int
aliases = Text -> Int -> Map Text Int -> Map Text Int
forall k a. Ord k => k -> a -> Map k a -> Map k a
Map.insert Text
prefix Int
newIndex (Map Text Int -> Map Text Int) -> Map Text Int -> Map Text Int
forall a b. (a -> b) -> a -> b
$ ClauseState -> Map Text Int
aliases ClauseState
clsState}
  Text -> QueryInner Text
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Text -> QueryInner Text) -> Text -> QueryInner Text
forall a b. (a -> b) -> a -> b
$ Text
prefix Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> String -> Text
Text.pack (Int -> String
forall a. Show a => a -> String
show Int
newIndex)

addClauses :: H.QueryClauses -> QueryInner ()
addClauses :: QueryClauses -> StateT ClauseState Identity ()
addClauses QueryClauses
c = (ClauseState -> ClauseState) -> StateT ClauseState Identity ()
forall s (m :: * -> *). MonadState s m => (s -> s) -> m ()
modify ((ClauseState -> ClauseState) -> StateT ClauseState Identity ())
-> (ClauseState -> ClauseState) -> StateT ClauseState Identity ()
forall a b. (a -> b) -> a -> b
$ \ClauseState
clsState ->
  ClauseState
clsState { clausesBuild :: QueryClauses
clausesBuild = ClauseState -> QueryClauses
clausesBuild ClauseState
clsState QueryClauses -> QueryClauses -> QueryClauses
forall a. Semigroup a => a -> a -> a
<> QueryClauses
c }

from :: Table table database
     -> Query database (Tbl table database 'InnerJoined)
from :: Table table database
-> Query database (Tbl table database 'InnerJoined)
from (Table Maybe Text
schema Text
tableName) = QueryInner (Tbl table database 'InnerJoined)
-> Query database (Tbl table database 'InnerJoined)
forall database a. QueryInner a -> Query database a
Query (QueryInner (Tbl table database 'InnerJoined)
 -> Query database (Tbl table database 'InnerJoined))
-> QueryInner (Tbl table database 'InnerJoined)
-> Query database (Tbl table database 'InnerJoined)
forall a b. (a -> b) -> a -> b
$
  do Text
alias <- Text -> QueryInner Text
newAlias (Int -> Text -> Text
Text.take Int
1 Text
tableName)
     QueryClauses -> StateT ClauseState Identity ()
addClauses (QueryClauses -> StateT ClauseState Identity ())
-> QueryClauses -> StateT ClauseState Identity ()
forall a b. (a -> b) -> a -> b
$ QueryBuilder -> QueryClauses
H.from (QueryBuilder -> QueryClauses) -> QueryBuilder -> QueryClauses
forall a b. (a -> b) -> a -> b
$
       Text -> QueryBuilder
H.rawSql (Text -> (Text -> Text) -> Maybe Text -> Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Text
forall a. Monoid a => a
mempty (Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
".") Maybe Text
schema Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
tableName) QueryBuilder -> QueryBuilder -> QueryBuilder
`H.as` Text -> QueryBuilder
H.rawSql Text
alias
     Tbl table database 'InnerJoined
-> QueryInner (Tbl table database 'InnerJoined)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Tbl table database 'InnerJoined
 -> QueryInner (Tbl table database 'InnerJoined))
-> Tbl table database 'InnerJoined
-> QueryInner (Tbl table database 'InnerJoined)
forall a b. (a -> b) -> a -> b
$ Text -> Tbl table database 'InnerJoined
forall (table :: Symbol) database (leftJoined :: JoinType).
Text -> Tbl table database leftJoined
mkTableAlias Text
alias

innerJoin :: Table table database
          -> (Tbl table database 'InnerJoined ->
              Expression nullable Bool)
          -> Query database (Tbl table database 'InnerJoined)
innerJoin :: Table table database
-> (Tbl table database 'InnerJoined -> Expression nullable Bool)
-> Query database (Tbl table database 'InnerJoined)
innerJoin (Table Maybe Text
schema Text
tableName) Tbl table database 'InnerJoined -> Expression nullable Bool
joinCondition = QueryInner (Tbl table database 'InnerJoined)
-> Query database (Tbl table database 'InnerJoined)
forall database a. QueryInner a -> Query database a
Query (QueryInner (Tbl table database 'InnerJoined)
 -> Query database (Tbl table database 'InnerJoined))
-> QueryInner (Tbl table database 'InnerJoined)
-> Query database (Tbl table database 'InnerJoined)
forall a b. (a -> b) -> a -> b
$ do
  Text
alias <- Text -> QueryInner Text
newAlias (Int -> Text -> Text
Text.take Int
1 Text
tableName)
  let tblAlias :: Tbl table database 'InnerJoined
tblAlias = Text -> Tbl table database 'InnerJoined
forall (table :: Symbol) database (leftJoined :: JoinType).
Text -> Tbl table database leftJoined
mkTableAlias Text
alias
  QueryBuilder
exprBuilder <- Expression nullable Bool -> QueryInner QueryBuilder
forall (nullable :: Nullable) a.
Expression nullable a -> QueryInner QueryBuilder
runExpression (Expression nullable Bool -> QueryInner QueryBuilder)
-> Expression nullable Bool -> QueryInner QueryBuilder
forall a b. (a -> b) -> a -> b
$ Tbl table database 'InnerJoined -> Expression nullable Bool
joinCondition Tbl table database 'InnerJoined
tblAlias
  QueryClauses -> StateT ClauseState Identity ()
addClauses (QueryClauses -> StateT ClauseState Identity ())
-> QueryClauses -> StateT ClauseState Identity ()
forall a b. (a -> b) -> a -> b
$
    [QueryBuilder] -> [QueryBuilder] -> QueryClauses
H.innerJoin [Text -> QueryBuilder
H.rawSql (Text -> (Text -> Text) -> Maybe Text -> Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Text
forall a. Monoid a => a
mempty (Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
".") Maybe Text
schema Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
tableName) QueryBuilder -> QueryBuilder -> QueryBuilder
`H.as`
                 Text -> QueryBuilder
H.rawSql Text
alias]
    [QueryBuilder
exprBuilder]
  Tbl table database 'InnerJoined
-> QueryInner (Tbl table database 'InnerJoined)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Tbl table database 'InnerJoined
tblAlias

leftJoin :: Table table database
         -> (Tbl table database 'LeftJoined ->
             Expression nullable Bool)
         -> Query database (Tbl table database 'LeftJoined)
leftJoin :: Table table database
-> (Tbl table database 'LeftJoined -> Expression nullable Bool)
-> Query database (Tbl table database 'LeftJoined)
leftJoin (Table Maybe Text
schema Text
tableName) Tbl table database 'LeftJoined -> Expression nullable Bool
joinCondition = QueryInner (Tbl table database 'LeftJoined)
-> Query database (Tbl table database 'LeftJoined)
forall database a. QueryInner a -> Query database a
Query (QueryInner (Tbl table database 'LeftJoined)
 -> Query database (Tbl table database 'LeftJoined))
-> QueryInner (Tbl table database 'LeftJoined)
-> Query database (Tbl table database 'LeftJoined)
forall a b. (a -> b) -> a -> b
$ do
  Text
alias <- Text -> QueryInner Text
newAlias (Int -> Text -> Text
Text.take Int
1 Text
tableName)
  let tblAlias :: Tbl table database 'LeftJoined
tblAlias = Text -> Tbl table database 'LeftJoined
forall (table :: Symbol) database (leftJoined :: JoinType).
Text -> Tbl table database leftJoined
mkTableAlias Text
alias
  QueryBuilder
exprBuilder <- Expression nullable Bool -> QueryInner QueryBuilder
forall (nullable :: Nullable) a.
Expression nullable a -> QueryInner QueryBuilder
runExpression (Expression nullable Bool -> QueryInner QueryBuilder)
-> Expression nullable Bool -> QueryInner QueryBuilder
forall a b. (a -> b) -> a -> b
$ Tbl table database 'LeftJoined -> Expression nullable Bool
joinCondition Tbl table database 'LeftJoined
tblAlias
  QueryClauses -> StateT ClauseState Identity ()
addClauses (QueryClauses -> StateT ClauseState Identity ())
-> QueryClauses -> StateT ClauseState Identity ()
forall a b. (a -> b) -> a -> b
$
    [QueryBuilder] -> [QueryBuilder] -> QueryClauses
H.leftJoin [Text -> QueryBuilder
H.rawSql (Text -> (Text -> Text) -> Maybe Text -> Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Text
forall a. Monoid a => a
mempty (Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
".") Maybe Text
schema Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
tableName) QueryBuilder -> QueryBuilder -> QueryBuilder
`H.as`
                Text -> QueryBuilder
H.rawSql Text
alias]
    [QueryBuilder
exprBuilder]
  Tbl table database 'LeftJoined
-> QueryInner (Tbl table database 'LeftJoined)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Tbl table database 'LeftJoined
tblAlias


class SubQueryExpr (joinType :: JoinType) inExpr outExpr where
  -- The ReaderT monad takes the alias of the subquery table.
  -- The State monad uses the index of the last expression in the select clause.
  -- It generates SELECT clause expressions with aliases e1, e2, ...
  -- The outExpr contains just the output aliases.
  -- input and output should be product types, and have the same number of
  -- elements.
  subJoinGeneric :: Proxy joinType
                 -> inExpr
                 -> ReaderT Text (State Int)
                    (DList.DList SomeExpression, outExpr)

instance ( SubQueryExpr joinType (a ()) (c ())
         , SubQueryExpr joinType (b ()) (d ())) =>
         SubQueryExpr joinType ((a :*: b) ()) ((c :*: d) ()) where
  subJoinGeneric :: Proxy joinType
-> (:*:) a b ()
-> ReaderT Text (State Int) (DList SomeExpression, (:*:) c d ())
subJoinGeneric Proxy joinType
p (a ()
l :*: b ()
r) = do
    (DList SomeExpression
lftBuilder, c ()
outLft) <- Proxy joinType
-> a () -> ReaderT Text (State Int) (DList SomeExpression, c ())
forall (joinType :: JoinType) inExpr outExpr.
SubQueryExpr joinType inExpr outExpr =>
Proxy joinType
-> inExpr
-> ReaderT Text (State Int) (DList SomeExpression, outExpr)
subJoinGeneric Proxy joinType
p a ()
l
    (DList SomeExpression
rtBuilder, d ()
outRt) <- Proxy joinType
-> b () -> ReaderT Text (State Int) (DList SomeExpression, d ())
forall (joinType :: JoinType) inExpr outExpr.
SubQueryExpr joinType inExpr outExpr =>
Proxy joinType
-> inExpr
-> ReaderT Text (State Int) (DList SomeExpression, outExpr)
subJoinGeneric Proxy joinType
p b ()
r
    (DList SomeExpression, (:*:) c d ())
-> ReaderT Text (State Int) (DList SomeExpression, (:*:) c d ())
forall (f :: * -> *) a. Applicative f => a -> f a
pure (DList SomeExpression
lftBuilder DList SomeExpression
-> DList SomeExpression -> DList SomeExpression
forall a. Semigroup a => a -> a -> a
<> DList SomeExpression
rtBuilder, c ()
outLft c () -> d () -> (:*:) c d ()
forall k (f :: k -> *) (g :: k -> *) (p :: k).
f p -> g p -> (:*:) f g p
:*: d ()
outRt)
          
instance SubQueryExpr joinType (a ()) (b ()) =>
         SubQueryExpr joinType (M1 m1 m2 a ()) (M1 m3 m4 b ()) where
  subJoinGeneric :: Proxy joinType
-> M1 m1 m2 a ()
-> ReaderT Text (State Int) (DList SomeExpression, M1 m3 m4 b ())
subJoinGeneric Proxy joinType
p (M1 a ()
x) = (b () -> M1 m3 m4 b ())
-> (DList SomeExpression, b ())
-> (DList SomeExpression, M1 m3 m4 b ())
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
fmap b () -> M1 m3 m4 b ()
forall k i (c :: Meta) (f :: k -> *) (p :: k). f p -> M1 i c f p
M1 ((DList SomeExpression, b ())
 -> (DList SomeExpression, M1 m3 m4 b ()))
-> ReaderT Text (State Int) (DList SomeExpression, b ())
-> ReaderT Text (State Int) (DList SomeExpression, M1 m3 m4 b ())
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Proxy joinType
-> a () -> ReaderT Text (State Int) (DList SomeExpression, b ())
forall (joinType :: JoinType) inExpr outExpr.
SubQueryExpr joinType inExpr outExpr =>
Proxy joinType
-> inExpr
-> ReaderT Text (State Int) (DList SomeExpression, outExpr)
subJoinGeneric Proxy joinType
p a ()
x
    
instance JoinNullable joinType nullable ~ nullable2 => 
         SubQueryExpr
         joinType
         (K1 r (Expression nullable a) ())
         (K1 r (Expression nullable2 b) ())
  where
  subJoinGeneric :: Proxy joinType
-> K1 r (Expression nullable a) ()
-> ReaderT
     Text
     (State Int)
     (DList SomeExpression, K1 r (Expression nullable2 b) ())
subJoinGeneric Proxy joinType
_ (K1 (Expression QueryInner QueryBuilder
exprBuilder)) =
    (Text
 -> State
      Int (DList SomeExpression, K1 r (Expression nullable2 b) ()))
-> ReaderT
     Text
     (State Int)
     (DList SomeExpression, K1 r (Expression nullable2 b) ())
forall r (m :: * -> *) a. (r -> m a) -> ReaderT r m a
ReaderT ((Text
  -> State
       Int (DList SomeExpression, K1 r (Expression nullable2 b) ()))
 -> ReaderT
      Text
      (State Int)
      (DList SomeExpression, K1 r (Expression nullable2 b) ()))
-> (Text
    -> State
         Int (DList SomeExpression, K1 r (Expression nullable2 b) ()))
-> ReaderT
     Text
     (State Int)
     (DList SomeExpression, K1 r (Expression nullable2 b) ())
forall a b. (a -> b) -> a -> b
$ \Text
alias -> (Int
 -> ((DList SomeExpression, K1 r (Expression nullable2 b) ()), Int))
-> State
     Int (DList SomeExpression, K1 r (Expression nullable2 b) ())
forall s (m :: * -> *) a. MonadState s m => (s -> (a, s)) -> m a
state ((Int
  -> ((DList SomeExpression, K1 r (Expression nullable2 b) ()), Int))
 -> State
      Int (DList SomeExpression, K1 r (Expression nullable2 b) ()))
-> (Int
    -> ((DList SomeExpression, K1 r (Expression nullable2 b) ()), Int))
-> State
     Int (DList SomeExpression, K1 r (Expression nullable2 b) ())
forall a b. (a -> b) -> a -> b
$ \Int
i ->
    let name :: Text
name = String -> Text
Text.pack (Char
'e'Char -> String -> String
forall a. a -> [a] -> [a]
: Int -> String
forall a. Show a => a -> String
show Int
i)
    in ( ( SomeExpression -> DList SomeExpression
forall a. a -> DList a
DList.singleton (SomeExpression -> DList SomeExpression)
-> SomeExpression -> DList SomeExpression
forall a b. (a -> b) -> a -> b
$ QueryInner QueryBuilder -> SomeExpression
SomeExpression (QueryInner QueryBuilder -> SomeExpression)
-> QueryInner QueryBuilder -> SomeExpression
forall a b. (a -> b) -> a -> b
$
           (QueryBuilder -> QueryBuilder -> QueryBuilder
`H.as` Text -> QueryBuilder
H.rawSql Text
name) (QueryBuilder -> QueryBuilder)
-> QueryInner QueryBuilder -> QueryInner QueryBuilder
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> QueryInner QueryBuilder
exprBuilder
         , Expression nullable2 b -> K1 r (Expression nullable2 b) ()
forall k i c (p :: k). c -> K1 i c p
K1 (Expression nullable2 b -> K1 r (Expression nullable2 b) ())
-> Expression nullable2 b -> K1 r (Expression nullable2 b) ()
forall a b. (a -> b) -> a -> b
$ QueryInner QueryBuilder -> Expression nullable2 b
forall (nullable :: Nullable) a.
QueryInner QueryBuilder -> Expression nullable a
Expression (QueryInner QueryBuilder -> Expression nullable2 b)
-> QueryInner QueryBuilder -> Expression nullable2 b
forall a b. (a -> b) -> a -> b
$ QueryBuilder -> QueryInner QueryBuilder
forall (f :: * -> *) a. Applicative f => a -> f a
pure (QueryBuilder -> QueryInner QueryBuilder)
-> QueryBuilder -> QueryInner QueryBuilder
forall a b. (a -> b) -> a -> b
$ Text -> QueryBuilder
H.rawSql (Text -> QueryBuilder) -> Text -> QueryBuilder
forall a b. (a -> b) -> a -> b
$ Text
alias Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
"." Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
name)
       , Int
iInt -> Int -> Int
forall a. Num a => a -> a -> a
+Int
1
       )

-- update the aliases, but create and return new query clauses
runAsSubQuery :: Query database a -> QueryInner (H.QueryClauses, a)
runAsSubQuery :: Query database a -> QueryInner (QueryClauses, a)
runAsSubQuery (Query QueryInner a
sq) =
  do ClauseState QueryClauses
currentClauses Map Text Int
currentAliases <- StateT ClauseState Identity ClauseState
forall s (m :: * -> *). MonadState s m => m s
get
     let (a
subQueryRet, ClauseState QueryClauses
subQueryBody Map Text Int
newAliases) =
           QueryInner a -> ClauseState -> (a, ClauseState)
forall s a. State s a -> s -> (a, s)
runState QueryInner a
sq (QueryClauses -> Map Text Int -> ClauseState
ClauseState QueryClauses
forall a. Monoid a => a
mempty Map Text Int
currentAliases)
     ClauseState -> StateT ClauseState Identity ()
forall s (m :: * -> *). MonadState s m => s -> m ()
put (ClauseState -> StateT ClauseState Identity ())
-> ClauseState -> StateT ClauseState Identity ()
forall a b. (a -> b) -> a -> b
$ QueryClauses -> Map Text Int -> ClauseState
ClauseState QueryClauses
currentClauses Map Text Int
newAliases
     (QueryClauses, a) -> QueryInner (QueryClauses, a)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (QueryClauses
subQueryBody, a
subQueryRet)

subQueryExpr :: Query database (Expression nullable a) -> Expression nullable a
subQueryExpr :: Query database (Expression nullable a) -> Expression nullable a
subQueryExpr Query database (Expression nullable a)
sq = QueryInner QueryBuilder -> Expression nullable a
forall (nullable :: Nullable) a.
QueryInner QueryBuilder -> Expression nullable a
Expression (QueryInner QueryBuilder -> Expression nullable a)
-> QueryInner QueryBuilder -> Expression nullable a
forall a b. (a -> b) -> a -> b
$
  do (QueryClauses
subQueryBody, Expression QueryInner QueryBuilder
subQuerySelect) <- Query database (Expression nullable a)
-> QueryInner (QueryClauses, Expression nullable a)
forall database a. Query database a -> QueryInner (QueryClauses, a)
runAsSubQuery Query database (Expression nullable a)
sq 
     QueryBuilder
selectBuilder <- QueryInner QueryBuilder
subQuerySelect
     QueryBuilder -> QueryInner QueryBuilder
forall (f :: * -> *) a. Applicative f => a -> f a
pure (QueryBuilder -> QueryInner QueryBuilder)
-> QueryBuilder -> QueryInner QueryBuilder
forall a b. (a -> b) -> a -> b
$ Query () -> QueryBuilder
forall a. ToQueryBuilder a => a -> QueryBuilder
H.subQuery (Query () -> QueryBuilder) -> Query () -> QueryBuilder
forall a b. (a -> b) -> a -> b
$ Selector () -> QueryClauses -> Query ()
forall a. Selector a -> QueryClauses -> Query a
H.select ([QueryBuilder] -> Selector ()
H.values_ [QueryBuilder
selectBuilder]) QueryClauses
subQueryBody

-- 
subJoinBody :: (Generic inExprs,
              Generic outExprs,
              SubQueryExpr joinType (Rep inExprs ()) (Rep outExprs ()))
            => Proxy joinType
            -> Query database inExprs
            -> QueryInner (H.QueryBuilder, outExprs)
subJoinBody :: Proxy joinType
-> Query database inExprs -> QueryInner (QueryBuilder, outExprs)
subJoinBody Proxy joinType
p Query database inExprs
sq = do
  Text
sqAlias <- Text -> QueryInner Text
newAlias Text
"sq"
  (QueryClauses
subQueryBody, inExprs
sqExprs) <- Query database inExprs -> QueryInner (QueryClauses, inExprs)
forall database a. Query database a -> QueryInner (QueryClauses, a)
runAsSubQuery Query database inExprs
sq
  let from' :: Generic inExprs => inExprs -> Rep inExprs ()
      from' :: inExprs -> Rep inExprs ()
from' = inExprs -> Rep inExprs ()
forall a x. Generic a => a -> Rep a x
Generics.from
      to' :: Generic outExpr => Rep outExpr () -> outExpr
      to' :: Rep outExpr () -> outExpr
to' = Rep outExpr () -> outExpr
forall a x. Generic a => Rep a x -> a
Generics.to
      (DList SomeExpression
selectExprs, Rep outExprs ()
outExprRep) = (State Int (DList SomeExpression, Rep outExprs ())
 -> Int -> (DList SomeExpression, Rep outExprs ()))
-> Int
-> State Int (DList SomeExpression, Rep outExprs ())
-> (DList SomeExpression, Rep outExprs ())
forall a b c. (a -> b -> c) -> b -> a -> c
flip State Int (DList SomeExpression, Rep outExprs ())
-> Int -> (DList SomeExpression, Rep outExprs ())
forall s a. State s a -> s -> a
evalState Int
1 (State Int (DList SomeExpression, Rep outExprs ())
 -> (DList SomeExpression, Rep outExprs ()))
-> State Int (DList SomeExpression, Rep outExprs ())
-> (DList SomeExpression, Rep outExprs ())
forall a b. (a -> b) -> a -> b
$
                                  (ReaderT Text (State Int) (DList SomeExpression, Rep outExprs ())
 -> Text -> State Int (DList SomeExpression, Rep outExprs ()))
-> Text
-> ReaderT Text (State Int) (DList SomeExpression, Rep outExprs ())
-> State Int (DList SomeExpression, Rep outExprs ())
forall a b c. (a -> b -> c) -> b -> a -> c
flip ReaderT Text (State Int) (DList SomeExpression, Rep outExprs ())
-> Text -> State Int (DList SomeExpression, Rep outExprs ())
forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
runReaderT Text
sqAlias (ReaderT Text (State Int) (DList SomeExpression, Rep outExprs ())
 -> State Int (DList SomeExpression, Rep outExprs ()))
-> ReaderT Text (State Int) (DList SomeExpression, Rep outExprs ())
-> State Int (DList SomeExpression, Rep outExprs ())
forall a b. (a -> b) -> a -> b
$
                                  Proxy joinType
-> Rep inExprs ()
-> ReaderT Text (State Int) (DList SomeExpression, Rep outExprs ())
forall (joinType :: JoinType) inExpr outExpr.
SubQueryExpr joinType inExpr outExpr =>
Proxy joinType
-> inExpr
-> ReaderT Text (State Int) (DList SomeExpression, outExpr)
subJoinGeneric Proxy joinType
p (Rep inExprs ()
 -> ReaderT
      Text (State Int) (DList SomeExpression, Rep outExprs ()))
-> Rep inExprs ()
-> ReaderT Text (State Int) (DList SomeExpression, Rep outExprs ())
forall a b. (a -> b) -> a -> b
$
                                  inExprs -> Rep inExprs ()
forall a. Generic a => a -> Rep a ()
from' inExprs
sqExprs
      outExpr :: outExprs
outExpr = Rep outExprs () -> outExprs
forall outExpr. Generic outExpr => Rep outExpr () -> outExpr
to' Rep outExprs ()
outExprRep
  [QueryBuilder]
selectBuilder <- DList QueryBuilder -> [QueryBuilder]
forall a. DList a -> [a]
DList.toList (DList QueryBuilder -> [QueryBuilder])
-> StateT ClauseState Identity (DList QueryBuilder)
-> StateT ClauseState Identity [QueryBuilder]
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> (SomeExpression -> QueryInner QueryBuilder)
-> DList SomeExpression
-> StateT ClauseState Identity (DList QueryBuilder)
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse SomeExpression -> QueryInner QueryBuilder
runSomeExpression DList SomeExpression
selectExprs
  (QueryBuilder, outExprs) -> QueryInner (QueryBuilder, outExprs)
forall (f :: * -> *) a. Applicative f => a -> f a
pure ( Query () -> QueryBuilder
forall a. ToQueryBuilder a => a -> QueryBuilder
H.subQuery (Query () -> QueryBuilder) -> Query () -> QueryBuilder
forall a b. (a -> b) -> a -> b
$ Selector () -> QueryClauses -> Query ()
forall a. Selector a -> QueryClauses -> Query a
H.select ([QueryBuilder] -> Selector ()
H.values_ [QueryBuilder]
selectBuilder) QueryClauses
subQueryBody
       , outExprs
outExpr)

joinSubQuery :: (Generic inExprs,
                 Generic outExprs,
                 SubQueryExpr 'InnerJoined (Rep inExprs ()) (Rep outExprs ()))
             => Query database inExprs
             -> (outExprs -> Expression nullable Bool)
             -> Query database outExprs
joinSubQuery :: Query database inExprs
-> (outExprs -> Expression nullable Bool)
-> Query database outExprs
joinSubQuery Query database inExprs
sq outExprs -> Expression nullable Bool
condition = QueryInner outExprs -> Query database outExprs
forall database a. QueryInner a -> Query database a
Query (QueryInner outExprs -> Query database outExprs)
-> QueryInner outExprs -> Query database outExprs
forall a b. (a -> b) -> a -> b
$ do
  (QueryBuilder
subQueryBody, outExprs
outExpr) <- Proxy 'InnerJoined
-> Query database inExprs -> QueryInner (QueryBuilder, outExprs)
forall inExprs outExprs (joinType :: JoinType) database.
(Generic inExprs, Generic outExprs,
 SubQueryExpr joinType (Rep inExprs ()) (Rep outExprs ())) =>
Proxy joinType
-> Query database inExprs -> QueryInner (QueryBuilder, outExprs)
subJoinBody (Proxy 'InnerJoined
forall k (t :: k). Proxy t
Proxy :: Proxy 'InnerJoined) Query database inExprs
sq
  QueryBuilder
conditionBuilder <- Expression nullable Bool -> QueryInner QueryBuilder
forall (nullable :: Nullable) a.
Expression nullable a -> QueryInner QueryBuilder
runExpression (Expression nullable Bool -> QueryInner QueryBuilder)
-> Expression nullable Bool -> QueryInner QueryBuilder
forall a b. (a -> b) -> a -> b
$ outExprs -> Expression nullable Bool
condition outExprs
outExpr
  QueryClauses -> StateT ClauseState Identity ()
addClauses (QueryClauses -> StateT ClauseState Identity ())
-> QueryClauses -> StateT ClauseState Identity ()
forall a b. (a -> b) -> a -> b
$ [QueryBuilder] -> [QueryBuilder] -> QueryClauses
H.innerJoin [QueryBuilder
subQueryBody] [QueryBuilder
conditionBuilder]
  outExprs -> QueryInner outExprs
forall (f :: * -> *) a. Applicative f => a -> f a
pure outExprs
outExpr

leftJoinSubQuery :: (Generic inExprs,
                     Generic outExprs,
                     SubQueryExpr 'LeftJoined (Rep inExprs ()) (Rep outExprs ()))
                 => Query database inExprs
                 -> (outExprs -> Expression nullable Bool)
                 -> Query database outExprs
leftJoinSubQuery :: Query database inExprs
-> (outExprs -> Expression nullable Bool)
-> Query database outExprs
leftJoinSubQuery Query database inExprs
sq outExprs -> Expression nullable Bool
condition = QueryInner outExprs -> Query database outExprs
forall database a. QueryInner a -> Query database a
Query (QueryInner outExprs -> Query database outExprs)
-> QueryInner outExprs -> Query database outExprs
forall a b. (a -> b) -> a -> b
$ do
  (QueryBuilder
subQueryBody, outExprs
outExpr) <- Proxy 'LeftJoined
-> Query database inExprs -> QueryInner (QueryBuilder, outExprs)
forall inExprs outExprs (joinType :: JoinType) database.
(Generic inExprs, Generic outExprs,
 SubQueryExpr joinType (Rep inExprs ()) (Rep outExprs ())) =>
Proxy joinType
-> Query database inExprs -> QueryInner (QueryBuilder, outExprs)
subJoinBody (Proxy 'LeftJoined
forall k (t :: k). Proxy t
Proxy :: Proxy 'LeftJoined) Query database inExprs
sq
  QueryBuilder
conditionBuilder <- Expression nullable Bool -> QueryInner QueryBuilder
forall (nullable :: Nullable) a.
Expression nullable a -> QueryInner QueryBuilder
runExpression (Expression nullable Bool -> QueryInner QueryBuilder)
-> Expression nullable Bool -> QueryInner QueryBuilder
forall a b. (a -> b) -> a -> b
$ outExprs -> Expression nullable Bool
condition outExprs
outExpr
  QueryClauses -> StateT ClauseState Identity ()
addClauses (QueryClauses -> StateT ClauseState Identity ())
-> QueryClauses -> StateT ClauseState Identity ()
forall a b. (a -> b) -> a -> b
$ [QueryBuilder] -> [QueryBuilder] -> QueryClauses
H.leftJoin [QueryBuilder
subQueryBody] [QueryBuilder
conditionBuilder]
  outExprs -> QueryInner outExprs
forall (f :: * -> *) a. Applicative f => a -> f a
pure outExprs
outExpr

fromSubQuery :: (Generic inExprs,
                 Generic outExprs,
                 SubQueryExpr 'LeftJoined (Rep inExprs ()) (Rep outExprs ()))
             => Query database inExprs
             -> Query database outExprs
fromSubQuery :: Query database inExprs -> Query database outExprs
fromSubQuery Query database inExprs
sq = QueryInner outExprs -> Query database outExprs
forall database a. QueryInner a -> Query database a
Query (QueryInner outExprs -> Query database outExprs)
-> QueryInner outExprs -> Query database outExprs
forall a b. (a -> b) -> a -> b
$ do              
  (QueryBuilder
subQueryBody, outExprs
outExpr) <- Proxy 'LeftJoined
-> Query database inExprs -> QueryInner (QueryBuilder, outExprs)
forall inExprs outExprs (joinType :: JoinType) database.
(Generic inExprs, Generic outExprs,
 SubQueryExpr joinType (Rep inExprs ()) (Rep outExprs ())) =>
Proxy joinType
-> Query database inExprs -> QueryInner (QueryBuilder, outExprs)
subJoinBody (Proxy 'LeftJoined
forall k (t :: k). Proxy t
Proxy :: Proxy 'LeftJoined) Query database inExprs
sq 
  QueryClauses -> StateT ClauseState Identity ()
addClauses (QueryClauses -> StateT ClauseState Identity ())
-> QueryClauses -> StateT ClauseState Identity ()
forall a b. (a -> b) -> a -> b
$ QueryBuilder -> QueryClauses
H.from QueryBuilder
subQueryBody
  outExprs -> QueryInner outExprs
forall (f :: * -> *) a. Applicative f => a -> f a
pure outExprs
outExpr

where_ :: Expression nullable Bool -> Query database ()
where_ :: Expression nullable Bool -> Query database ()
where_ Expression nullable Bool
expr = StateT ClauseState Identity () -> Query database ()
forall database a. QueryInner a -> Query database a
Query (StateT ClauseState Identity () -> Query database ())
-> StateT ClauseState Identity () -> Query database ()
forall a b. (a -> b) -> a -> b
$ do
  QueryBuilder
exprBuilder <- Expression nullable Bool -> QueryInner QueryBuilder
forall (nullable :: Nullable) a.
Expression nullable a -> QueryInner QueryBuilder
runExpression Expression nullable Bool
expr
  QueryClauses -> StateT ClauseState Identity ()
addClauses (QueryClauses -> StateT ClauseState Identity ())
-> QueryClauses -> StateT ClauseState Identity ()
forall a b. (a -> b) -> a -> b
$ [QueryBuilder] -> QueryClauses
H.where_ [QueryBuilder
exprBuilder]

groupBy_ :: [SomeExpression] -> Query database ()
groupBy_ :: [SomeExpression] -> Query database ()
groupBy_ [SomeExpression]
columns = StateT ClauseState Identity () -> Query database ()
forall database a. QueryInner a -> Query database a
Query (StateT ClauseState Identity () -> Query database ())
-> StateT ClauseState Identity () -> Query database ()
forall a b. (a -> b) -> a -> b
$ do
  [QueryBuilder]
columnBuilders <- (SomeExpression -> QueryInner QueryBuilder)
-> [SomeExpression] -> StateT ClauseState Identity [QueryBuilder]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse SomeExpression -> QueryInner QueryBuilder
runSomeExpression [SomeExpression]
columns
  QueryClauses -> StateT ClauseState Identity ()
addClauses (QueryClauses -> StateT ClauseState Identity ())
-> QueryClauses -> StateT ClauseState Identity ()
forall a b. (a -> b) -> a -> b
$ [QueryBuilder] -> QueryClauses
H.groupBy_ [QueryBuilder]
columnBuilders

having :: Expression nullable Bool -> Query database ()
having :: Expression nullable Bool -> Query database ()
having Expression nullable Bool
expr = StateT ClauseState Identity () -> Query database ()
forall database a. QueryInner a -> Query database a
Query (StateT ClauseState Identity () -> Query database ())
-> StateT ClauseState Identity () -> Query database ()
forall a b. (a -> b) -> a -> b
$ do
  QueryBuilder
exprBuilder <- Expression nullable Bool -> QueryInner QueryBuilder
forall (nullable :: Nullable) a.
Expression nullable a -> QueryInner QueryBuilder
runExpression Expression nullable Bool
expr
  QueryClauses -> StateT ClauseState Identity ()
addClauses (QueryClauses -> StateT ClauseState Identity ())
-> QueryClauses -> StateT ClauseState Identity ()
forall a b. (a -> b) -> a -> b
$ [QueryBuilder] -> QueryClauses
H.having [QueryBuilder
exprBuilder]

orderBy :: [QueryOrdering] -> Query database ()
orderBy :: [QueryOrdering] -> Query database ()
orderBy [QueryOrdering]
ordering = StateT ClauseState Identity () -> Query database ()
forall database a. QueryInner a -> Query database a
Query (StateT ClauseState Identity () -> Query database ())
-> StateT ClauseState Identity () -> Query database ()
forall a b. (a -> b) -> a -> b
$
  do [QueryOrdering]
newOrdering <- (QueryOrdering -> StateT ClauseState Identity QueryOrdering)
-> [QueryOrdering] -> StateT ClauseState Identity [QueryOrdering]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse QueryOrdering -> StateT ClauseState Identity QueryOrdering
orderingToH [QueryOrdering]
ordering
     QueryClauses -> StateT ClauseState Identity ()
addClauses (QueryClauses -> StateT ClauseState Identity ())
-> QueryClauses -> StateT ClauseState Identity ()
forall a b. (a -> b) -> a -> b
$ [QueryOrdering] -> QueryClauses
H.orderBy [QueryOrdering]
newOrdering
  where orderingToH :: QueryOrdering -> StateT ClauseState Identity QueryOrdering
orderingToH (Asc SomeExpression
x) = QueryBuilder -> QueryOrdering
H.Asc (QueryBuilder -> QueryOrdering)
-> QueryInner QueryBuilder
-> StateT ClauseState Identity QueryOrdering
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SomeExpression -> QueryInner QueryBuilder
runSomeExpression SomeExpression
x
        orderingToH (Desc SomeExpression
x) = QueryBuilder -> QueryOrdering
H.Desc (QueryBuilder -> QueryOrdering)
-> QueryInner QueryBuilder
-> StateT ClauseState Identity QueryOrdering
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> SomeExpression -> QueryInner QueryBuilder
runSomeExpression SomeExpression
x

limit :: Int -> Query database ()
limit :: Int -> Query database ()
limit Int
count = StateT ClauseState Identity () -> Query database ()
forall database a. QueryInner a -> Query database a
Query (StateT ClauseState Identity () -> Query database ())
-> StateT ClauseState Identity () -> Query database ()
forall a b. (a -> b) -> a -> b
$ QueryClauses -> StateT ClauseState Identity ()
addClauses (QueryClauses -> StateT ClauseState Identity ())
-> QueryClauses -> StateT ClauseState Identity ()
forall a b. (a -> b) -> a -> b
$ Int -> QueryClauses
H.limit Int
count

limitOffset :: Int -> Int -> Query database ()
limitOffset :: Int -> Int -> Query database ()
limitOffset Int
count Int
offset = StateT ClauseState Identity () -> Query database ()
forall database a. QueryInner a -> Query database a
Query (StateT ClauseState Identity () -> Query database ())
-> StateT ClauseState Identity () -> Query database ()
forall a b. (a -> b) -> a -> b
$ QueryClauses -> StateT ClauseState Identity ()
addClauses (QueryClauses -> StateT ClauseState Identity ())
-> QueryClauses -> StateT ClauseState Identity ()
forall a b. (a -> b) -> a -> b
$ Int -> Int -> QueryClauses
H.limitOffset Int
count Int
offset

newtype Into database (table :: Symbol) =
  Into { Into database table -> QueryInner (Text, QueryBuilder)
runInto :: QueryInner (Text, H.QueryBuilder) }

exprInto :: CheckExprNullable exprNullable fieldNullable
         => Expression exprNullable a ->
            Field table database fieldNullable a ->
            Into database table
exprInto :: Expression exprNullable a
-> Field table database fieldNullable a -> Into database table
exprInto Expression exprNullable a
expr (Field Text
_ Text
fieldName) =
  QueryInner (Text, QueryBuilder) -> Into database table
forall database (table :: Symbol).
QueryInner (Text, QueryBuilder) -> Into database table
Into (QueryInner (Text, QueryBuilder) -> Into database table)
-> QueryInner (Text, QueryBuilder) -> Into database table
forall a b. (a -> b) -> a -> b
$ (Text
fieldName,) (QueryBuilder -> (Text, QueryBuilder))
-> QueryInner QueryBuilder -> QueryInner (Text, QueryBuilder)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Expression exprNullable a -> QueryInner QueryBuilder
forall (nullable :: Nullable) a.
Expression nullable a -> QueryInner QueryBuilder
runExpression Expression exprNullable a
expr

insertSelect :: Table table database
             -> Query database [Into database table]
             -> H.Command
insertSelect :: Table table database
-> Query database [Into database table] -> Command
insertSelect (Table Maybe Text
schema Text
tbl) (Query QueryInner [Into database table]
query) =
  QueryBuilder
-> [QueryBuilder] -> [QueryBuilder] -> QueryClauses -> Command
H.insertSelect (Text -> QueryBuilder
H.rawSql (Text -> (Text -> Text) -> Maybe Text -> Text
forall b a. b -> (a -> b) -> Maybe a -> b
maybe Text
forall a. Monoid a => a
mempty (Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
".") Maybe Text
schema Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
tbl))
  (((Text, QueryBuilder) -> QueryBuilder)
-> [(Text, QueryBuilder)] -> [QueryBuilder]
forall a b. (a -> b) -> [a] -> [b]
map (Text -> QueryBuilder
H.rawSql (Text -> QueryBuilder)
-> ((Text, QueryBuilder) -> Text)
-> (Text, QueryBuilder)
-> QueryBuilder
forall b c a. (b -> c) -> (a -> b) -> a -> c
. (Text, QueryBuilder) -> Text
forall a b. (a, b) -> a
fst) [(Text, QueryBuilder)]
intos)
  (((Text, QueryBuilder) -> QueryBuilder)
-> [(Text, QueryBuilder)] -> [QueryBuilder]
forall a b. (a -> b) -> [a] -> [b]
map (Text, QueryBuilder) -> QueryBuilder
forall a b. (a, b) -> b
snd [(Text, QueryBuilder)]
intos) QueryClauses
clauses
  where ([(Text, QueryBuilder)]
intos, ClauseState QueryClauses
clauses Map Text Int
_) =
          State ClauseState [(Text, QueryBuilder)]
-> ClauseState -> ([(Text, QueryBuilder)], ClauseState)
forall s a. State s a -> s -> (a, s)
runState (QueryInner [Into database table]
query QueryInner [Into database table]
-> ([Into database table]
    -> State ClauseState [(Text, QueryBuilder)])
-> State ClauseState [(Text, QueryBuilder)]
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Into database table -> QueryInner (Text, QueryBuilder))
-> [Into database table]
-> State ClauseState [(Text, QueryBuilder)]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse Into database table -> QueryInner (Text, QueryBuilder)
forall database (table :: Symbol).
Into database table -> QueryInner (Text, QueryBuilder)
runInto) ClauseState
emptyClauseState


{- TODO:

DML values:

values :: Insertable database a inExpres outExprs =>
  inExprs -> [a] -> Query database outExprs

specialized:

(Person -> Int, Person -> Maybe String) ->
  [Person] -> 
  Query database (Expression nullable Int, Expression 'Nullable String)

-}