packages feed

hasql-postgresql-types 0.1.0.1 → 0.2

raw patch · 5 files changed

+255/−52 lines, 5 filesdep +hasql-mappingdep +postgresql-typesdep ~hasqlPVP ok

version bump matches the API change (PVP)

Dependencies added: hasql-mapping, postgresql-types

Dependency ranges changed: hasql

API changes (from Hackage documentation)

- Hasql.PostgresqlTypes: decoder :: IsScalar a => Value a
- Hasql.PostgresqlTypes: encoder :: IsScalar a => Value a
+ Hasql.PostgresqlTypes: instance (GHC.Internal.TypeNats.KnownNat precision, GHC.Internal.TypeNats.KnownNat scale) => Hasql.Mapping.IsScalar.IsScalar (PostgresqlTypes.Numeric.Numeric precision scale)
+ Hasql.PostgresqlTypes: instance GHC.Internal.TypeNats.KnownNat len => Hasql.Mapping.IsScalar.IsScalar (PostgresqlTypes.Bit.Bit len)
+ Hasql.PostgresqlTypes: instance GHC.Internal.TypeNats.KnownNat len => Hasql.Mapping.IsScalar.IsScalar (PostgresqlTypes.Bpchar.Bpchar len)
+ Hasql.PostgresqlTypes: instance GHC.Internal.TypeNats.KnownNat maxLen => Hasql.Mapping.IsScalar.IsScalar (PostgresqlTypes.Varbit.Varbit maxLen)
+ Hasql.PostgresqlTypes: instance GHC.Internal.TypeNats.KnownNat maxLen => Hasql.Mapping.IsScalar.IsScalar (PostgresqlTypes.Varchar.Varchar maxLen)
+ Hasql.PostgresqlTypes: instance Hasql.Mapping.IsScalar.IsScalar PostgresqlTypes.Bool.Bool
+ Hasql.PostgresqlTypes: instance Hasql.Mapping.IsScalar.IsScalar PostgresqlTypes.Box.Box
+ Hasql.PostgresqlTypes: instance Hasql.Mapping.IsScalar.IsScalar PostgresqlTypes.Bytea.Bytea
+ Hasql.PostgresqlTypes: instance Hasql.Mapping.IsScalar.IsScalar PostgresqlTypes.Char.Char
+ Hasql.PostgresqlTypes: instance Hasql.Mapping.IsScalar.IsScalar PostgresqlTypes.Cidr.Cidr
+ Hasql.PostgresqlTypes: instance Hasql.Mapping.IsScalar.IsScalar PostgresqlTypes.Circle.Circle
+ Hasql.PostgresqlTypes: instance Hasql.Mapping.IsScalar.IsScalar PostgresqlTypes.Date.Date
+ Hasql.PostgresqlTypes: instance Hasql.Mapping.IsScalar.IsScalar PostgresqlTypes.Float4.Float4
+ Hasql.PostgresqlTypes: instance Hasql.Mapping.IsScalar.IsScalar PostgresqlTypes.Float8.Float8
+ Hasql.PostgresqlTypes: instance Hasql.Mapping.IsScalar.IsScalar PostgresqlTypes.Hstore.Hstore
+ Hasql.PostgresqlTypes: instance Hasql.Mapping.IsScalar.IsScalar PostgresqlTypes.Inet.Inet
+ Hasql.PostgresqlTypes: instance Hasql.Mapping.IsScalar.IsScalar PostgresqlTypes.Int2.Int2
+ Hasql.PostgresqlTypes: instance Hasql.Mapping.IsScalar.IsScalar PostgresqlTypes.Int4.Int4
+ Hasql.PostgresqlTypes: instance Hasql.Mapping.IsScalar.IsScalar PostgresqlTypes.Int8.Int8
+ Hasql.PostgresqlTypes: instance Hasql.Mapping.IsScalar.IsScalar PostgresqlTypes.Interval.Interval
+ Hasql.PostgresqlTypes: instance Hasql.Mapping.IsScalar.IsScalar PostgresqlTypes.Json.Json
+ Hasql.PostgresqlTypes: instance Hasql.Mapping.IsScalar.IsScalar PostgresqlTypes.Jsonb.Jsonb
+ Hasql.PostgresqlTypes: instance Hasql.Mapping.IsScalar.IsScalar PostgresqlTypes.Line.Line
+ Hasql.PostgresqlTypes: instance Hasql.Mapping.IsScalar.IsScalar PostgresqlTypes.Lseg.Lseg
+ Hasql.PostgresqlTypes: instance Hasql.Mapping.IsScalar.IsScalar PostgresqlTypes.Macaddr.Macaddr
+ Hasql.PostgresqlTypes: instance Hasql.Mapping.IsScalar.IsScalar PostgresqlTypes.Macaddr8.Macaddr8
+ Hasql.PostgresqlTypes: instance Hasql.Mapping.IsScalar.IsScalar PostgresqlTypes.Money.Money
+ Hasql.PostgresqlTypes: instance Hasql.Mapping.IsScalar.IsScalar PostgresqlTypes.Oid.Oid
+ Hasql.PostgresqlTypes: instance Hasql.Mapping.IsScalar.IsScalar PostgresqlTypes.Path.Path
+ Hasql.PostgresqlTypes: instance Hasql.Mapping.IsScalar.IsScalar PostgresqlTypes.Point.Point
+ Hasql.PostgresqlTypes: instance Hasql.Mapping.IsScalar.IsScalar PostgresqlTypes.Polygon.Polygon
+ Hasql.PostgresqlTypes: instance Hasql.Mapping.IsScalar.IsScalar PostgresqlTypes.Text.Text
+ Hasql.PostgresqlTypes: instance Hasql.Mapping.IsScalar.IsScalar PostgresqlTypes.Time.Time
+ Hasql.PostgresqlTypes: instance Hasql.Mapping.IsScalar.IsScalar PostgresqlTypes.Timestamp.Timestamp
+ Hasql.PostgresqlTypes: instance Hasql.Mapping.IsScalar.IsScalar PostgresqlTypes.Timestamptz.Timestamptz
+ Hasql.PostgresqlTypes: instance Hasql.Mapping.IsScalar.IsScalar PostgresqlTypes.Timetz.Timetz
+ Hasql.PostgresqlTypes: instance Hasql.Mapping.IsScalar.IsScalar PostgresqlTypes.Tsvector.Tsvector
+ Hasql.PostgresqlTypes: instance Hasql.Mapping.IsScalar.IsScalar PostgresqlTypes.Uuid.Uuid
+ Hasql.PostgresqlTypes: instance PostgresqlTypes.Algebra.IsMultirangeElement element => Hasql.Mapping.IsScalar.IsScalar (PostgresqlTypes.Multirange.Multirange element)
+ Hasql.PostgresqlTypes: instance PostgresqlTypes.Algebra.IsRangeElement element => Hasql.Mapping.IsScalar.IsScalar (PostgresqlTypes.Range.Range element)

