module Polysemy.Hasql.Database where

import Hasql.Decoders (Row)
import Hasql.Encoders (Params)
import Time (Seconds (Seconds))
import Sqel.Data.Codec (Encoder, FullCodec)
import Sqel.Data.Dd (Dd, DdType)
import Sqel.Data.QuerySchema (QuerySchema (QuerySchema))
import Sqel.Data.Sql (Sql)
import Sqel.Data.TableSchema (TableSchema (TableSchema))
import Sqel.PgType (tableSchema)
import Sqel.Query (CheckedQuery, checkQuery)
import Sqel.ReifyCodec (ReifyCodec)
import Sqel.ReifyDd (ReifyDd)
import Sqel.ResultShape (ResultShape)
import Sqel.Statement (plain, prepared, unprepared)

import qualified Polysemy.Hasql.Effect.Database as Database
import Polysemy.Hasql.Effect.Database (Database (..))

retryingSql ::
  TimeUnit t =>
  Member Database r =>
  t ->
  Sql ->
  Sem r ()
retryingSql :: forall t (r :: EffectRow).
(TimeUnit t, Member Database r) =>
t -> Sql -> Sem r ()
retryingSql t
interval =
  forall (r :: EffectRow) t a.
(Member Database r, TimeUnit t) =>
t -> Maybe Int -> Sem r a -> Sem r a
Database.retry t
interval forall a. Maybe a
Nothing forall b c a. (b -> c) -> (a -> b) -> a -> c
. forall (r :: EffectRow) p o.
Member Database r =>
p -> Statement p o -> Sem r o
Database.statement () forall b c a. (b -> c) -> (a -> b) -> a -> c
. Sql -> Statement () ()
plain

retryingSqlDef ::
  Member Database r =>
  Sql ->
  Sem r ()
retryingSqlDef :: forall (r :: EffectRow). Member Database r => Sql -> Sem r ()
retryingSqlDef =
  forall t (r :: EffectRow).
(TimeUnit t, Member Database r) =>
t -> Sql -> Sem r ()
retryingSql (Int64 -> Seconds
Seconds Int64
3)

retryingQuerySql ::
  TimeUnit t =>
  ResultShape d result =>
  Members [Database !! e, Stop e] r =>
  t ->
  Sql ->
  Row d ->
  Params param ->
  param ->
  Sem r result
retryingQuerySql :: forall t d result e (r :: EffectRow) param.
(TimeUnit t, ResultShape d result,
 Members '[Database !! e, Stop e] r) =>
t -> Sql -> Row d -> Params param -> param -> Sem r result
retryingQuerySql t
interval Sql
s Row d
row Params param
params param
q =
  forall err (eff :: (* -> *) -> * -> *) (r :: EffectRow).
Members '[Resumable err eff, Stop err] r =>
InterpreterFor eff r
restop (forall (r :: EffectRow) t a.
(Member Database r, TimeUnit t) =>
t -> Maybe Int -> Sem r a -> Sem r a
Database.retry t
interval forall a. Maybe a
Nothing (forall (r :: EffectRow) p o.
Member Database r =>
p -> Statement p o -> Sem r o
Database.statement param
q (forall d result p.
ResultShape d result =>
Sql -> Row d -> Params p -> Statement p result
prepared Sql
s Row d
row Params param
params)))

retryingQuerySqlDef ::
   e d param result r .
  ResultShape d result =>
  Members [Database !! e, Stop e] r =>
  Sql ->
  Row d ->
  Params param ->
  param ->
  Sem r result
retryingQuerySqlDef :: forall e d param result (r :: EffectRow).
(ResultShape d result, Members '[Database !! e, Stop e] r) =>
Sql -> Row d -> Params param -> param -> Sem r result
retryingQuerySqlDef =
  forall t d result e (r :: EffectRow) param.
(TimeUnit t, ResultShape d result,
 Members '[Database !! e, Stop e] r) =>
t -> Sql -> Row d -> Params param -> param -> Sem r result
retryingQuerySql (Int64 -> Seconds
Seconds Int64
3)

-- TODO check projection
query ::
   res query proj table r .
  Member Database r =>
  CheckedQuery query table =>
  ReifyCodec Encoder query (DdType query) =>
  ReifyDd proj =>
  ReifyCodec FullCodec proj (DdType proj) =>
  ResultShape (DdType proj) res =>
  Dd query ->
  Dd proj ->
  Dd table ->
  DdType query ->
  Sql ->
  Sem r res
query :: forall res (query :: DdK) (proj :: DdK) (table :: DdK)
       (r :: EffectRow).
(Member Database r, CheckedQuery query table,
 ReifyCodec Encoder query (DdType query), ReifyDd proj,
 ReifyCodec FullCodec proj (DdType proj),
 ResultShape (DdType proj) res) =>
Dd query -> Dd proj -> Dd table -> DdType query -> Sql -> Sem r res
query Dd query
queryDd Dd proj
projDd Dd table
tableDd DdType query
q Sql
s =
  forall (r :: EffectRow) p o.
Member Database r =>
p -> Statement p o -> Sem r o
Database.statement DdType query
q (forall result d p.
ResultShape d result =>
Sql -> Row d -> Params p -> Statement p result
unprepared Sql
s Row (DdType proj)
decoder (Encoder (DdType query)
encoder forall s a. s -> Getting a s a -> a
^. forall a. IsLabel "encodeValue" a => a
#encodeValue))
  where
    QuerySchema [SelectFragment]
_ Encoder (DdType query)
encoder =
      forall (query :: DdK) (table :: DdK).
CheckQuery query table =>
Dd query -> Dd table -> QuerySchema (DdType query) (DdType table)
checkQuery Dd query
queryDd Dd table
tableDd
    TableSchema PgTable (DdType proj)
_ Row (DdType proj)
decoder Params (DdType proj)
_ =
      forall (table :: DdK).
MkTableSchema table =>
Dd table -> TableSchema (DdType table)
tableSchema Dd proj
projDd