{-# 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 DeriveFunctor #-}

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

    -- * Selectors
    Selector, sel, selMaybe,

    -- * Expressions
    Expression, SomeExpression, someExpr, Operator, 
    arg, argMaybe, isNull, isNotNull, nullable, notNull, orNull, unlessNull,
    cast, unsafeCast, op, fun1, fun2, fun3, (=.), (/=.), (>.), (<.), (>=.),
    (<=.), (&&.), (||.), substr, true_, false_, in_, notIn_, 
    
    -- * Clauses
    from, fromSubQuery, innerJoin, leftJoin, joinSubQuery, leftJoinSubQuery,
    where_, groupBy_, having, orderBy, limit, limitOffset,

    -- * Insertion
    Insertor, insertValues, insertUpdateValues, insertSelect, insertData,
    skipInsert, into,
    lensInto, maybeLensInto, opticInto, maybeOpticInto, insertOne, exprInto,
    Into,

    -- * Update
    Updator(..), update,

    -- * imported from Database.MySQL.Hasqlator
    H.Getter, H.ToSql, H.FromSql, subQueryExpr, H.executeCommand, 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.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
import qualified Database.MySQL.Base as MySQL
import Optics.Core hiding (lens)

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

-- | 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 Alias table database (joinType :: JoinType) =
  Alias { Alias table database joinType
-> forall (fieldNull :: Nullable) a.
   Field table database fieldNull a
   -> Expression (JoinNullable joinType fieldNull) a
getTableAlias ::
          forall fieldNull a .
          Field table database fieldNull a ->
          Expression (JoinNullable joinType fieldNull) 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)

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

infixl 9 @@

untypeQuery :: Query database (Selector a) -> H.Query a
untypeQuery :: Query database (Selector a) -> Query a
untypeQuery (Query QueryInner (Selector a)
query) =
  let (Selector a
selector, ClauseState
clauseState) =
        State ClauseState (Selector a)
-> ClauseState -> (Selector a, ClauseState)
forall s a. State s a -> s -> (a, s)
runState (do (Selector State ClauseState (Selector a)
sel) <- QueryInner (Selector a)
query; State ClauseState (Selector a)
sel) ClauseState
emptyClauseState
  in 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

executeQuery :: MySQL.MySQLConn -> Query database (Selector a) -> IO [a]
executeQuery :: MySQLConn -> Query database (Selector a) -> IO [a]
executeQuery MySQLConn
conn Query database (Selector a)
query = MySQLConn -> Query a -> IO [a]
forall a. MySQLConn -> Query a -> IO [a]
H.executeQuery MySQLConn
conn (Query database (Selector a) -> Query a
forall database a. Query database (Selector a) -> Query a
untypeQuery Query database (Selector a)
query)
  
-- | Create an expression from an aliased table and a field.
(@@) :: Alias table database (joinType :: JoinType)
     -> Field table database fieldNull a
     -> Expression (JoinNullable joinType fieldNull) a
@@ :: Alias table database joinType
-> Field table database fieldNull a
-> Expression (JoinNullable joinType fieldNull) a
(@@) = Alias table database joinType
-> Field table database fieldNull a
-> Expression (JoinNullable joinType fieldNull) a
forall (table :: Symbol) database (joinType :: JoinType).
Alias table database joinType
-> forall (fieldNull :: Nullable) a.
   Field table database fieldNull a
   -> Expression (JoinNullable joinType fieldNull) a
getTableAlias  
 
mkTableAlias :: Text -> Alias table database leftJoined
mkTableAlias :: Text -> Alias table database leftJoined
mkTableAlias Text
tableName = (forall (fieldNull :: Nullable) a.
 Field table database fieldNull a
 -> Expression (JoinNullable leftJoined fieldNull) a)
-> Alias table database leftJoined
forall (table :: Symbol) database (joinType :: JoinType).
(forall (fieldNull :: Nullable) a.
 Field table database fieldNull a
 -> Expression (JoinNullable joinType fieldNull) a)
-> Alias table database joinType
Alias ((forall (fieldNull :: Nullable) a.
  Field table database fieldNull a
  -> Expression (JoinNullable leftJoined fieldNull) a)
 -> Alias table database leftJoined)
-> (forall (fieldNull :: Nullable) a.
    Field table database fieldNull a
    -> Expression (JoinNullable leftJoined fieldNull) a)
-> Alias table database leftJoined
forall a b. (a -> b) -> a -> b
$ \Field table database fieldNull a
field ->
  QueryInner QueryBuilder
-> Expression (JoinNullable leftJoined fieldNull) a
forall (nullable :: Nullable) a.
QueryInner QueryBuilder -> Expression nullable a
Expression (QueryInner QueryBuilder
 -> Expression (JoinNullable leftJoined fieldNull) a)
-> QueryInner QueryBuilder
-> Expression (JoinNullable leftJoined fieldNull) 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
<> Field table database fieldNull a -> Text
forall (table :: Symbol) database (nullable :: Nullable) a.
Field table database nullable a -> Text
fieldName Field table database fieldNull a
field

emptyAlias :: Alias table database leftJoined
emptyAlias :: Alias table database leftJoined
emptyAlias = (forall (fieldNull :: Nullable) a.
 Field table database fieldNull a
 -> Expression (JoinNullable leftJoined fieldNull) a)
-> Alias table database leftJoined
forall (table :: Symbol) database (joinType :: JoinType).
(forall (fieldNull :: Nullable) a.
 Field table database fieldNull a
 -> Expression (JoinNullable joinType fieldNull) a)
-> Alias table database joinType
Alias ((forall (fieldNull :: Nullable) a.
  Field table database fieldNull a
  -> Expression (JoinNullable leftJoined fieldNull) a)
 -> Alias table database leftJoined)
-> (forall (fieldNull :: Nullable) a.
    Field table database fieldNull a
    -> Expression (JoinNullable leftJoined fieldNull) a)
-> Alias table database leftJoined
forall a b. (a -> b) -> a -> b
$ \Field table database fieldNull a
field ->
  QueryInner QueryBuilder
-> Expression (JoinNullable leftJoined fieldNull) a
forall (nullable :: Nullable) a.
QueryInner QueryBuilder -> Expression nullable a
Expression (QueryInner QueryBuilder
 -> Expression (JoinNullable leftJoined fieldNull) a)
-> QueryInner QueryBuilder
-> Expression (JoinNullable leftJoined fieldNull) 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
$ Field table database fieldNull a -> Text
forall (table :: Symbol) database (nullable :: Nullable) a.
Field table database nullable a -> Text
fieldName Field table database fieldNull a
field

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

infixr 3 &&., ||.
infix 4 <., >., >=., <=., =., /=.

(=.), (/=.), (>.), (<.), (>=.), (<=.) :: 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.&&.)