Files

+ CHANGELOG.md view
@@ -0,0 +1,17 @@+# Changelog++## 0.2++*Breaking changes*++- Removed the `encoder` and `decoder` functions from `Hasql.PostgresqlTypes`. Codec access is now done via the `IsScalar` typeclass from the new [`hasql-mapping`](https://hackage.haskell.org/package/hasql-mapping) dependency. Import `Hasql.PostgresqlTypes ()` to bring the instances into scope, then use `Hasql.Mapping.IsScalar.encoder` and `Hasql.Mapping.IsScalar.decoder` (or the re-exports from `Hasql.Mapping`).+- Bumped `hasql` lower bound from `1.10.1` to `1.10.3`.++*New features*++- Added `IsScalar` instances for all PostgreSQL types defined in [`postgresql-types`](https://hackage.haskell.org/package/postgresql-types), including `Tsvector`.+- Added new dependencies: [`hasql-mapping`](https://hackage.haskell.org/package/hasql-mapping) and [`postgresql-types`](https://hackage.haskell.org/package/postgresql-types).++## 0.1.0.1++Initial release.
README.md view
@@ -13,16 +13,17 @@ ## Usage  ```haskell-import Hasql.PostgresqlTypes (encoder, decoder)+import Hasql.PostgresqlTypes () -- for the instances import qualified PostgresqlTypes as Pt import qualified Hasql.Statement as Statement import qualified Hasql.Encoders as Encoders import qualified Hasql.Decoders as Decoders+import qualified Hasql.Mapping.IsScalar as IsScalar  myStatement :: Statement.Statement Pt.Timestamptz [Pt.Timestamptz] myStatement = Statement.preparable sql enc dec   where     sql = "SELECT $1::timestamptz"-    enc = Encoders.param (Encoders.nonNullable encoder)-    dec = Decoders.rowList (Decoders.column (Decoders.nonNullable decoder))+    enc = Encoders.param (Encoders.nonNullable IsScalar.encoder)+    dec = Decoders.rowList (Decoders.column (Decoders.nonNullable IsScalar.decoder)) ```
hasql-postgresql-types.cabal view
@@ -1,6 +1,6 @@ cabal-version: 3.0 name: hasql-postgresql-types-version: 0.1.0.1+version: 0.2 category: PostgreSQL, Codecs, Hasql synopsis: Integration of "hasql" with "postgresql-types" description:@@ -19,6 +19,7 @@ license: MIT license-file: LICENSE extra-doc-files:+  CHANGELOG.md   LICENSE   README.md @@ -96,9 +97,14 @@   exposed-modules:     Hasql.PostgresqlTypes +  other-modules:+    Hasql.PostgresqlTypes.Core+   build-depends:     base >=4.11 && <5,-    hasql ^>=1.10.1,+    hasql ^>=1.10.3,+    hasql-mapping ^>=0.1,+    postgresql-types ^>=0.1,     postgresql-types-algebra ^>=0.1,     ptr-peeker ^>=0.1.0.1,     ptr-poker ^>=0.1.3,
src/library/Hasql/PostgresqlTypes.hs view
@@ -1,68 +1,191 @@+{-# OPTIONS_GHC -Wno-orphans #-}+ -- | -- This module provides a bridge between the types defined in the ["postgresql-types"](https://hackage.haskell.org/package/postgresql-types) and the ["hasql"](https://hackage.haskell.org/package/hasql) library, -- offering automatic encoder and decoder generation for types that implement the 'IsScalar' constraint. -- -- == Usage Example ----- > import Hasql.PostgresqlTypes (encoder, decoder)+-- > import Hasql.PostgresqlTypes () -- > import qualified PostgresqlTypes as Pt -- > import qualified Hasql.Statement as Statement -- > import qualified Hasql.Encoders as Encoders -- > import qualified Hasql.Decoders as Decoders+-- > import qualified Hasql.Mapping.IsScalar as IsScalar -- > -- > myStatement :: Statement.Statement Pt.Timestamptz [Pt.Timestamptz] -- > myStatement = Statement.preparable sql enc dec -- >   where -- >     sql = "SELECT $1::timestamptz"--- >     enc = Encoders.param (Encoders.nonNullable encoder)--- >     dec = Decoders.rowList (Decoders.column (Decoders.nonNullable decoder))+-- >     enc = Encoders.param (Encoders.nonNullable IsScalar.encoder)+-- >     dec = Decoders.rowList (Decoders.column (Decoders.nonNullable IsScalar.decoder)) -- -- The 'encoder' and 'decoder' functions work with any type having an 'IsScalar' instance, -- automatically handling binary encoding/decoding and OID resolution.-module Hasql.PostgresqlTypes-  ( encoder,-    decoder,-  )-where+module Hasql.PostgresqlTypes () where -import Data.String (fromString)-import Data.Tagged (untag)-import qualified Hasql.Decoders as Decoders-import qualified Hasql.Encoders as Encoders-import PostgresqlTypes.Algebra (IsScalar (..))-import qualified PtrPeeker-import qualified PtrPoker.Write as Write-import qualified TextBuilder-import Prelude+import GHC.TypeLits (KnownNat)+import qualified Hasql.Mapping.IsScalar as IsScalar+import qualified Hasql.PostgresqlTypes.Core as Core+import PostgresqlTypes+import PostgresqlTypes.Algebra --- | Hasql value encoder for a PostgreSQL standard type.------ Generates a Hasql value encoder for any type implementing 'IsScalar'.--- The encoder handles type resolution, and binary encoding automatically.-encoder :: forall a. (IsScalar a) => Encoders.Value a-encoder =-  Encoders.custom-    Nothing-    (untag (typeName @a))-    ((,) <$> untag (baseOid @a) <*> untag (arrayOid @a))-    []-    (\_ value -> Write.toByteString (binaryEncoder value))-    (TextBuilder.toText . textualEncoder)+instance (KnownNat len) => IsScalar.IsScalar (Bit len) where+  encoder = Core.encoder+  decoder = Core.decoder --- | Hasql value decoder for a PostgreSQL standard type.------ Generates a Hasql value decoder for any type implementing 'IsScalar'.--- The decoder handles type resolution, and binary decoding with proper error handling.-decoder :: forall a. (IsScalar a) => Decoders.Value a-decoder =-  Decoders.custom-    Nothing-    (untag (typeName @a))-    ((,) <$> untag (baseOid @a) <*> untag (arrayOid @a))-    []-    ( \_ bytes ->-        case PtrPeeker.runVariableOnByteString binaryDecoder bytes of-          Left bytesUnconsumed -> Left ("Binary decoder did not consume all input bytes, unconsumed bytes: " <> fromString (show bytesUnconsumed))-          Right (Left err) -> Left (fromString (show err))-          Right (Right value) -> Right value-    )+instance IsScalar.IsScalar Bool where+  encoder = Core.encoder+  decoder = Core.decoder++instance IsScalar.IsScalar Box where+  encoder = Core.encoder+  decoder = Core.decoder++instance (KnownNat len) => IsScalar.IsScalar (Bpchar len) where+  encoder = Core.encoder+  decoder = Core.decoder++instance IsScalar.IsScalar Bytea where+  encoder = Core.encoder+  decoder = Core.decoder++instance IsScalar.IsScalar Char where+  encoder = Core.encoder+  decoder = Core.decoder++instance IsScalar.IsScalar Cidr where+  encoder = Core.encoder+  decoder = Core.decoder++instance IsScalar.IsScalar Circle where+  encoder = Core.encoder+  decoder = Core.decoder++instance IsScalar.IsScalar Date where+  encoder = Core.encoder+  decoder = Core.decoder++instance IsScalar.IsScalar Float4 where+  encoder = Core.encoder+  decoder = Core.decoder++instance IsScalar.IsScalar Float8 where+  encoder = Core.encoder+  decoder = Core.decoder++instance IsScalar.IsScalar Hstore where+  encoder = Core.encoder+  decoder = Core.decoder++instance IsScalar.IsScalar Inet where+  encoder = Core.encoder+  decoder = Core.decoder++instance IsScalar.IsScalar Int2 where+  encoder = Core.encoder+  decoder = Core.decoder++instance IsScalar.IsScalar Int4 where+  encoder = Core.encoder+  decoder = Core.decoder++instance IsScalar.IsScalar Int8 where+  encoder = Core.encoder+  decoder = Core.decoder++instance IsScalar.IsScalar Interval where+  encoder = Core.encoder+  decoder = Core.decoder++instance IsScalar.IsScalar Json where+  encoder = Core.encoder+  decoder = Core.decoder++instance IsScalar.IsScalar Jsonb where+  encoder = Core.encoder+  decoder = Core.decoder++instance IsScalar.IsScalar Line where+  encoder = Core.encoder+  decoder = Core.decoder++instance IsScalar.IsScalar Lseg where+  encoder = Core.encoder+  decoder = Core.decoder++instance IsScalar.IsScalar Macaddr where+  encoder = Core.encoder+  decoder = Core.decoder++instance IsScalar.IsScalar Macaddr8 where+  encoder = Core.encoder+  decoder = Core.decoder++instance IsScalar.IsScalar Money where+  encoder = Core.encoder+  decoder = Core.decoder++instance (IsMultirangeElement element) => IsScalar.IsScalar (Multirange element) where+  encoder = Core.encoder+  decoder = Core.decoder++instance (KnownNat precision, KnownNat scale) => IsScalar.IsScalar (Numeric precision scale) where+  encoder = Core.encoder+  decoder = Core.decoder++instance IsScalar.IsScalar Oid where+  encoder = Core.encoder+  decoder = Core.decoder++instance IsScalar.IsScalar Path where+  encoder = Core.encoder+  decoder = Core.decoder++instance IsScalar.IsScalar Point where+  encoder = Core.encoder+  decoder = Core.decoder++instance IsScalar.IsScalar Polygon where+  encoder = Core.encoder+  decoder = Core.decoder++instance (IsRangeElement element) => IsScalar.IsScalar (Range element) where+  encoder = Core.encoder+  decoder = Core.decoder++instance IsScalar.IsScalar Text where+  encoder = Core.encoder+  decoder = Core.decoder++instance IsScalar.IsScalar Time where+  encoder = Core.encoder+  decoder = Core.decoder++instance IsScalar.IsScalar Timestamp where+  encoder = Core.encoder+  decoder = Core.decoder++instance IsScalar.IsScalar Timestamptz where+  encoder = Core.encoder+  decoder = Core.decoder++instance IsScalar.IsScalar Timetz where+  encoder = Core.encoder+  decoder = Core.decoder++instance IsScalar.IsScalar Uuid where+  encoder = Core.encoder+  decoder = Core.decoder++instance (KnownNat maxLen) => IsScalar.IsScalar (Varbit maxLen) where+  encoder = Core.encoder+  decoder = Core.decoder++instance (KnownNat maxLen) => IsScalar.IsScalar (Varchar maxLen) where+  encoder = Core.encoder+  decoder = Core.decoder++instance IsScalar.IsScalar Tsvector where+  encoder = Core.encoder+  decoder = Core.decoder
+ src/library/Hasql/PostgresqlTypes/Core.hs view
@@ -0,0 +1,56 @@+-- |+-- Internal implementation of the hasql encoder and decoder for types+-- that implement the 'IsScalar' constraint from+-- ["postgresql-types-algebra"](https://hackage.haskell.org/package/postgresql-types-algebra).+-- These are used by the 'IsScalar.IsScalar' instances defined in+-- "Hasql.PostgresqlTypes".+--+-- The 'encoder' and 'decoder' functions work with any type having an 'IsScalar' instance,+-- automatically handling binary encoding/decoding and OID resolution.+module Hasql.PostgresqlTypes.Core+  ( encoder,+    decoder,+  )+where++import Data.String (fromString)+import Data.Tagged (untag)+import qualified Hasql.Decoders as Decoders+import qualified Hasql.Encoders as Encoders+import PostgresqlTypes.Algebra (IsScalar (..))+import qualified PtrPeeker+import qualified PtrPoker.Write as Write+import qualified TextBuilder+import Prelude++-- | Hasql value encoder for a PostgreSQL standard type.+--+-- Generates a Hasql value encoder for any type implementing 'IsScalar'.+-- The encoder handles type resolution, and binary encoding automatically.+encoder :: forall a. (IsScalar a) => Encoders.Value a+encoder =+  Encoders.custom+    Nothing+    (untag (typeName @a))+    ((,) <$> untag (baseOid @a) <*> untag (arrayOid @a))+    []+    (\_ value -> Write.toByteString (binaryEncoder value))+    (TextBuilder.toText . textualEncoder)++-- | Hasql value decoder for a PostgreSQL standard type.+--+-- Generates a Hasql value decoder for any type implementing 'IsScalar'.+-- The decoder handles type resolution, and binary decoding with proper error handling.+decoder :: forall a. (IsScalar a) => Decoders.Value a+decoder =+  Decoders.custom+    Nothing+    (untag (typeName @a))+    ((,) <$> untag (baseOid @a) <*> untag (arrayOid @a))+    []+    ( \_ bytes ->+        case PtrPeeker.runVariableOnByteString binaryDecoder bytes of+          Left bytesUnconsumed -> Left ("Binary decoder did not consume all input bytes, unconsumed bytes: " <> fromString (show bytesUnconsumed))+          Right (Left err) -> Left (fromString (show err))+          Right (Right value) -> Right value+    )