module Database.PostgreSQL.Query.Entity.Internal
(
entityFields
, entityFieldsId
, selectEntity
, selectEntitiesBy
, insertEntity
, insertManyEntities
, entityToMR
) where
import Database.PostgreSQL.Query.Entity.Class
import Database.PostgreSQL.Query.Import
import Database.PostgreSQL.Query.Internal
import Database.PostgreSQL.Query.SqlBuilder
( SqlBuilder, ToSqlBuilder(..), mkValue )
import Database.PostgreSQL.Query.TH
( sqlExp )
import Database.PostgreSQL.Query.Types
( FN(..), MarkedRow(..),
ToMarkedRow(..), mrToBuilder )
import Database.PostgreSQL.Simple.ToRow
( ToRow(..) )
import qualified Data.List.NonEmpty as NL
import qualified Data.List as L
entityFields :: (Entity a)
=> ([FN] -> [FN])
-> (FN -> FN)
-> Proxy a
-> SqlBuilder
entityFields :: ([FN] -> [FN]) -> (FN -> FN) -> Proxy a -> SqlBuilder
entityFields [FN] -> [FN]
xpref FN -> FN
fpref Proxy a
p =
[FN] -> SqlBuilder
buildFields
([FN] -> SqlBuilder) -> [FN] -> SqlBuilder
forall a b. (a -> b) -> a -> b
$ [FN] -> [FN]
xpref
([FN] -> [FN]) -> [FN] -> [FN]
forall a b. (a -> b) -> a -> b
$ (FN -> FN) -> [FN] -> [FN]
forall a b. (a -> b) -> [a] -> [b]
map FN -> FN
fpref
([FN] -> [FN]) -> [FN] -> [FN]
forall a b. (a -> b) -> a -> b
$ Proxy a -> [FN]
forall a. Entity a => Proxy a -> [FN]
fieldNames Proxy a
p
entityFieldsId :: (Entity a)
=> (FN -> FN)
-> Proxy a
-> SqlBuilder
entityFieldsId :: (FN -> FN) -> Proxy a -> SqlBuilder
entityFieldsId FN -> FN
fpref Proxy a
p =
let xpref :: [FN] -> [FN]
xpref = ((FN -> FN
fpref FN
"id")FN -> [FN] -> [FN]
forall a. a -> [a] -> [a]
:)
in ([FN] -> [FN]) -> (FN -> FN) -> Proxy a -> SqlBuilder
forall a.
Entity a =>
([FN] -> [FN]) -> (FN -> FN) -> Proxy a -> SqlBuilder
entityFields [FN] -> [FN]
xpref FN -> FN
fpref Proxy a
p
selectEntity :: (Entity a)
=> (Proxy a -> SqlBuilder)
-> Proxy a
-> SqlBuilder
selectEntity :: (Proxy a -> SqlBuilder) -> Proxy a -> SqlBuilder
selectEntity Proxy a -> SqlBuilder
bld Proxy a
p =
[sqlExp|SELECT ^{bld p} FROM ^{tableName p}|]
selectEntitiesBy :: (Entity a, ToMarkedRow b)
=> ([FN] -> [FN])
-> Proxy a
-> b
-> SqlBuilder
selectEntitiesBy :: ([FN] -> [FN]) -> Proxy a -> b -> SqlBuilder
selectEntitiesBy [FN] -> [FN]
xpref Proxy a
p b
b =
let mr :: MarkedRow
mr = b -> MarkedRow
forall a. ToMarkedRow a => a -> MarkedRow
toMarkedRow b
b
cond :: SqlBuilder
cond = if [(FN, SqlBuilder)] -> Bool
forall (t :: * -> *) a. Foldable t => t a -> Bool
L.null ([(FN, SqlBuilder)] -> Bool) -> [(FN, SqlBuilder)] -> Bool
forall a b. (a -> b) -> a -> b
$ MarkedRow -> [(FN, SqlBuilder)]
unMR MarkedRow
mr
then SqlBuilder
forall a. Monoid a => a
mempty
else [sqlExp| WHERE ^{mrToBuilder "AND" mr}|]
q :: SqlBuilder
q = (Proxy a -> SqlBuilder) -> Proxy a -> SqlBuilder
forall a.
Entity a =>
(Proxy a -> SqlBuilder) -> Proxy a -> SqlBuilder
selectEntity (([FN] -> [FN]) -> (FN -> FN) -> Proxy a -> SqlBuilder
forall a.
Entity a =>
([FN] -> [FN]) -> (FN -> FN) -> Proxy a -> SqlBuilder
entityFields [FN] -> [FN]
xpref FN -> FN
forall a. a -> a
id) Proxy a
p
in SqlBuilder
q SqlBuilder -> SqlBuilder -> SqlBuilder
forall a. Semigroup a => a -> a -> a
<> SqlBuilder
cond
entityToMR :: forall a. (Entity a, ToRow a) => a -> MarkedRow
entityToMR :: a -> MarkedRow
entityToMR a
a =
let p :: Proxy a
p = Proxy a
forall k (t :: k). Proxy t
Proxy :: Proxy a
names :: [FN]
names = Proxy a -> [FN]
forall a. Entity a => Proxy a -> [FN]
fieldNames Proxy a
p
values :: [SqlBuilder]
values = (Action -> SqlBuilder) -> [Action] -> [SqlBuilder]
forall a b. (a -> b) -> [a] -> [b]
map Action -> SqlBuilder
forall a. ToField a => a -> SqlBuilder
mkValue ([Action] -> [SqlBuilder]) -> [Action] -> [SqlBuilder]
forall a b. (a -> b) -> a -> b
$ a -> [Action]
forall a. ToRow a => a -> [Action]
toRow a
a
in [(FN, SqlBuilder)] -> MarkedRow
MR ([(FN, SqlBuilder)] -> MarkedRow)
-> [(FN, SqlBuilder)] -> MarkedRow
forall a b. (a -> b) -> a -> b
$ [FN] -> [SqlBuilder] -> [(FN, SqlBuilder)]
forall a b. [a] -> [b] -> [(a, b)]
zip [FN]
names [SqlBuilder]
values
insertEntity :: forall a. (Entity a, ToRow a) => a -> SqlBuilder
insertEntity :: a -> SqlBuilder
insertEntity a
a =
let p :: Proxy a
p = Proxy a
forall k (t :: k). Proxy t
Proxy :: Proxy a
mr :: MarkedRow
mr = a -> MarkedRow
forall a. (Entity a, ToRow a) => a -> MarkedRow
entityToMR a
a
in FN -> MarkedRow -> SqlBuilder
forall b. ToMarkedRow b => FN -> b -> SqlBuilder
insertInto (Proxy a -> FN
forall a. Entity a => Proxy a -> FN
tableName Proxy a
p) MarkedRow
mr
insertManyEntities :: forall a. (Entity a, ToRow a)
=> NonEmpty a
-> SqlBuilder
insertManyEntities :: NonEmpty a -> SqlBuilder
insertManyEntities NonEmpty a
rows =
let p :: Proxy a
p = Proxy a
forall k (t :: k). Proxy t
Proxy :: Proxy a
names :: SqlBuilder
names = [SqlBuilder] -> SqlBuilder
forall a. Monoid a => [a] -> a
mconcat
([SqlBuilder] -> SqlBuilder) -> [SqlBuilder] -> SqlBuilder
forall a b. (a -> b) -> a -> b
$ SqlBuilder -> [SqlBuilder] -> [SqlBuilder]
forall a. a -> [a] -> [a]
L.intersperse SqlBuilder
","
([SqlBuilder] -> [SqlBuilder]) -> [SqlBuilder] -> [SqlBuilder]
forall a b. (a -> b) -> a -> b
$ (FN -> SqlBuilder) -> [FN] -> [SqlBuilder]
forall a b. (a -> b) -> [a] -> [b]
map FN -> SqlBuilder
forall a. ToSqlBuilder a => a -> SqlBuilder
toSqlBuilder
([FN] -> [SqlBuilder]) -> [FN] -> [SqlBuilder]
forall a b. (a -> b) -> a -> b
$ Proxy a -> [FN]
forall a. Entity a => Proxy a -> [FN]
fieldNames Proxy a
p
values :: SqlBuilder
values = [SqlBuilder] -> SqlBuilder
forall a. Monoid a => [a] -> a
mconcat
([SqlBuilder] -> SqlBuilder) -> [SqlBuilder] -> SqlBuilder
forall a b. (a -> b) -> a -> b
$ SqlBuilder -> [SqlBuilder] -> [SqlBuilder]
forall a. a -> [a] -> [a]
L.intersperse SqlBuilder
","
([SqlBuilder] -> [SqlBuilder]) -> [SqlBuilder] -> [SqlBuilder]
forall a b. (a -> b) -> a -> b
$ (a -> SqlBuilder) -> [a] -> [SqlBuilder]
forall a b. (a -> b) -> [a] -> [b]
map a -> SqlBuilder
rValue
([a] -> [SqlBuilder]) -> [a] -> [SqlBuilder]
forall a b. (a -> b) -> a -> b
$ NonEmpty a -> [a]
forall a. NonEmpty a -> [a]
NL.toList NonEmpty a
rows
in [sqlExp|INSERT INTO ^{tableName p}
(^{names}) VALUES ^{values}|]
where
rValue :: a -> SqlBuilder
rValue :: a -> SqlBuilder
rValue a
row =
let values :: SqlBuilder
values = [SqlBuilder] -> SqlBuilder
forall a. Monoid a => [a] -> a
mconcat
([SqlBuilder] -> SqlBuilder) -> [SqlBuilder] -> SqlBuilder
forall a b. (a -> b) -> a -> b
$ SqlBuilder -> [SqlBuilder] -> [SqlBuilder]
forall a. a -> [a] -> [a]
L.intersperse SqlBuilder
","
([SqlBuilder] -> [SqlBuilder]) -> [SqlBuilder] -> [SqlBuilder]
forall a b. (a -> b) -> a -> b
$ (Action -> SqlBuilder) -> [Action] -> [SqlBuilder]
forall a b. (a -> b) -> [a] -> [b]
map Action -> SqlBuilder
forall a. ToField a => a -> SqlBuilder
mkValue
([Action] -> [SqlBuilder]) -> [Action] -> [SqlBuilder]
forall a b. (a -> b) -> a -> b
$ a -> [Action]
forall a. ToRow a => a -> [Action]
toRow a
row
in [sqlExp|(^{values})|]