isNull :: Expression nullable a -> Expression 'NotNull Bool
isNull :: Expression nullable a -> Expression 'NotNull Bool
isNull (Expression QueryInner QueryBuilder
e) = QueryInner QueryBuilder -> Expression 'NotNull Bool
forall (nullable :: Nullable) a.
QueryInner QueryBuilder -> Expression nullable a
Expression (QueryInner QueryBuilder -> Expression 'NotNull Bool)
-> QueryInner QueryBuilder -> Expression 'NotNull Bool
forall a b. (a -> b) -> a -> b
$ QueryBuilder -> QueryBuilder
H.isNull (QueryBuilder -> QueryBuilder)
-> QueryInner QueryBuilder -> QueryInner QueryBuilder
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> QueryInner QueryBuilder
e

isNotNull :: Expression 'Nullable a -> Expression 'NotNull Bool
isNotNull :: Expression 'Nullable a -> Expression 'NotNull Bool
isNotNull (Expression QueryInner QueryBuilder
e) = QueryInner QueryBuilder -> Expression 'NotNull Bool
forall (nullable :: Nullable) a.
QueryInner QueryBuilder -> Expression nullable a
Expression (QueryInner QueryBuilder -> Expression 'NotNull Bool)
-> QueryInner QueryBuilder -> Expression 'NotNull Bool
forall a b. (a -> b) -> a -> b
$ QueryBuilder -> QueryBuilder
H.isNotNull (QueryBuilder -> QueryBuilder)
-> QueryInner QueryBuilder -> QueryInner QueryBuilder
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> QueryInner QueryBuilder
e

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
$ QueryBuilder
H.false_
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
$ QueryBuilder
H.true_

in_ :: Expression nullable a -> [Expression nullable a]
    -> Expression nullable Bool
in_ :: Expression nullable a
-> [Expression nullable a] -> Expression nullable Bool
in_ Expression nullable a
e [Expression nullable a]
es = 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 -> [QueryBuilder] -> QueryBuilder)
-> QueryInner QueryBuilder
-> StateT ClauseState Identity [QueryBuilder]
-> QueryInner QueryBuilder
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 QueryBuilder -> [QueryBuilder] -> QueryBuilder
H.in_ (Expression nullable a -> QueryInner QueryBuilder
forall (nullable :: Nullable) a.
Expression nullable a -> QueryInner QueryBuilder
runExpression Expression nullable a
e) ((Expression nullable a -> QueryInner QueryBuilder)
-> [Expression nullable a]
-> StateT ClauseState Identity [QueryBuilder]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse Expression nullable a -> QueryInner QueryBuilder
forall (nullable :: Nullable) a.
Expression nullable a -> QueryInner QueryBuilder
runExpression [Expression nullable a]
es)

notIn_ :: Expression nullable a -> [Expression nullable a]
       -> Expression nullable Bool
notIn_ :: Expression nullable a
-> [Expression nullable a] -> Expression nullable Bool
notIn_ Expression nullable a
e [Expression nullable a]
es = 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 -> [QueryBuilder] -> QueryBuilder)
-> QueryInner QueryBuilder
-> StateT ClauseState Identity [QueryBuilder]
-> QueryInner QueryBuilder
forall (f :: * -> *) a b c.
Applicative f =>
(a -> b -> c) -> f a -> f b -> f c
liftA2 QueryBuilder -> [QueryBuilder] -> QueryBuilder
H.notIn_ (Expression nullable a -> QueryInner QueryBuilder
forall (nullable :: Nullable) a.
Expression nullable a -> QueryInner QueryBuilder
runExpression Expression nullable a
e) ((Expression nullable a -> QueryInner QueryBuilder)
-> [Expression nullable a]
-> StateT ClauseState Identity [QueryBuilder]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse Expression nullable a -> QueryInner QueryBuilder
forall (nullable :: Nullable) a.
Expression nullable a -> QueryInner QueryBuilder
runExpression [Expression nullable a]
es)

