module Database.PostgreSQL.Query.Entity.Functions
(
pgInsertEntity
, pgInsertManyEntities
, pgInsertManyEntitiesId
, pgSelectEntities
, pgSelectJustEntities
, pgSelectEntitiesBy
, pgGetEntity
, pgGetEntityBy
, pgQueryEntities
, pgDeleteEntity
, pgUpdateEntity
, pgSelectCount
) where
import Control.Monad.Logger
import Data.Int ( Int64 )
import Data.Maybe ( listToMaybe )
import Data.Proxy ( Proxy(..) )
import Data.Typeable ( Typeable )
import Database.PostgreSQL.Query.Entity.Class
import Database.PostgreSQL.Query.Entity.Internal
import Database.PostgreSQL.Query.Functions
import Database.PostgreSQL.Query.SqlBuilder
import Database.PostgreSQL.Query.TH
( sqlExp )
import Database.PostgreSQL.Query.Types
import Database.PostgreSQL.Simple
import Database.PostgreSQL.Simple.FromField
import Database.PostgreSQL.Simple.ToField
#if !MIN_VERSION_base(4,8,0)
import Control.Applicative
#endif
import qualified Data.List as L
import qualified Data.List.NonEmpty as NL
pgInsertEntity
:: forall a m
. ( MonadPostgres m, MonadLogger m, Entity a
, ToRow a, FromField (EntityId a) )
=> a
-> m (EntityId a)
pgInsertEntity a = do
pgQuery [sqlExp|^{insertEntity a} RETURNING id|] >>= \case
((Only ret):_) -> return ret
_ -> fail "Query did not return any response"
pgSelectEntities
:: forall m a q
. ( Functor m, MonadPostgres m, MonadLogger m, Entity a
, FromRow a, ToSqlBuilder q, FromField (EntityId a) )
=> (FN -> FN)
-> q
-> m [Ent a]
pgSelectEntities fpref q = do
let p = Proxy :: Proxy a
pgQueryEntities [sqlExp|^{selectEntity (entityFieldsId fpref) p} ^{q}|]
pgSelectJustEntities
:: forall m a q
. ( Functor m, MonadPostgres m, MonadLogger m, Entity a
, FromRow a, ToSqlBuilder q )
=> (FN -> FN)
-> q
-> m [a]
pgSelectJustEntities fpref q = do
let p = Proxy :: Proxy a
pgQuery [sqlExp|^{selectEntity (entityFields id fpref) p} ^{q}|]
pgSelectEntitiesBy
:: forall a m b
. ( Functor m, MonadPostgres m, MonadLogger m, Entity a, ToMarkedRow b
, FromRow a, FromField (EntityId a) )
=> b
-> m [Ent a]
pgSelectEntitiesBy b =
let p = Proxy :: Proxy a
in pgQueryEntities $ selectEntitiesBy ("id":) p b
pgGetEntity
:: forall m a
. ( ToField (EntityId a), Entity a, FromRow a
, MonadPostgres m, MonadLogger m, Functor m)
=> EntityId a
-> m (Maybe a)
pgGetEntity eid = do
listToMaybe <$> pgSelectJustEntities id [sqlExp|WHERE id = #{eid} LIMIT 1|]
pgGetEntityBy
:: forall m a b
. ( Entity a, MonadPostgres m, MonadLogger m, ToMarkedRow b
, FromField (EntityId a), FromRow a, Functor m )
=> b
-> m (Maybe (Ent a))
pgGetEntityBy b =
let p = Proxy :: Proxy a
in fmap listToMaybe
$ pgQueryEntities
[sqlExp|^{selectEntitiesBy ("id":) p b} LIMIT 1|]
pgInsertManyEntitiesId
:: forall a m
. ( Entity a, MonadPostgres m, MonadLogger m
, ToRow a, FromField (EntityId a))
=> [a]
-> m [EntityId a]
pgInsertManyEntitiesId [] = return []
pgInsertManyEntitiesId ents' =
let ents = NL.fromList ents'
q = [sqlExp|^{insertManyEntities ents} RETURNING id|]
in map fromOnly <$> pgQuery q
pgInsertManyEntities
:: forall a m
. (Entity a, MonadPostgres m, MonadLogger m, ToRow a)
=> [a]
-> m Int64
pgInsertManyEntities [] = return 0
pgInsertManyEntities ents' =
let ents = NL.fromList ents'
in pgExecute $ insertManyEntities ents
pgDeleteEntity
:: forall a m
. (Entity a, MonadPostgres m, MonadLogger m, ToField (EntityId a), Functor m)
=> EntityId a
-> m Bool
pgDeleteEntity eid =
let p = Proxy :: Proxy a
in fmap (1 ==)
$ pgExecute [sqlExp|DELETE FROM ^{tableName p}
WHERE id = #{eid}|]
pgUpdateEntity
:: forall a b m
. ( ToMarkedRow b, Entity a, MonadPostgres m, MonadLogger m
, ToField (EntityId a), Functor m, Typeable a, Typeable b)
=> EntityId a
-> b
-> m Bool
pgUpdateEntity eid b =
let p = Proxy :: Proxy a
mr = toMarkedRow b
in if L.null $ unMR mr
then return False
else fmap (1 ==)
$ pgExecute [sqlExp|UPDATE ^{tableName p}
SET ^{mrToBuilder ", " mr}
WHERE id = #{eid}|]
pgQueryEntities
:: ( ToSqlBuilder q, MonadPostgres m, MonadLogger m, Entity a
, FromRow a, FromField (EntityId a))
=> q
-> m [Ent a]
pgQueryEntities q =
map toTuples <$> pgQuery q
where
toTuples ((Only eid) :. entity) = (eid, entity)
pgSelectCount
:: forall m a q
. ( Entity a, MonadPostgres m, MonadLogger m, ToSqlBuilder q )
=> Proxy a
-> q
-> m Integer
pgSelectCount p q = do
[[c]] <- pgQuery [sqlExp|SELECT count(id) FROM ^{tableName p} ^{q}|]
return c