Skip to content

Commit e6e0f6e

Browse files
authoredMar 26, 2025··
add array_agg functions (#9)
* nix update * require esqueleto 3.6 * add array_agg functions
1 parent 971add0 commit e6e0f6e

File tree

11 files changed

+170
-41
lines changed

11 files changed

+170
-41
lines changed
 

‎flake.lock

+49-32
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎flake.nix

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
inputs = {
33
nixpkgs.url = "github:nixos/nixpkgs/nixos-24.11";
4-
freckle.url = "git+ssh://git@github.com/freckle/flakes?dir=main";
4+
freckle.url = "github:freckle/flakes?dir=main";
55
flake-utils.url = "github:numtide/flake-utils";
66
};
77
outputs =

‎persistent-sql-lifted/CHANGELOG.md

+5-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
## [_Unreleased_](https://github.com/freckle/persistent-sql-lifted/compare/persistent-sql-lifted-v0.4.0.0...main)
1+
## [_Unreleased_](https://github.com/freckle/persistent-sql-lifted/compare/persistent-sql-lifted-v0.4.1.0...main)
2+
3+
## [v0.4.1.0](https://github.com/freckle/persistent-sql-lifted/compare/persistent-sql-lifted-v0.4.0.0...persistent-sql-lifted-v0.4.1.0)
4+
5+
Add module `Database.Persist.Sql.Lifted.Expression.ArrayAggregate.PostgreSQL`
26

37
## [v0.4.0.0](https://github.com/freckle/persistent-sql-lifted/compare/persistent-sql-lifted-v0.3.0.0...persistent-sql-lifted-v0.4.0.0)
48

‎persistent-sql-lifted/README.md

+11-5
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,14 @@ How to migrate from vanilla persistent/esqueleto:
2323
- Instead of calling `runSqlPool` directly from the rest of your application code,
2424
use the `runSqlTx` method from the `MonadSqlTx` class.
2525

26-
[checkpointCallStack]: https://hackage.haskell.org/package/annotated-exception-0.3.0.2/docs/Control-Exception-Annotated-UnliftIO.html
27-
[esqueleto]: https://hackage.haskell.org/package/esqueleto
28-
[persistent]: https://hackage.haskell.org/package/persistent
29-
[runSqlPool]: https://hackage.haskell.org/package/persistent-2.14.6.3/docs/Database-Persist-Sql.html#v:runSqlPool
30-
[SqlPersistT]: https://hackage.haskell.org/package/persistent-2.14.6.3/docs/Database-Persist-Sql.html#t:SqlPersistT
26+
For constructing SQL expressions, you may which to import the utilities from
27+
`Database.Persist.Sql.Lifted.Expression` et al rather than getting them from
28+
Esqueleto. This allows you to import the specific bits you need piecemeal and
29+
without having to hide the unlifted versions of query-running functions that this
30+
package replaces. Moreover, this package contains some additional utilities.
31+
32+
[checkpointCallStack]: https://hackage.haskell.org/package/annotated-exception-0.3.0.2/docs/Control-Exception-Annotated-UnliftIO.html
33+
[esqueleto]: https://hackage.haskell.org/package/esqueleto
34+
[persistent]: https://hackage.haskell.org/package/persistent
35+
[runSqlPool]: https://hackage.haskell.org/package/persistent-2.14.6.3/docs/Database-Persist-Sql.html#v:runSqlPool
36+
[SqlPersistT]: https://hackage.haskell.org/package/persistent-2.14.6.3/docs/Database-Persist-Sql.html#t:SqlPersistT
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
module Database.Persist.Sql.Lifted.Expression.ArrayAggregate.PostgreSQL
2+
( AggMode (..)
3+
, arrayAggDistinct
4+
, arrayAgg
5+
, arrayAggWith
6+
, arrayRemove
7+
, arrayRemoveNull
8+
, maybeArray
9+
, arrayAggById
10+
, arrayAggByIdMaybe
11+
, arrayAggByMaybe
12+
, arrayAggBy
13+
) where
14+
15+
import Prelude
16+
17+
import Database.Esqueleto.Experimental
18+
( Entity
19+
, EntityField
20+
, PersistEntity
21+
, PersistField
22+
, SqlExpr
23+
, Value
24+
, asc
25+
, persistIdField
26+
, (^.)
27+
)
28+
import Database.Esqueleto.Internal.Internal
29+
( (??.)
30+
)
31+
import Database.Esqueleto.PostgreSQL
32+
( AggMode (..)
33+
, arrayAgg
34+
, arrayAggDistinct
35+
, arrayAggWith
36+
, arrayRemove
37+
, arrayRemoveNull
38+
, maybeArray
39+
)
40+
41+
-- | Aggregrate the given column with stable ordering (by ID)
42+
--
43+
-- This ensures that if you aggregrate two columns:
44+
--
45+
-- @
46+
-- pure
47+
-- ( 'arrayAggById' students StudentFirstName
48+
-- , 'arrayAggById' students StudentLastName
49+
-- )
50+
-- @
51+
--
52+
-- The list, if zipped, will be as expected.
53+
--
54+
-- See <https://stackoverflow.com/a/7317520>.
55+
--
56+
-- Also replaces the 'Maybe' result with an empty list, because really that's
57+
-- what you always want.
58+
arrayAggById
59+
:: (PersistEntity val, PersistField [typ], PersistField typ)
60+
=> SqlExpr (Entity val)
61+
-> EntityField val typ
62+
-> SqlExpr (Value [typ])
63+
arrayAggById es f = arrayAggBy (es ^. f) (es ^. persistIdField)
64+
65+
-- | 'arrayAggById' but for a left-outer-joined entity
66+
--
67+
-- If you're using '(?.)' instead of '(^.)', use this instead of 'arrayAggById'.
68+
arrayAggByIdMaybe
69+
:: (PersistEntity val, PersistField typ)
70+
=> SqlExpr (Maybe (Entity val))
71+
-> EntityField val typ
72+
-> SqlExpr (Value [typ])
73+
arrayAggByIdMaybe es f =
74+
arrayRemoveNull $ arrayAggBy (es ??. f) (es ??. persistIdField)
75+
76+
-- | 'arrayAggBy' but for a left-outer-joined entity
77+
--
78+
-- If you're using '(?.)' instead of '(^.)', use this instead of 'arrayAggBy'.
79+
arrayAggByMaybe
80+
:: (PersistField a, PersistField b)
81+
=> SqlExpr (Value (Maybe a))
82+
-> SqlExpr (Value b)
83+
-> SqlExpr (Value [a])
84+
arrayAggByMaybe a = arrayRemoveNull . arrayAggBy a
85+
86+
arrayAggBy
87+
:: (PersistField [a], PersistField a, PersistField b)
88+
=> SqlExpr (Value a)
89+
-> SqlExpr (Value b)
90+
-> SqlExpr (Value [a])
91+
arrayAggBy a b = maybeArray $ arrayAggWith AggModeAll a [asc b]

‎persistent-sql-lifted/package.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: persistent-sql-lifted
2-
version: 0.4.0.0
2+
version: 0.4.1.0
33

44
maintainer: Freckle Education
55
category: Database

‎persistent-sql-lifted/persistent-sql-lifted.cabal

+2-1
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ cabal-version: 1.18
55
-- see: https://github.com/sol/hpack
66

77
name: persistent-sql-lifted
8-
version: 0.4.0.0
8+
version: 0.4.1.0
99
synopsis: Monad classes for running queries with Persistent and Esqueleto
1010
description: This package introduces two classes: MonadSqlBackend for monadic contexts in
1111
which a SqlBackend is available, and MonadSqlTx for contexts in which we
@@ -38,6 +38,7 @@ library
3838
Database.Persist.Sql.Lifted.Core
3939
Database.Persist.Sql.Lifted.Esqueleto
4040
Database.Persist.Sql.Lifted.Expression
41+
Database.Persist.Sql.Lifted.Expression.ArrayAggregate.PostgreSQL
4142
Database.Persist.Sql.Lifted.Expression.Bool
4243
Database.Persist.Sql.Lifted.Expression.Case
4344
Database.Persist.Sql.Lifted.Expression.Comparison

‎stack-lts20.yaml

+1
Original file line numberDiff line numberDiff line change
@@ -4,4 +4,5 @@ packages:
44
- persistent-sql-lifted
55

66
extra-deps:
7+
- esqueleto-3.6.0.0
78
- persistent-2.14.5.0

‎stack-lts21.yaml

+3
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,6 @@ resolver: lts-21.25
22

33
packages:
44
- persistent-sql-lifted
5+
6+
extra-deps:
7+
- esqueleto-3.6.0.0

‎stack-lts22.yaml

+3
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,6 @@ resolver: lts-22.43
22

33
packages:
44
- persistent-sql-lifted
5+
6+
extra-deps:
7+
- esqueleto-3.6.0.0

‎stack-lts23.yaml

+3
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,6 @@ resolver: lts-23.3
22

33
packages:
44
- persistent-sql-lifted
5+
6+
extra-deps:
7+
- esqueleto-3.6.0.0

0 commit comments

Comments
 (0)
Please sign in to comment.