module Polysemy.Hasql.Interpreter.Store where

import Hasql.Connection (Connection)
import Hasql.Statement (Statement)
import qualified Polysemy.Db.Effect.Store as Store
import Polysemy.Db.Effect.Store (QStore, Store)
import Sqel.Data.QuerySchema (QuerySchema, emptyQuerySchema)
import Sqel.Data.TableSchema (TableSchema)
import Sqel.Data.Uid (Uid)
import Sqel.PgType (toFullProjection)
import Sqel.ResultShape (ResultShape)
import Sqel.Statement (delete, insert, selectWhere, upsert)

import Polysemy.Hasql.Effect.Database (ConnectionSource)
import qualified Polysemy.Hasql.Effect.DbTable as DbTable
import Polysemy.Hasql.Effect.DbTable (DbTable, StoreTable)
import Polysemy.Hasql.Transaction (interpretForXa)

handleQStoreDb ::
   f q d e r m a .
  ResultShape d (f d) =>
  Members [DbTable d !! e, Stop e] r =>
  TableSchema d ->
  QuerySchema q d ->
  QStore f q d m a ->
  Sem r a
handleQStoreDb :: forall (f :: * -> *) q d e (r :: EffectRow) (m :: * -> *) a.
(ResultShape d (f d), Members '[DbTable d !! e, Stop e] r) =>
TableSchema d -> QuerySchema q d -> QStore f q d m a -> Sem r a
handleQStoreDb TableSchema d
table QuerySchema q d
query = \case
  Store.Insert d
d ->
    forall err (eff :: (* -> *) -> * -> *) (r :: EffectRow).
Members '[Resumable err eff, Stop err] r =>
InterpreterFor eff r
restop (forall a (r :: EffectRow) p o.
Member (DbTable a) r =>
p -> Statement p o -> Sem r o
DbTable.statement d
d Statement d ()
is)
  Store.Upsert d
d ->
    forall err (eff :: (* -> *) -> * -> *) (r :: EffectRow).
Members '[Resumable err eff, Stop err] r =>
InterpreterFor eff r
restop (forall a (r :: EffectRow) p o.
Member (DbTable a) r =>
p -> Statement p o -> Sem r o
DbTable.statement d
d Statement d ()
us)
  Store.Delete q
i ->
    forall err (eff :: (* -> *) -> * -> *) (r :: EffectRow).
Members '[Resumable err eff, Stop err] r =>
InterpreterFor eff r
restop (forall a (r :: EffectRow) p o.
Member (DbTable a) r =>
p -> Statement p o -> Sem r o
DbTable.statement q
i Statement q (f d)
ds)
  QStore f q d m a
Store.DeleteAll ->
    forall err (eff :: (* -> *) -> * -> *) (r :: EffectRow).
Members '[Resumable err eff, Stop err] r =>
InterpreterFor eff r
restop (forall a (r :: EffectRow) p o.
Member (DbTable a) r =>
p -> Statement p o -> Sem r o
DbTable.statement () Statement () [d]
das)
  Store.Fetch q
i ->
    forall err (eff :: (* -> *) -> * -> *) (r :: EffectRow).
Members '[Resumable err eff, Stop err] r =>
InterpreterFor eff r
restop (forall a (r :: EffectRow) p o.
Member (DbTable a) r =>
p -> Statement p o -> Sem r o
DbTable.statement q
i Statement q (f d)
qs)
  QStore f q d m a
Store.FetchAll ->
    forall err (eff :: (* -> *) -> * -> *) (r :: EffectRow).
Members '[Resumable err eff, Stop err] r =>
InterpreterFor eff r
restop (forall a (r :: EffectRow) p o.
Member (DbTable a) r =>
p -> Statement p o -> Sem r o
DbTable.statement () Statement () [d]
qas)
  where
    is :: Statement d ()
is = forall a. TableSchema a -> Statement a ()
insert TableSchema d
table
    us :: Statement d ()
us = forall a. TableSchema a -> Statement a ()
upsert TableSchema d
table
    ds :: Statement q (f d)
    ds :: Statement q (f d)
ds = forall a result q.
ResultShape a result =>
QuerySchema q a -> TableSchema a -> Statement q result
delete QuerySchema q d
query TableSchema d
table
    qs :: Statement q (f d)
    qs :: Statement q (f d)
qs = forall result proj q table.
ResultShape proj result =>
QuerySchema q table -> Projection proj table -> Statement q result
selectWhere QuerySchema q d
query Projection d d
full
    qas :: Statement () [d]
    qas :: Statement () [d]
qas = forall result proj q table.
ResultShape proj result =>
QuerySchema q table -> Projection proj table -> Statement q result
selectWhere forall {k} (a :: k). QuerySchema () a
emptyQuerySchema Projection d d
full
    das :: Statement () [d]
    das :: Statement () [d]
das = forall a result q.
ResultShape a result =>
QuerySchema q a -> TableSchema a -> Statement q result
delete forall {k} (a :: k). QuerySchema () a
emptyQuerySchema TableSchema d
table
    full :: Projection d d
full = forall table. TableSchema table -> Projection table table
toFullProjection TableSchema d
table

interpretQStoreDb ::
   f q d e r .
  ResultShape d (f d) =>
  Member (DbTable d !! e) r =>
  TableSchema d ->
  QuerySchema q d ->
  InterpreterFor (QStore f q d !! e) r
interpretQStoreDb :: forall (f :: * -> *) q d e (r :: EffectRow).
(ResultShape d (f d), Member (DbTable d !! e) r) =>
TableSchema d
-> QuerySchema q d -> InterpreterFor (QStore f q d !! e) r
interpretQStoreDb TableSchema d
table QuerySchema q d
query =
  forall err (eff :: (* -> *) -> * -> *) (r :: EffectRow).
FirstOrder eff "interpretResumable" =>
(forall x (r0 :: EffectRow).
 eff (Sem r0) x -> Sem (Stop err : r) x)
-> InterpreterFor (Resumable err eff) r
interpretResumable (forall (f :: * -> *) q d e (r :: EffectRow) (m :: * -> *) a.
(ResultShape d (f d), Members '[DbTable d !! e, Stop e] r) =>
TableSchema d -> QuerySchema q d -> QStore f q d m a -> Sem r a
handleQStoreDb TableSchema d
table QuerySchema q d
query)

interpretStoreDb ::
   i d e r .
  Member (StoreTable i d !! e) r =>
  TableSchema (Uid i d) ->
  QuerySchema i (Uid i d) ->
  InterpreterFor (Store i d !! e) r
interpretStoreDb :: forall i d e (r :: EffectRow).
Member (StoreTable i d !! e) r =>
TableSchema (Uid i d)
-> QuerySchema i (Uid i d) -> InterpreterFor (Store i d !! e) r
interpretStoreDb TableSchema (Uid i d)
table QuerySchema i (Uid i d)
query =
  forall (f :: * -> *) q d e (r :: EffectRow).
(ResultShape d (f d), Member (DbTable d !! e) r) =>
TableSchema d
-> QuerySchema q d -> InterpreterFor (QStore f q d !! e) r
interpretQStoreDb TableSchema (Uid i d)
table QuerySchema i (Uid i d)
query

interpretQStoreXa ::
   f err i d r .
  ResultShape d (f d) =>
  Members [Scoped ConnectionSource (DbTable d !! err), Log, Embed IO] r =>
  TableSchema d ->
  QuerySchema i d ->
  InterpreterFor (Scoped Connection (QStore f i d !! err) !! err) r
interpretQStoreXa :: forall (f :: * -> *) err i d (r :: EffectRow).
(ResultShape d (f d),
 Members
   '[Scoped ConnectionSource (DbTable d !! err), Log, Embed IO] r) =>
TableSchema d
-> QuerySchema i d
-> InterpreterFor
     (Scoped Connection (QStore f i d !! err) !! err) r
interpretQStoreXa TableSchema d
table QuerySchema i d
query =
  forall (dep :: (* -> *) -> * -> *) (eff :: (* -> *) -> * -> *) err
       (r :: EffectRow).
Member (Scoped ConnectionSource (dep !! err)) r =>
(forall x (r0 :: EffectRow).
 eff (Sem r0) x -> Sem (Stop err : (dep !! err) : r) x)
-> InterpreterFor (Scoped Connection (eff !! err) !! err) r
interpretForXa (forall (f :: * -> *) q d e (r :: EffectRow) (m :: * -> *) a.
(ResultShape d (f d), Members '[DbTable d !! e, Stop e] r) =>
TableSchema d -> QuerySchema q d -> QStore f q d m a -> Sem r a
handleQStoreDb TableSchema d
table QuerySchema i d
query)

interpretStoreXa ::
   err i d r .
  Members [Scoped ConnectionSource (DbTable (Uid i d) !! err), Log, Embed IO] r =>
  TableSchema (Uid i d) ->
  QuerySchema i (Uid i d) ->
  InterpreterFor (Scoped Connection (Store i d !! err) !! err) r
interpretStoreXa :: forall err i d (r :: EffectRow).
Members
  '[Scoped ConnectionSource (DbTable (Uid i d) !! err), Log,
    Embed IO]
  r =>
TableSchema (Uid i d)
-> QuerySchema i (Uid i d)
-> InterpreterFor (Scoped Connection (Store i d !! err) !! err) r
interpretStoreXa =
  forall (f :: * -> *) err i d (r :: EffectRow).
(ResultShape d (f d),
 Members
   '[Scoped ConnectionSource (DbTable d !! err), Log, Embed IO] r) =>
TableSchema d
-> QuerySchema i d
-> InterpreterFor
     (Scoped Connection (QStore f i d !! err) !! err) r
interpretQStoreXa @Maybe

interpretQStores ::
   f err q d r .
  ResultShape d (f d) =>
  Members [Scoped ConnectionSource (DbTable d !! err), DbTable d !! err, Log, Embed IO] r =>
  TableSchema d ->
  QuerySchema q d ->
  InterpretersFor [QStore f q d !! err, Scoped Connection (QStore f q d !! err) !! err] r
interpretQStores :: forall (f :: * -> *) err q d (r :: EffectRow).
(ResultShape d (f d),
 Members
   '[Scoped ConnectionSource (DbTable d !! err), DbTable d !! err,
     Log, Embed IO]
   r) =>
TableSchema d
-> QuerySchema q d
-> InterpretersFor
     '[QStore f q d !! err,
       Scoped Connection (QStore f q d !! err) !! err]
     r
interpretQStores TableSchema d
table QuerySchema q d
query =
  forall (f :: * -> *) err i d (r :: EffectRow).
(ResultShape d (f d),
 Members
   '[Scoped ConnectionSource (DbTable d !! err), Log, Embed IO] r) =>
TableSchema d
-> QuerySchema i d
-> InterpreterFor
     (Scoped Connection (QStore f i d !! err) !! err) r
interpretQStoreXa TableSchema d
table QuerySchema q d
query forall b c a. (b -> c) -> (a -> b) -> a -> c
.
  forall (f :: * -> *) q d e (r :: EffectRow).
(ResultShape d (f d), Member (DbTable d !! e) r) =>
TableSchema d
-> QuerySchema q d -> InterpreterFor (QStore f q d !! e) r
interpretQStoreDb TableSchema d
table QuerySchema q d
query

interpretStores ::
   err i d r .
  Members [Scoped ConnectionSource (DbTable (Uid i d) !! err), StoreTable i d !! err, Log, Embed IO] r =>
  TableSchema (Uid i d) ->
  QuerySchema i (Uid i d) ->
  InterpretersFor [Store i d !! err, Scoped Connection (Store i d !! err) !! err] r
interpretStores :: forall err i d (r :: EffectRow).
Members
  '[Scoped ConnectionSource (DbTable (Uid i d) !! err),
    DbTable (Uid i d) !! err, Log, Embed IO]
  r =>
TableSchema (Uid i d)
-> QuerySchema i (Uid i d)
-> InterpretersFor
     '[Store i d !! err, Scoped Connection (Store i d !! err) !! err] r
interpretStores =
  forall (f :: * -> *) err q d (r :: EffectRow).
(ResultShape d (f d),
 Members
   '[Scoped ConnectionSource (DbTable d !! err), DbTable d !! err,
     Log, Embed IO]
   r) =>
TableSchema d
-> QuerySchema q d
-> InterpretersFor
     '[QStore f q d !! err,
       Scoped Connection (QStore f q d !! err) !! err]
     r
interpretQStores @Maybe