Skip to content

Commit

Permalink
Support nested catListTable (by represented nested arrays as text) (#…
Browse files Browse the repository at this point in the history
…242)

This is one possible "fix" to #168. With this we can `catListTable` arbitrarily deep trees of `ListTable`s.

It comes at a relatively high cost, however.

Currently we represent nested arrays with anonymous records. This works reasonably well, except that we can't extract the field from the anonymous record when we need it (PostgreSQL [theoretically](https://www.postgresql.org/docs/13/release-13.html#id-1.11.6.16.5.6) suports `.f1` syntax since PG13 but it only works in very limited situations). But it does mean we can decode the results using Hasql's binary decoders, and ordering works how we expect ('array[row(array[9])] < array[row(array[10])]'.

What this PR does is instead represent nested arrays as text. To be able to decode this, we need each 'DBType' to supply a text parser in addition to a binary decoder. It also means that ordering is no longer intuitive, because `array[array[9]::text] > array[array[10]::text]`. However, it does mean we can nest `catListTable`s to our heart's content and it will always just work.
  • Loading branch information
shane-circuithub authored Sep 27, 2023
1 parent 72a76aa commit 10eab21
Show file tree
Hide file tree
Showing 14 changed files with 614 additions and 93 deletions.
6 changes: 5 additions & 1 deletion changelog.d/20230707_185221_ollie_scriv.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
### Fixed

- A partial fix for nesting `catListTable`. The underlying issue in [#168](https://github.com/circuithub/rel8/issues/168) is still present, but we've made a bit of progress to reduce when this bug can happen. ([#243](https://github.com/circuithub/rel8/pull/243))
- A fix for [#168](https://github.com/circuithub/rel8/issues/168), which prevented using `catListTable` on arrays of arrays. To achieve this we had to coerce arrays of arrays to text internally, which unfortunately isn't completely transparent; you can oberve it if you write something like `listTable [listTable [10]] > listTable [listTable [9]]`: previously that would be `false`, but now it's `true`. Arrays of non-arrays are unaffected by this.

### Changed

- `TypeInformation`'s `decoder` field has changed. Instead of taking a `Hasql.Decoder`, it now takes a `Rel8.Decoder`, which itself is comprised of a `Hasql.Decoder` and an `attoparsec` `Parser`. This is necessitated by the fix for [#168](https://github.com/circuithub/rel8/issues/168); we generally decode things in PostgreSQL's binary format (using a `Hasql.Decoder`), but for nested arrays we now get things in PostgreSQL's text format (for which we need an `attoparsec` `Parser`), so must have both. Most `DBType` instances that use `mapTypeInformation` or `ParseTypeInformation`, or `DerivingVia` helpers like `ReadShow`, `JSONBEncoded`, `Enum` and `Composite` are unaffected by this change.
9 changes: 9 additions & 0 deletions rel8.cabal
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,16 @@ source-repository head
library
build-depends:
aeson
, attoparsec
, base ^>= 4.14 || ^>=4.15 || ^>=4.16 || ^>=4.17
, base16 >= 1.0
, base-compat ^>= 0.11 || ^>= 0.12 || ^>= 0.13
, bifunctors
, bytestring
, case-insensitive
, comonad
, contravariant
, data-textual
, hasql ^>= 1.6.1.2
, network-ip
, opaleye ^>= 0.10.0.0
Expand All @@ -40,8 +43,10 @@ library
, these
, time
, transformers
, utf8-string
, uuid
, vector

default-language:
Haskell2010
ghc-options:
Expand Down Expand Up @@ -201,6 +206,7 @@ library
Rel8.Type
Rel8.Type.Array
Rel8.Type.Composite
Rel8.Type.Decoder
Rel8.Type.Eq
Rel8.Type.Enum
Rel8.Type.Information
Expand All @@ -210,6 +216,9 @@ library
Rel8.Type.Name
Rel8.Type.Num
Rel8.Type.Ord
Rel8.Type.Parser
Rel8.Type.Parser.ByteString
Rel8.Type.Parser.Time
Rel8.Type.ReadShow
Rel8.Type.Semigroup
Rel8.Type.String
Expand Down
7 changes: 4 additions & 3 deletions src/Rel8/Expr/Serialize.hs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {-# SOURCE #-} Rel8.Expr ( Expr( Expr ) )
import Rel8.Expr.Opaleye ( scastExpr )
import Rel8.Schema.Null ( Unnullify, Nullity( Null, NotNull ), Sql, nullable )
import Rel8.Type ( DBType, typeInformation )
import Rel8.Type.Decoder (Decoder (..))
import Rel8.Type.Information ( TypeInformation(..) )


Expand All @@ -44,6 +45,6 @@ slitExpr nullity info@TypeInformation {encode} =


sparseValue :: Nullity a -> TypeInformation (Unnullify a) -> Hasql.Row a
sparseValue nullity TypeInformation {decode} = case nullity of
Null -> Hasql.column $ Hasql.nullable decode
NotNull -> Hasql.column $ Hasql.nonNullable decode
sparseValue nullity TypeInformation {decode = Decoder {binary}} = case nullity of
Null -> Hasql.column $ Hasql.nullable binary
NotNull -> Hasql.column $ Hasql.nonNullable binary
Loading

0 comments on commit 10eab21

Please sign in to comment.