on master help sign in
Add indexed combinator (#117)
commit7c33143d11c0f8cc0110a700415afc29989c5f0a authorShane <shane.obrien@circuithub.com> dateFri 16 Jul 2021, 16:18 (5 years ago) parentb0e47ec
4 files changed+41
Changelog.md+2 rel8.cabal+1 src/Rel8.hs+4 src/Rel8/Query/Indexed.hs+34
Changelog.md+2
@@ -27,6 +27,8 @@
2727
2828* The new `Rel8.Tabulate` module has been added, which gives a `Map`-esque interface to writing and composing queries. ([#70](https://github.com/circuithub/rel8/pull/70))
2929
30+* The new `indexed` `Query -> Query` function was added. This function augments each row in a query with it's 0-based index. ([#117](https://github.com/circuithub/rel8/pull/117))
31+
3032## Breaking changes
3133
3234* `Insert`, `Delete` and `Update` have all changed. In particular, for `Insert` users should now replace `rows = xs` with `rows = values xs`. ([#85](https://github.com/circuithub/rel8/pull/85))
rel8.cabal+1
@@ -106,6 +106,7 @@ library
106106 Rel8.Query.Evaluate
107107 Rel8.Query.Exists
108108 Rel8.Query.Filter
109+ Rel8.Query.Indexed
109110 Rel8.Query.Limit
110111 Rel8.Query.List
111112 Rel8.Query.Maybe
src/Rel8.hs+4
@@ -244,6 +244,9 @@ module Rel8
244244 , nullsFirst
245245 , nullsLast
246246
247+ -- ** Window functions
248+ , indexed
249+
247250 -- ** Bindings
248251 , rebind
249252
@@ -322,6 +325,7 @@ import Rel8.Query.Either
322325import Rel8.Query.Evaluate
323326import Rel8.Query.Exists
324327import Rel8.Query.Filter
328+import Rel8.Query.Indexed
325329import Rel8.Query.Limit
326330import Rel8.Query.List
327331import Rel8.Query.Maybe
src/Rel8/Query/Indexed.hsnew file+34
@@ -0,0 +1,34 @@
1+module Rel8.Query.Indexed
2+ ( indexed
3+ )
4+where
5+
6+-- base
7+import Data.Int ( Int64 )
8+import Prelude
9+
10+-- opaleye
11+import qualified Opaleye.Internal.HaskellDB.PrimQuery as Opaleye
12+import qualified Opaleye.Internal.PackMap as Opaleye
13+import qualified Opaleye.Internal.PrimQuery as Opaleye
14+import qualified Opaleye.Internal.QueryArr as Opaleye
15+import qualified Opaleye.Internal.Tag as Opaleye
16+
17+-- rel8
18+import Rel8.Expr ( Expr )
19+import Rel8.Expr.Opaleye ( fromPrimExpr )
20+import Rel8.Query ( Query )
21+import Rel8.Query.Opaleye ( mapOpaleye )
22+
23+
24+-- | Pair each row of a query with its index within the query.
25+indexed :: Query a -> Query (Expr Int64, a)
26+indexed = mapOpaleye $ \(Opaleye.QueryArr f) -> Opaleye.QueryArr $ \(_, tag) ->
27+ let
28+ (a, query, tag') = f ((), tag)
29+ tag'' = Opaleye.next tag'
30+ window = Opaleye.ConstExpr $ Opaleye.OtherLit "ROW_NUMBER() OVER () - 1"
31+ (index, bindings) = Opaleye.run $ Opaleye.extractAttr "index" tag' window
32+ query' lateral = Opaleye.Rebind True bindings . query lateral
33+ in
34+ ((fromPrimExpr index, a), query', tag'')