-- | 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

-- | ensure expression is not null
notNull :: Expression 'NotNull a -> Expression 'NotNull a
notNull :: Expression 'NotNull a -> Expression 'NotNull a
notNull = Expression 'NotNull a -> Expression 'NotNull a
forall a. a -> a
id

-- | Return a true expression if the given expression is NULL (using
-- the IS NULL sql test), or pass the expression (coerced to
-- 'NotNull) to the given test.
orNull :: Expression nullable a
       -> (Expression 'NotNull a -> Expression 'NotNull Bool)
       -> Expression 'NotNull Bool
orNull :: Expression nullable a
-> (Expression 'NotNull a -> Expression 'NotNull Bool)
-> Expression 'NotNull Bool
orNull Expression nullable a
e Expression 'NotNull a -> Expression 'NotNull Bool
f = Expression nullable a -> Expression 'NotNull Bool
forall (nullable :: Nullable) a.
Expression nullable a -> Expression 'NotNull Bool
isNull Expression nullable a
e Expression 'NotNull Bool
-> Expression 'NotNull Bool -> Expression 'NotNull Bool
Operator Bool Bool Bool
||. Expression 'NotNull a -> Expression 'NotNull Bool
f (Expression nullable a -> Expression 'NotNull a
coerce Expression nullable a
e)

-- | Perform test if given expression is not NULL
unlessNull :: Expression nullable a
           -> (Expression 'NotNull a -> Expression 'NotNull Bool)
           -> Expression 'NotNull Bool
unlessNull :: Expression nullable a
-> (Expression 'NotNull a -> Expression 'NotNull Bool)
-> Expression 'NotNull Bool
unlessNull Expression nullable a
e Expression 'NotNull a -> Expression 'NotNull Bool
f = Expression 'NotNull a -> Expression 'NotNull Bool
f (Expression nullable a -> Expression 'NotNull a
coerce Expression nullable a
e)

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

fieldName :: Field table database nullable a -> Text
fieldName :: Field table database nullable a -> Text
fieldName (Field Text
_ Text
fn) = Text
fn

insertOne :: H.ToSql a
          => Field table database 'NotNull fieldType
          -> Insertor table database a
insertOne :: Field table database 'NotNull 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 'NotNull fieldType -> Insertor a)
-> Field table database 'NotNull 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 'NotNull fieldType -> Text)
-> Field table database 'NotNull fieldType
-> Insertor a
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Field table database 'NotNull fieldType -> Text
forall (table :: Symbol) database (nullable :: Nullable) a.
Field table database nullable a -> Text
fieldName

insertOneMaybe :: H.ToSql a
               => Field table database 'Nullable fieldType
               -> Insertor table database (Maybe a)
