module Rel8.Query.Indexed
  ( indexed
  )
where

-- base
import Data.Int ( Int64 )
import Prelude

-- opaleye
import qualified Opaleye.Internal.HaskellDB.PrimQuery as Opaleye
import qualified Opaleye.Internal.PackMap as Opaleye
import qualified Opaleye.Internal.PrimQuery as Opaleye
import qualified Opaleye.Internal.QueryArr as Opaleye
import qualified Opaleye.Internal.Tag as Opaleye

-- rel8
import Rel8.Expr ( Expr )
import Rel8.Expr.Opaleye ( fromPrimExpr )
import Rel8.Query ( Query )
import Rel8.Query.Opaleye ( mapOpaleye )


-- | Pair each row of a query with its index within the query.
indexed :: Query a -> Query (Expr Int64, a)
indexed :: Query a -> Query (Expr Int64, a)
indexed = (Select a -> Select (Expr Int64, a))
-> Query a -> Query (Expr Int64, a)
forall a b. (Select a -> Select b) -> Query a -> Query b
mapOpaleye ((Select a -> Select (Expr Int64, a))
 -> Query a -> Query (Expr Int64, a))
-> (Select a -> Select (Expr Int64, a))
-> Query a
-> Query (Expr Int64, a)
forall a b. (a -> b) -> a -> b
$ \Select a
f -> (() -> Tag -> ((Expr Int64, a), PrimQueryArr, Tag))
-> Select (Expr Int64, a)
forall a b. (a -> Tag -> (b, PrimQueryArr, Tag)) -> QueryArr a b
Opaleye.stateQueryArr ((() -> Tag -> ((Expr Int64, a), PrimQueryArr, Tag))
 -> Select (Expr Int64, a))
-> (() -> Tag -> ((Expr Int64, a), PrimQueryArr, Tag))
-> Select (Expr Int64, a)
forall a b. (a -> b) -> a -> b
$ \()
_ Tag
tag ->
  let
    (a
a, PrimQueryArr
query, Tag
tag') = Select a -> () -> Tag -> (a, PrimQueryArr, Tag)
forall a b. QueryArr a b -> a -> Tag -> (b, PrimQueryArr, Tag)
Opaleye.runStateQueryArr Select a
f () Tag
tag
    tag'' :: Tag
tag'' = Tag -> Tag
Opaleye.next Tag
tag'
    window :: PrimExpr
window = Literal -> PrimExpr
Opaleye.ConstExpr (Literal -> PrimExpr) -> Literal -> PrimExpr
forall a b. (a -> b) -> a -> b
$ String -> Literal
Opaleye.OtherLit String
"ROW_NUMBER() OVER () - 1"
    (PrimExpr
index, [(Symbol, PrimExpr)]
bindings) = PM [(Symbol, PrimExpr)] PrimExpr
-> (PrimExpr, [(Symbol, PrimExpr)])
forall a r. PM [a] r -> (r, [a])
Opaleye.run (PM [(Symbol, PrimExpr)] PrimExpr
 -> (PrimExpr, [(Symbol, PrimExpr)]))
-> PM [(Symbol, PrimExpr)] PrimExpr
-> (PrimExpr, [(Symbol, PrimExpr)])
forall a b. (a -> b) -> a -> b
$ String -> Tag -> PrimExpr -> PM [(Symbol, PrimExpr)] PrimExpr
forall primExpr.
String -> Tag -> primExpr -> PM [(Symbol, primExpr)] PrimExpr
Opaleye.extractAttr String
"index" Tag
tag' PrimExpr
window
    query' :: PrimQueryArr
query' = PrimQueryArr
query PrimQueryArr -> PrimQueryArr -> PrimQueryArr
forall a. Semigroup a => a -> a -> a
<> [(Symbol, PrimExpr)] -> PrimQueryArr
Opaleye.aRebind [(Symbol, PrimExpr)]
bindings
  in
    ((PrimExpr -> Expr Int64
forall a. PrimExpr -> Expr a
fromPrimExpr PrimExpr
index, a
a), PrimQueryArr
query', Tag
tag'')