insertOneMaybe :: Field table database 'Nullable fieldType
-> Insertor table database (Maybe a)
insertOneMaybe = Insertor (Maybe a) -> Insertor table database (Maybe a)
forall (table :: Symbol) database a.
Insertor a -> Insertor table database a
Insertor (Insertor (Maybe a) -> Insertor table database (Maybe a))
-> (Field table database 'Nullable fieldType -> Insertor (Maybe a))
-> Field table database 'Nullable fieldType
-> Insertor table database (Maybe a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Text -> Insertor (Maybe a)
forall a. ToSql a => Text -> Insertor a
H.insertOne (Text -> Insertor (Maybe a))
-> (Field table database 'Nullable fieldType -> Text)
-> Field table database 'Nullable fieldType
-> Insertor (Maybe a)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Field table database 'Nullable fieldType -> Text
forall (table :: Symbol) database (nullable :: Nullable) a.
Field table database nullable a -> Text
fieldName

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 H.ToSql b =>
         InsertGeneric tbl db (K1 r (Field tbl db 'NotNull a) ()) (K1 r b ())
  where insertDataGeneric :: K1 r (Field tbl db 'NotNull 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 'NotNull a) () -> Insertor tbl db b)
-> K1 r (Field tbl db 'NotNull a) ()
-> Insertor tbl db (K1 r b ())
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Field tbl db 'NotNull a -> Insertor tbl db b
forall a (table :: Symbol) database fieldType.
ToSql a =>
Field table database 'NotNull fieldType
-> Insertor table database a
insertOne (Field tbl db 'NotNull a -> Insertor tbl db b)
-> (K1 r (Field tbl db 'NotNull a) () -> Field tbl db 'NotNull a)
-> K1 r (Field tbl db 'NotNull a) ()
-> Insertor tbl db b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. K1 r (Field tbl db 'NotNull a) () -> Field tbl db 'NotNull a
forall i c k (p :: k). K1 i c p -> c
unK1

instance H.ToSql b =>
         InsertGeneric tbl db (K1 r (Field tbl db 'Nullable a) ())
         (K1 r (Maybe b) ())
  where insertDataGeneric :: K1 r (Field tbl db 'Nullable a) ()
-> Insertor tbl db (K1 r (Maybe b) ())
insertDataGeneric = (K1 r (Maybe b) () -> Maybe b)
-> Insertor tbl db (Maybe b) -> Insertor tbl db (K1 r (Maybe b) ())
forall (f :: * -> *) a b. Contravariant f => (a -> b) -> f b -> f a
contramap K1 r (Maybe b) () -> Maybe b
forall i c k (p :: k). K1 i c p -> c
unK1 (Insertor tbl db (Maybe b) -> Insertor tbl db (K1 r (Maybe b) ()))
-> (K1 r (Field tbl db 'Nullable a) ()
    -> Insertor tbl db (Maybe b))
-> K1 r (Field tbl db 'Nullable a) ()
-> Insertor tbl db (K1 r (Maybe b) ())
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Field tbl db 'Nullable a -> Insertor tbl db (Maybe b)
forall a (table :: Symbol) database fieldType.
ToSql a =>
Field table database 'Nullable fieldType
-> Insertor table database (Maybe a)
insertOneMaybe (Field tbl db 'Nullable a -> Insertor tbl db (Maybe b))
-> (K1 r (Field tbl db 'Nullable a) () -> Field tbl db 'Nullable a)
-> K1 r (Field tbl db 'Nullable a) ()
-> Insertor tbl db (Maybe b)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. K1 r (Field tbl db 'Nullable a) () -> Field tbl db 'Nullable 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)
-}

-- (a -> Expression) -> QueryInner (a -> QueryBuilder)
-- (a -> QueryInner QueryBuilder)
-- a -> queryState -> (queryState, result)
-- queryState -> a -> (query, result)
-- (a -> Expression) -> queryState -> a -> QueryBuilder
-- 

into :: (a -> Expression nullable b)
     -> Field table database nullable fieldType
     -> Insertor table database a
into :: (a -> Expression nullable b)
-> Field table database nullable fieldType
-> Insertor table database a
into a -> Expression nullable b
e Field table database nullable fieldType
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)
-> Insertor a -> Insertor table database a
forall a b. (a -> b) -> a -> b
$
  (a -> QueryBuilder) -> Text -> Insertor a
forall a. (a -> QueryBuilder) -> Text -> Insertor a
H.exprInto (\a
x -> QueryInner QueryBuilder -> ClauseState -> QueryBuilder
forall s a. State s a -> s -> a
evalState (Expression nullable b -> QueryInner QueryBuilder
forall (nullable :: Nullable) a.
Expression nullable a -> QueryInner QueryBuilder
runExpression (Expression nullable b -> QueryInner QueryBuilder)
-> Expression nullable b -> QueryInner QueryBuilder
forall a b. (a -> b) -> a -> b
$ a -> Expression nullable b
e a
x) ClauseState
emptyClauseState)
  (Field table database nullable fieldType -> Text
forall (table :: Symbol) database (nullable :: Nullable) a.
Field table database nullable a -> Text
fieldName Field table database nullable fieldType
f) 

lensInto :: H.ToSql b
         => H.Getter a b
         -> Field table database 'NotNull fieldType
         -> Insertor table database a
lensInto :: Getter a b
-> Field table database 'NotNull fieldType
-> Insertor table database a
lensInto Getter a b
lens Field table database 'NotNull 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 'NotNull fieldType -> Text
forall (table :: Symbol) database (nullable :: Nullable) a.
Field table database nullable a -> Text
fieldName Field table database 'NotNull fieldType
a

maybeLensInto :: H.ToSql b
              => H.Getter a (Maybe b)
              -> Field table database 'Nullable fieldType
              -> Insertor table database a
maybeLensInto :: Getter a (Maybe b)
-> Field table database 'Nullable fieldType
-> Insertor table database a
maybeLensInto Getter a (Maybe b)
lens Field table database 'Nullable 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 (Maybe b) -> Text -> Insertor a
forall b a. ToSql b => Getter a b -> Text -> Insertor a
H.lensInto Getter a (Maybe b)
lens (Text -> Insertor a) -> Text -> Insertor a
forall a b. (a -> b) -> a -> b
$ Field table database 'Nullable fieldType -> Text
forall (table :: Symbol) database (nullable :: Nullable) a.
Field table database nullable a -> Text
fieldName Field table database 'Nullable fieldType
a

opticInto :: (H.ToSql b , Is k A_Getter )
          => Optic' k is a b
          -> Field table database 'NotNull fieldType
          -> Insertor table database a
opticInto :: Optic' k is a b
-> Field table database 'NotNull fieldType
-> Insertor table database a
opticInto Optic' k is a b
getter Field table database 'NotNull fieldType
field = (b -> Expression 'NotNull b
forall a (nullable :: Nullable).
ToSql a =>
a -> Expression nullable a
arg (b -> Expression 'NotNull b)
-> (a -> b) -> a -> Expression 'NotNull b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Optic' k is a b -> a -> b
forall k (is :: IxList) s a.
Is k A_Getter =>
Optic' k is s a -> s -> a
view Optic' k is a b
getter) (a -> Expression 'NotNull b)
-> Field table database 'NotNull fieldType
-> Insertor table database a
forall a (nullable :: Nullable) b (table :: Symbol) database
       fieldType.
(a -> Expression nullable b)
-> Field table database nullable fieldType
-> Insertor table database a
`into` Field table database 'NotNull fieldType
field

maybeOpticInto :: (H.ToSql b , Is k A_Getter)
               => Optic' k is a (Maybe b)
               -> Field table database 'Nullable fieldType
               -> Insertor table database a
maybeOpticInto :: Optic' k is a (Maybe b)
-> Field table database 'Nullable fieldType
-> Insertor table database a
maybeOpticInto Optic' k is a (Maybe b)
getter Field table database 'Nullable fieldType
field = (Maybe b -> Expression 'Nullable b
forall a. ToSql a => Maybe a -> Expression 'Nullable a
argMaybe (Maybe b -> Expression 'Nullable b)
-> (a -> Maybe b) -> a -> Expression 'Nullable b
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Optic' k is a (Maybe b) -> a -> Maybe b
forall k (is :: IxList) s a.
Is k A_Getter =>
Optic' k is s a -> s -> a
view Optic' k is a (Maybe b)
getter) (a -> Expression 'Nullable b)
-> Field table database 'Nullable fieldType
-> Insertor table database a
forall a (nullable :: Nullable) b (table :: Symbol) database
       fieldType.
(a -> Expression nullable b)
-> Field table database nullable fieldType
-> Insertor table database a
`into` Field table database 'Nullable fieldType
field

tableSql :: Table table database -> H.QueryBuilder
tableSql :: Table table database -> QueryBuilder
tableSql (Table Maybe Text
mbSchema Text
tableName) =
  Text -> QueryBuilder
H.rawSql (Text -> QueryBuilder) -> Text -> QueryBuilder
forall a b. (a -> b) -> a -> b
$ (Text -> Text) -> Maybe Text -> Text
forall (t :: * -> *) m a.
(Foldable t, Monoid m) =>
(a -> m) -> t a -> m
foldMap (Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
".") Maybe Text
mbSchema Text -> Text -> Text
forall a. Semigroup a => a -> a -> a
<> Text
tableName

insertValues :: Table table database
             -> Insertor table database a
             -> [a]
             -> H.Command
insertValues :: Table table database -> Insertor table database a -> [a] -> Command
insertValues Table table database
table (Insertor Insertor a
i) =
  QueryBuilder -> Insertor a -> [a] -> Command
forall a. QueryBuilder -> Insertor a -> [a] -> Command
H.insertValues (Table table database -> QueryBuilder
forall (table :: Symbol) database.
Table table database -> QueryBuilder
tableSql Table table database
table) Insertor a
i

valuesAlias :: Alias table database leftJoined
valuesAlias :: Alias table database leftJoined
valuesAlias = (forall (fieldNull :: Nullable) a.
 Field table database fieldNull a
 -> Expression (JoinNullable leftJoined fieldNull) a)
-> Alias table database leftJoined
forall (table :: Symbol) database (joinType :: JoinType).
(forall (fieldNull :: Nullable) a.
 Field table database fieldNull a
 -> Expression (JoinNullable joinType fieldNull) a)
-> Alias table database joinType
Alias ((forall (fieldNull :: Nullable) a.
  Field table database fieldNull a
  -> Expression (JoinNullable leftJoined fieldNull) a)
 -> Alias table database leftJoined)
-> (forall (fieldNull :: Nullable) a.
    Field table database fieldNull a
    -> Expression (JoinNullable leftJoined fieldNull) a)
-> Alias table database leftJoined
forall a b. (a -> b) -> a -> b
$ \Field table database fieldNull a
field ->
  QueryInner QueryBuilder
-> Expression (JoinNullable leftJoined fieldNull) a
forall (nullable :: Nullable) a.
QueryInner QueryBuilder -> Expression nullable a
Expression (QueryInner QueryBuilder
 -> Expression (JoinNullable leftJoined fieldNull) a)
-> QueryInner QueryBuilder
-> Expression (JoinNullable leftJoined fieldNull) 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
$ QueryBuilder -> QueryBuilder
H.values (QueryBuilder -> QueryBuilder) -> QueryBuilder -> QueryBuilder
forall a b. (a -> b) -> a -> b
$ Text -> QueryBuilder
H.rawSql (Text -> QueryBuilder) -> Text -> QueryBuilder
forall a b. (a -> b) -> a -> b
$ Field table database fieldNull a -> Text
forall (table :: Symbol) database (nullable :: Nullable) a.
Field table database nullable a -> Text
fieldName Field table database fieldNull a
field

insertUpdateValues :: Table table database
                   -> Insertor table database a
                   -> (Alias table database 'InnerJoined ->
                       Alias table database 'InnerJoined ->
                       [Updator table database])
                   -> [a]
                   -> H.Command
insertUpdateValues :: Table table database
-> Insertor table database a
-> (Alias table database 'InnerJoined
    -> Alias table database 'InnerJoined -> [Updator table database])
-> [a]
-> Command
insertUpdateValues Table table database
table (Insertor Insertor a
i) Alias table database 'InnerJoined
-> Alias table database 'InnerJoined -> [Updator table database]
mkUpdators =
  QueryBuilder
-> Insertor a -> [(QueryBuilder, QueryBuilder)] -> [a] -> Command
forall a.
QueryBuilder
-> Insertor a -> [(QueryBuilder, QueryBuilder)] -> [a] -> Command
H.insertUpdateValues (Table table database -> QueryBuilder
forall (table :: Symbol) database.
Table table database -> QueryBuilder
tableSql Table table database
table) Insertor a
i [(QueryBuilder, QueryBuilder)]
updators
  where updators :: [(QueryBuilder, QueryBuilder)]
updators = (State ClauseState [(QueryBuilder, QueryBuilder)]
 -> ClauseState -> [(QueryBuilder, QueryBuilder)])
-> ClauseState
-> State ClauseState [(QueryBuilder, QueryBuilder)]
-> [(QueryBuilder, QueryBuilder)]
forall a b c. (a -> b -> c) -> b -> a -> c
flip State ClauseState [(QueryBuilder, QueryBuilder)]
-> ClauseState -> [(QueryBuilder, QueryBuilder)]
forall s a. State s a -> s -> a
evalState ClauseState
emptyClauseState (State ClauseState [(QueryBuilder, QueryBuilder)]
 -> [(QueryBuilder, QueryBuilder)])
-> State ClauseState [(QueryBuilder, QueryBuilder)]
-> [(QueryBuilder, QueryBuilder)]
forall a b. (a -> b) -> a -> b
$ 
                   (Updator table database
 -> StateT ClauseState Identity (QueryBuilder, QueryBuilder))
-> [Updator table database]
-> State ClauseState [(QueryBuilder, QueryBuilder)]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse Updator table database
-> StateT ClauseState Identity (QueryBuilder, QueryBuilder)
forall (table :: Symbol) database.
Updator table database
-> StateT ClauseState Identity (QueryBuilder, QueryBuilder)
runUpdator ([Updator table database]
 -> State ClauseState [(QueryBuilder, QueryBuilder)])
-> [Updator table database]
-> State ClauseState [(QueryBuilder, QueryBuilder)]
forall a b. (a -> b) -> a -> b
$ Alias table database 'InnerJoined
-> Alias table database 'InnerJoined -> [Updator table database]
mkUpdators Alias table database 'InnerJoined
forall (table :: Symbol) database (leftJoined :: JoinType).
Alias table database leftJoined
emptyAlias Alias table database 'InnerJoined
forall (table :: Symbol) database (leftJoined :: JoinType).
Alias table database leftJoined
valuesAlias
        runUpdator :: Updator table database
                   -> QueryInner (H.QueryBuilder, H.QueryBuilder)  
        runUpdator :: Updator table database
-> StateT ClauseState Identity (QueryBuilder, QueryBuilder)
runUpdator (Field table database nullable a
field := Expression QueryInner QueryBuilder
expr) = do
          (Text -> QueryBuilder
H.rawSql (Text -> QueryBuilder) -> Text -> QueryBuilder
forall a b. (a -> b) -> a -> b
$ Field table database nullable a -> Text
forall (table :: Symbol) database (nullable :: Nullable) a.
Field table database nullable a -> Text
fieldName Field table database nullable a
field, ) (QueryBuilder -> (QueryBuilder, QueryBuilder))
-> QueryInner QueryBuilder
-> StateT ClauseState Identity (QueryBuilder, QueryBuilder)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> QueryInner QueryBuilder
expr

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 (Alias table database 'InnerJoined)
from :: Table table database
-> Query database (Alias table database 'InnerJoined)
from table :: Table table database
table@(Table Maybe Text
_ Text
tableName) = QueryInner (Alias table database 'InnerJoined)
-> Query database (Alias table database 'InnerJoined)
forall database a. QueryInner a -> Query database a
Query (QueryInner (Alias table database 'InnerJoined)
 -> Query database (Alias table database 'InnerJoined))
-> QueryInner (Alias table database 'InnerJoined)
-> Query database (Alias 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
$ Table table database -> QueryBuilder
forall (table :: Symbol) database.
Table table database -> QueryBuilder
tableSql Table table database
table QueryBuilder -> QueryBuilder -> QueryBuilder
`H.as` Text -> QueryBuilder
H.rawSql Text
alias
     Alias table database 'InnerJoined
-> QueryInner (Alias table database 'InnerJoined)
forall (f :: * -> *) a. Applicative f => a -> f a
pure (Alias table database 'InnerJoined
 -> QueryInner (Alias table database 'InnerJoined))
-> Alias table database 'InnerJoined
-> QueryInner (Alias table database 'InnerJoined)
forall a b. (a -> b) -> a -> b
$ Text -> Alias table database 'InnerJoined
forall (table :: Symbol) database (leftJoined :: JoinType).
Text -> Alias table database leftJoined
mkTableAlias Text
alias

innerJoin :: Table table database
          -> (Alias table database 'InnerJoined ->
              Expression nullable Bool)
          -> Query database (Alias table database 'InnerJoined)
innerJoin :: Table table database
-> (Alias table database 'InnerJoined -> Expression nullable Bool)
-> Query database (Alias table database 'InnerJoined)
innerJoin table :: Table table database
table@(Table Maybe Text
_ Text
tableName) Alias table database 'InnerJoined -> Expression nullable Bool
joinCondition = QueryInner (Alias table database 'InnerJoined)
-> Query database (Alias table database 'InnerJoined)
forall database a. QueryInner a -> Query database a
Query (QueryInner (Alias table database 'InnerJoined)
 -> Query database (Alias table database 'InnerJoined))
-> QueryInner (Alias table database 'InnerJoined)
-> Query database (Alias table database 'InnerJoined)
forall a b. (a -> b) -> a -> b
$ do
  Text
alias <- Text -> QueryInner Text
newAlias (Text -> QueryInner Text) -> Text -> QueryInner Text
forall a b. (a -> b) -> a -> b
$ Int -> Text -> Text
Text.take Int
1 Text
tableName
  let tblAlias :: Alias table database 'InnerJoined
tblAlias = Text -> Alias table database 'InnerJoined
forall (table :: Symbol) database (leftJoined :: JoinType).
Text -> Alias 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
$ Alias table database 'InnerJoined -> Expression nullable Bool
joinCondition Alias 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 [Table table database -> QueryBuilder
forall (table :: Symbol) database.
Table table database -> QueryBuilder
tableSql Table table database
table QueryBuilder -> QueryBuilder -> QueryBuilder
`H.as` Text -> QueryBuilder
H.rawSql Text
alias]
    [QueryBuilder
exprBuilder]
  Alias table database 'InnerJoined
-> QueryInner (Alias table database 'InnerJoined)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Alias table database 'InnerJoined
tblAlias

leftJoin :: Table table database
         -> (Alias table database 'LeftJoined ->
             Expression nullable Bool)
         -> Query database (Alias table database 'LeftJoined)
leftJoin :: Table table database
-> (Alias table database 'LeftJoined -> Expression nullable Bool)
-> Query database (Alias table database 'LeftJoined)
leftJoin table :: Table table database
table@(Table Maybe Text
_ Text
tableName) Alias table database 'LeftJoined -> Expression nullable Bool
joinCondition = QueryInner (Alias table database 'LeftJoined)
-> Query database (Alias table database 'LeftJoined)
forall database a. QueryInner a -> Query database a
Query (QueryInner (Alias table database 'LeftJoined)
 -> Query database (Alias table database 'LeftJoined))
-> QueryInner (Alias table database 'LeftJoined)
-> Query database (Alias table database 'LeftJoined)
forall a b. (a -> b) -> a -> b
$ do
  Text
alias <- Text -> QueryInner Text
newAlias (Text -> QueryInner Text) -> Text -> QueryInner Text
forall a b. (a -> b) -> a -> b
$ Int -> Text -> Text
Text.take Int
1 Text
tableName
  let tblAlias :: Alias table database 'LeftJoined
tblAlias = Text -> Alias table database 'LeftJoined
forall (table :: Symbol) database (leftJoined :: JoinType).
Text -> Alias 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
$ Alias table database 'LeftJoined -> Expression nullable Bool
joinCondition Alias 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 [Table table database -> QueryBuilder
forall (table :: Symbol) database.
Table table database -> QueryBuilder
tableSql Table table database
table QueryBuilder -> QueryBuilder -> QueryBuilder
`H.as` Text -> QueryBuilder
H.rawSql Text
alias]
    [QueryBuilder
exprBuilder]
  Alias table database 'LeftJoined
-> QueryInner (Alias table database 'LeftJoined)
forall (f :: * -> *) a. Applicative f => a -> f a
pure Alias 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.rawValues_ [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.rawValues_ [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 'NotNull Bool -> Query database ()
where_ :: Expression 'NotNull Bool -> Query database ()
where_ Expression 'NotNull 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 'NotNull Bool -> QueryInner QueryBuilder
forall (nullable :: Nullable) a.
Expression nullable a -> QueryInner QueryBuilder
runExpression Expression 'NotNull 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 :: Expression nullable a ->
            Field table database nullable a ->
            Into database table
exprInto :: Expression nullable a
-> Field table database nullable a -> Into database table
exprInto Expression nullable a
expr Field table database nullable a
field =
  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
$ (Field table database nullable a -> Text
forall (table :: Symbol) database (nullable :: Nullable) a.
Field table database nullable a -> Text
fieldName Field table database nullable a
field,) (QueryBuilder -> (Text, QueryBuilder))
-> QueryInner QueryBuilder -> QueryInner (Text, QueryBuilder)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> Expression nullable a -> QueryInner QueryBuilder
forall (nullable :: Nullable) a.
Expression nullable a -> QueryInner QueryBuilder
runExpression Expression nullable 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 table database
table (Query QueryInner [Into database table]
query) =
  QueryBuilder
-> [QueryBuilder] -> [QueryBuilder] -> QueryClauses -> Command
H.insertSelect (Table table database -> QueryBuilder
forall (table :: Symbol) database.
Table table database -> QueryBuilder
tableSql Table table database
table)
  (((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

infix 0 :=

data Updator table database =
  forall nullable a.
  Field table database nullable a := Expression nullable a

update :: Table table database
       -> (Alias table database 'InnerJoined ->
           Query database [Updator table database])
       -> H.Command
update :: Table table database
-> (Alias table database 'InnerJoined
    -> Query database [Updator table database])
-> Command
update Table table database
table Alias table database 'InnerJoined
-> Query database [Updator table database]
query =
  [QueryBuilder]
-> [(QueryBuilder, QueryBuilder)] -> QueryClauses -> Command
H.update [Table table database -> QueryBuilder
forall (table :: Symbol) database.
Table table database -> QueryBuilder
tableSql Table table database
table]
  [(QueryBuilder, QueryBuilder)]
updators QueryClauses
clauses
  where Query QueryInner [Updator table database]
runQuery = Alias table database 'InnerJoined
-> Query database [Updator table database]
query Alias table database 'InnerJoined
forall (table :: Symbol) database (leftJoined :: JoinType).
Alias table database leftJoined
emptyAlias
        ([(QueryBuilder, QueryBuilder)]
updators, ClauseState QueryClauses
clauses Map Text Int
_) =
          State ClauseState [(QueryBuilder, QueryBuilder)]
-> ClauseState -> ([(QueryBuilder, QueryBuilder)], ClauseState)
forall s a. State s a -> s -> (a, s)
runState (QueryInner [Updator table database]
runQuery QueryInner [Updator table database]
-> ([Updator table database]
    -> State ClauseState [(QueryBuilder, QueryBuilder)])
-> State ClauseState [(QueryBuilder, QueryBuilder)]
forall (m :: * -> *) a b. Monad m => m a -> (a -> m b) -> m b
>>= (Updator table database
 -> StateT ClauseState Identity (QueryBuilder, QueryBuilder))
-> [Updator table database]
-> State ClauseState [(QueryBuilder, QueryBuilder)]
forall (t :: * -> *) (f :: * -> *) a b.
(Traversable t, Applicative f) =>
(a -> f b) -> t a -> f (t b)
traverse Updator table database
-> StateT ClauseState Identity (QueryBuilder, QueryBuilder)
forall (table :: Symbol) database.
Updator table database
-> StateT ClauseState Identity (QueryBuilder, QueryBuilder)
runUpdator) ClauseState
emptyClauseState
        runUpdator :: Updator table database
                   -> QueryInner (H.QueryBuilder, H.QueryBuilder)  
        runUpdator :: Updator table database
-> StateT ClauseState Identity (QueryBuilder, QueryBuilder)
runUpdator (Field table database nullable a
field := Expression QueryInner QueryBuilder
expr) = do
          (Text -> QueryBuilder
H.rawSql (Text -> QueryBuilder) -> Text -> QueryBuilder
forall a b. (a -> b) -> a -> b
$ Field table database nullable a -> Text
forall (table :: Symbol) database (nullable :: Nullable) a.
Field table database nullable a -> Text
fieldName Field table database nullable a
field, ) (QueryBuilder -> (QueryBuilder, QueryBuilder))
-> QueryInner QueryBuilder
-> StateT ClauseState Identity (QueryBuilder, QueryBuilder)
forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
<$> QueryInner QueryBuilder
expr
          
          
        
          

{- 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)

-}