packages feed

hasql 1.3.0.6 → 1.4

raw patch · 18 files changed

+1118/−1427 lines, 18 filesdep −data-default-classPVP ok

version bump matches the API change (PVP)

Dependencies removed: data-default-class

API changes (from Hackage documentation)

- Hasql.Decoders: instance (Data.Default.Class.Default (Hasql.Decoders.Value a1), Data.Default.Class.Default (Hasql.Decoders.Value a2)) => Data.Default.Class.Default (Hasql.Decoders.Row (a1, a2))
- Hasql.Decoders: instance Data.Default.Class.Default (Hasql.Decoders.Result ())
- Hasql.Decoders: instance Data.Default.Class.Default (Hasql.Decoders.Result GHC.Int.Int64)
- Hasql.Decoders: instance Data.Default.Class.Default (Hasql.Decoders.Row a) => Data.Default.Class.Default (Hasql.Decoders.Result (Data.Functor.Identity.Identity a))
- Hasql.Decoders: instance Data.Default.Class.Default (Hasql.Decoders.Row a) => Data.Default.Class.Default (Hasql.Decoders.Result (Data.Vector.Vector a))
- Hasql.Decoders: instance Data.Default.Class.Default (Hasql.Decoders.Row a) => Data.Default.Class.Default (Hasql.Decoders.Result (GHC.Maybe.Maybe a))
- Hasql.Decoders: instance Data.Default.Class.Default (Hasql.Decoders.Row a) => Data.Default.Class.Default (Hasql.Decoders.Result [a])
- Hasql.Decoders: instance Data.Default.Class.Default (Hasql.Decoders.Value (Data.Time.LocalTime.Internal.TimeOfDay.TimeOfDay, Data.Time.LocalTime.Internal.TimeZone.TimeZone))
- Hasql.Decoders: instance Data.Default.Class.Default (Hasql.Decoders.Value Data.Aeson.Types.Internal.Value)
- Hasql.Decoders: instance Data.Default.Class.Default (Hasql.Decoders.Value Data.ByteString.Internal.ByteString)
- Hasql.Decoders: instance Data.Default.Class.Default (Hasql.Decoders.Value Data.Scientific.Scientific)
- Hasql.Decoders: instance Data.Default.Class.Default (Hasql.Decoders.Value Data.Text.Internal.Text)
- Hasql.Decoders: instance Data.Default.Class.Default (Hasql.Decoders.Value Data.Time.Calendar.Days.Day)
- Hasql.Decoders: instance Data.Default.Class.Default (Hasql.Decoders.Value Data.Time.Clock.Internal.DiffTime.DiffTime)
- Hasql.Decoders: instance Data.Default.Class.Default (Hasql.Decoders.Value Data.Time.Clock.Internal.UTCTime.UTCTime)
- Hasql.Decoders: instance Data.Default.Class.Default (Hasql.Decoders.Value Data.Time.LocalTime.Internal.LocalTime.LocalTime)
- Hasql.Decoders: instance Data.Default.Class.Default (Hasql.Decoders.Value Data.Time.LocalTime.Internal.TimeOfDay.TimeOfDay)
- Hasql.Decoders: instance Data.Default.Class.Default (Hasql.Decoders.Value Data.UUID.Types.Internal.UUID)
- Hasql.Decoders: instance Data.Default.Class.Default (Hasql.Decoders.Value GHC.Int.Int16)
- Hasql.Decoders: instance Data.Default.Class.Default (Hasql.Decoders.Value GHC.Int.Int32)
- Hasql.Decoders: instance Data.Default.Class.Default (Hasql.Decoders.Value GHC.Int.Int64)
- Hasql.Decoders: instance Data.Default.Class.Default (Hasql.Decoders.Value GHC.Types.Bool)
- Hasql.Decoders: instance Data.Default.Class.Default (Hasql.Decoders.Value GHC.Types.Char)
- Hasql.Decoders: instance Data.Default.Class.Default (Hasql.Decoders.Value GHC.Types.Double)
- Hasql.Decoders: instance Data.Default.Class.Default (Hasql.Decoders.Value GHC.Types.Float)
- Hasql.Decoders: instance Data.Default.Class.Default (Hasql.Decoders.Value a) => Data.Default.Class.Default (Hasql.Decoders.Row (Data.Functor.Identity.Identity a))
- Hasql.Decoders: instance Data.Default.Class.Default (Hasql.Decoders.Value a) => Data.Default.Class.Default (Hasql.Decoders.Row (GHC.Maybe.Maybe a))
- Hasql.Decoders: instance GHC.Base.Applicative Hasql.Decoders.Composite
- Hasql.Decoders: instance GHC.Base.Applicative Hasql.Decoders.Row
- Hasql.Decoders: instance GHC.Base.Functor Hasql.Decoders.Array
- Hasql.Decoders: instance GHC.Base.Functor Hasql.Decoders.Composite
- Hasql.Decoders: instance GHC.Base.Functor Hasql.Decoders.Result
- Hasql.Decoders: instance GHC.Base.Functor Hasql.Decoders.Row
- Hasql.Decoders: instance GHC.Base.Functor Hasql.Decoders.Value
- Hasql.Decoders: instance GHC.Base.Monad Hasql.Decoders.Composite
- Hasql.Decoders: instance GHC.Base.Monad Hasql.Decoders.Row
- Hasql.Decoders: nullableColumn :: Value a -> Row (Maybe a)
- Hasql.Decoders: nullableElement :: Value a -> Array (Maybe a)
- Hasql.Decoders: nullableField :: Value a -> Composite (Maybe a)
- Hasql.Decoders: unit :: Result ()
- Hasql.Encoders: instance (Data.Default.Class.Default (Hasql.Encoders.Value a1), Data.Default.Class.Default (Hasql.Encoders.Value a2)) => Data.Default.Class.Default (Hasql.Encoders.Params (a1, a2))
- Hasql.Encoders: instance (Data.Default.Class.Default (Hasql.Encoders.Value a1), Data.Default.Class.Default (Hasql.Encoders.Value a2), Data.Default.Class.Default (Hasql.Encoders.Value a3)) => Data.Default.Class.Default (Hasql.Encoders.Params (a1, a2, a3))
- Hasql.Encoders: instance (Data.Default.Class.Default (Hasql.Encoders.Value a1), Data.Default.Class.Default (Hasql.Encoders.Value a2), Data.Default.Class.Default (Hasql.Encoders.Value a3), Data.Default.Class.Default (Hasql.Encoders.Value a4)) => Data.Default.Class.Default (Hasql.Encoders.Params (a1, a2, a3, a4))
- Hasql.Encoders: instance (Data.Default.Class.Default (Hasql.Encoders.Value a1), Data.Default.Class.Default (Hasql.Encoders.Value a2), Data.Default.Class.Default (Hasql.Encoders.Value a3), Data.Default.Class.Default (Hasql.Encoders.Value a4), Data.Default.Class.Default (Hasql.Encoders.Value a5)) => Data.Default.Class.Default (Hasql.Encoders.Params (a1, a2, a3, a4, a5))
- Hasql.Encoders: instance Data.Default.Class.Default (Hasql.Encoders.Params ())
- Hasql.Encoders: instance Data.Default.Class.Default (Hasql.Encoders.Value (Data.Time.LocalTime.Internal.TimeOfDay.TimeOfDay, Data.Time.LocalTime.Internal.TimeZone.TimeZone))
- Hasql.Encoders: instance Data.Default.Class.Default (Hasql.Encoders.Value Data.Aeson.Types.Internal.Value)
- Hasql.Encoders: instance Data.Default.Class.Default (Hasql.Encoders.Value Data.ByteString.Internal.ByteString)
- Hasql.Encoders: instance Data.Default.Class.Default (Hasql.Encoders.Value Data.Scientific.Scientific)
- Hasql.Encoders: instance Data.Default.Class.Default (Hasql.Encoders.Value Data.Text.Internal.Text)
- Hasql.Encoders: instance Data.Default.Class.Default (Hasql.Encoders.Value Data.Time.Calendar.Days.Day)
- Hasql.Encoders: instance Data.Default.Class.Default (Hasql.Encoders.Value Data.Time.Clock.Internal.DiffTime.DiffTime)
- Hasql.Encoders: instance Data.Default.Class.Default (Hasql.Encoders.Value Data.Time.Clock.Internal.UTCTime.UTCTime)
- Hasql.Encoders: instance Data.Default.Class.Default (Hasql.Encoders.Value Data.Time.LocalTime.Internal.LocalTime.LocalTime)
- Hasql.Encoders: instance Data.Default.Class.Default (Hasql.Encoders.Value Data.Time.LocalTime.Internal.TimeOfDay.TimeOfDay)
- Hasql.Encoders: instance Data.Default.Class.Default (Hasql.Encoders.Value Data.UUID.Types.Internal.UUID)
- Hasql.Encoders: instance Data.Default.Class.Default (Hasql.Encoders.Value GHC.Int.Int16)
- Hasql.Encoders: instance Data.Default.Class.Default (Hasql.Encoders.Value GHC.Int.Int32)
- Hasql.Encoders: instance Data.Default.Class.Default (Hasql.Encoders.Value GHC.Int.Int64)
- Hasql.Encoders: instance Data.Default.Class.Default (Hasql.Encoders.Value GHC.Types.Bool)
- Hasql.Encoders: instance Data.Default.Class.Default (Hasql.Encoders.Value GHC.Types.Char)
- Hasql.Encoders: instance Data.Default.Class.Default (Hasql.Encoders.Value GHC.Types.Double)
- Hasql.Encoders: instance Data.Default.Class.Default (Hasql.Encoders.Value GHC.Types.Float)
- Hasql.Encoders: instance Data.Default.Class.Default (Hasql.Encoders.Value a) => Data.Default.Class.Default (Hasql.Encoders.Params (Data.Functor.Identity.Identity a))
- Hasql.Encoders: instance Data.Functor.Contravariant.Contravariant Hasql.Encoders.Params
- Hasql.Encoders: instance Data.Functor.Contravariant.Contravariant Hasql.Encoders.Value
- Hasql.Encoders: instance Data.Functor.Contravariant.Divisible.Decidable Hasql.Encoders.Params
- Hasql.Encoders: instance Data.Functor.Contravariant.Divisible.Divisible Hasql.Encoders.Params
- Hasql.Encoders: instance GHC.Base.Monoid (Hasql.Encoders.Params a)
- Hasql.Encoders: instance GHC.Base.Semigroup (Hasql.Encoders.Params a)
- Hasql.Encoders: nullableElement :: Value a -> Array (Maybe a)
- Hasql.Encoders: nullableParam :: Value a -> Params (Maybe a)
- Hasql.Encoders: unit :: Params ()
+ Hasql.Decoders: data NullableOrNot decoder a
+ Hasql.Decoders: listArray :: NullableOrNot Value element -> Value [element]
+ Hasql.Decoders: noResult :: Result ()
+ Hasql.Decoders: nonNullable :: decoder a -> NullableOrNot decoder a
+ Hasql.Decoders: nullable :: decoder a -> NullableOrNot decoder (Maybe a)
+ Hasql.Decoders: vectorArray :: Vector vector element => NullableOrNot Value element -> Value (vector element)
+ Hasql.Encoders: data NullableOrNot encoder a
+ Hasql.Encoders: foldableArray :: Foldable foldable => NullableOrNot Value element -> Value (foldable element)
+ Hasql.Encoders: noParams :: Params ()
+ Hasql.Encoders: nonNullable :: encoder a -> NullableOrNot encoder a
+ Hasql.Encoders: nullable :: encoder a -> NullableOrNot encoder (Maybe a)
- Hasql.Decoders: column :: Value a -> Row a
+ Hasql.Decoders: column :: NullableOrNot Value a -> Row a
- Hasql.Decoders: element :: Value a -> Array a
+ Hasql.Decoders: element :: NullableOrNot Value a -> Array a
- Hasql.Decoders: field :: Value a -> Composite a
+ Hasql.Decoders: field :: NullableOrNot Value a -> Composite a
- Hasql.Encoders: element :: Value a -> Array a
+ Hasql.Encoders: element :: NullableOrNot Value a -> Array a
- Hasql.Encoders: param :: Value a -> Params a
+ Hasql.Encoders: param :: NullableOrNot Value a -> Params a

Files

benchmarks/Main.hs view
@@ -79,7 +79,7 @@       D.singleRow row       where         row =-          tuple <$> D.column D.int8 <*> D.column D.int8+          tuple <$> (D.column . D.nonNullable) D.int8 <*> (D.column . D.nonNullable) D.int8           where             tuple !a !b =               (a, b)@@ -93,7 +93,7 @@     encoder =       conquer     rowDecoder =-      tuple <$> D.column D.int8 <*> D.column D.int8+      tuple <$> (D.column . D.nonNullable) D.int8 <*> (D.column . D.nonNullable) D.int8       where         tuple !a !b =           (a, b)
hasql.cabal view
@@ -1,50 +1,29 @@-name:-  hasql-version:-  1.3.0.6-category:-  Hasql, Database, PostgreSQL-synopsis:-  An efficient PostgreSQL driver and a flexible mapping API+name: hasql+version: 1.4+category: Hasql, Database, PostgreSQL+synopsis: An efficient PostgreSQL driver with a flexible mapping API description:   This package is the root of the \"hasql\" ecosystem.   .   The API comes free from all kinds of exceptions. All error-reporting is explicit and is presented using the 'Either' type.-homepage:-  https://github.com/nikita-volkov/hasql -bug-reports:-  https://github.com/nikita-volkov/hasql/issues -author:-  Nikita Volkov <nikita.y.volkov@mail.ru>-maintainer:-  Nikita Volkov <nikita.y.volkov@mail.ru>-copyright:-  (c) 2014, Nikita Volkov-license:-  MIT-license-file:-  LICENSE-build-type:-  Simple-cabal-version:-  >=1.10-+homepage: https://github.com/nikita-volkov/hasql+bug-reports: https://github.com/nikita-volkov/hasql/issues+author: Nikita Volkov <nikita.y.volkov@mail.ru>+maintainer: Nikita Volkov <nikita.y.volkov@mail.ru>+copyright: (c) 2014, Nikita Volkov+license: MIT+license-file: LICENSE+build-type: Simple+cabal-version: >=1.10  source-repository head-  type:-    git-  location:-    git://github.com/nikita-volkov/hasql.git-+  type: git+  location: git://github.com/nikita-volkov/hasql.git  library-  hs-source-dirs:-    library-  ghc-options:-  default-extensions:-    Arrows, BangPatterns, ConstraintKinds, DataKinds, DefaultSignatures, DeriveDataTypeable, DeriveFoldable, DeriveFunctor, DeriveGeneric, DeriveTraversable, EmptyDataDecls, FlexibleContexts, FlexibleInstances, FunctionalDependencies, GADTs, GeneralizedNewtypeDeriving, LambdaCase, LiberalTypeSynonyms, MagicHash, MultiParamTypeClasses, MultiWayIf, NoImplicitPrelude, NoMonomorphismRestriction, OverloadedStrings, PatternGuards, ParallelListComp, QuasiQuotes, RankNTypes, RecordWildCards, ScopedTypeVariables, StandaloneDeriving, TemplateHaskell, TupleSections, TypeFamilies, TypeOperators, UnboxedTuples-  default-language:-    Haskell2010+  hs-source-dirs: library+  default-extensions: Arrows, BangPatterns, ConstraintKinds, DataKinds, DefaultSignatures, DeriveDataTypeable, DeriveFoldable, DeriveFunctor, DeriveGeneric, DeriveTraversable, EmptyDataDecls, FlexibleContexts, FlexibleInstances, FunctionalDependencies, GADTs, GeneralizedNewtypeDeriving, LambdaCase, LiberalTypeSynonyms, MagicHash, MultiParamTypeClasses, MultiWayIf, NoImplicitPrelude, NoMonomorphismRestriction, OverloadedStrings, PatternGuards, ParallelListComp, QuasiQuotes, RankNTypes, RecordWildCards, ScopedTypeVariables, StandaloneDeriving, TemplateHaskell, TupleSections, TypeFamilies, TypeOperators, UnboxedTuples+  default-language: Haskell2010   exposed-modules:     Hasql.Decoders     Hasql.Encoders@@ -61,143 +40,106 @@     Hasql.Private.PreparedStatementRegistry     Hasql.Private.Settings     Hasql.Private.Commands+    Hasql.Private.Decoders     Hasql.Private.Decoders.Array     Hasql.Private.Decoders.Composite     Hasql.Private.Decoders.Value     Hasql.Private.Decoders.Row     Hasql.Private.Decoders.Result     Hasql.Private.Decoders.Results+    Hasql.Private.Encoders     Hasql.Private.Encoders.Array     Hasql.Private.Encoders.Value     Hasql.Private.Encoders.Params   build-depends:-    -- parsing:-    attoparsec >= 0.10 && < 0.14,-    -- database:-    postgresql-binary >= 0.12.1 && < 0.13,-    postgresql-libpq == 0.9.*,-    -- builders:-    bytestring-strict-builder >= 0.4.5.1 && < 0.5,-    -- data:-    dlist >= 0.7 && < 0.9,-    vector >= 0.10 && < 0.13,-    hashtables >= 1.1 && < 2,-    text >= 1 && < 2,-    text-builder >= 0.6.1.2 && < 0.7,-    bytestring >= 0.10 && < 0.11,-    hashable >= 1.2 && < 2,-    -- control:-    data-default-class >= 0.0.1 && < 0.2,-    profunctors >= 5.1 && < 6,-    contravariant-extras == 0.3.*,-    contravariant >= 1.3 && < 2,-    mtl >= 2 && < 3,-    transformers >= 0.3 && < 0.6,-    -- errors:-    loch-th == 0.2.*,-    placeholders == 0.1.*,-    -- general:-    base-prelude >= 0.1.19 && < 2,-    base >= 4.9 && < 5-+    attoparsec >=0.10 && <0.14,+    base >=4.9 && <5,+    base-prelude >=0.1.19 && <2,+    bytestring >=0.10 && <0.11,+    bytestring-strict-builder >=0.4.5.1 && <0.5,+    contravariant >=1.3 && <2,+    contravariant-extras ==0.3.*,+    dlist >=0.7 && <0.9,+    hashable >=1.2 && <2,+    hashtables >=1.1 && <2,+    loch-th ==0.2.*,+    mtl >=2 && <3,+    placeholders ==0.1.*,+    postgresql-binary >=0.12.1 && <0.13,+    postgresql-libpq ==0.9.*,+    profunctors >=5.1 && <6,+    text >=1 && <2,+    text-builder >=0.6.1.2 && <0.7,+    transformers >=0.3 && <0.6,+    vector >=0.10 && <0.13  test-suite tasty-  type:-    exitcode-stdio-1.0-  hs-source-dirs:-    tasty-  main-is:-    Main.hs+  type: exitcode-stdio-1.0+  hs-source-dirs: tasty+  main-is: Main.hs+  default-extensions: Arrows, BangPatterns, ConstraintKinds, DataKinds, DefaultSignatures, DeriveDataTypeable, DeriveFoldable, DeriveFunctor, DeriveGeneric, DeriveTraversable, EmptyDataDecls, FlexibleContexts, FlexibleInstances, FunctionalDependencies, GADTs, GeneralizedNewtypeDeriving, LambdaCase, LiberalTypeSynonyms, MagicHash, MultiParamTypeClasses, MultiWayIf, NoImplicitPrelude, NoMonomorphismRestriction, OverloadedStrings, PatternGuards, ParallelListComp, QuasiQuotes, RankNTypes, RecordWildCards, ScopedTypeVariables, StandaloneDeriving, TemplateHaskell, TupleSections, TypeFamilies, TypeOperators, UnboxedTuples+  default-language: Haskell2010   other-modules:     Main.DSL     Main.Connection     Main.Statements     Main.Prelude-  default-extensions:-    Arrows, BangPatterns, ConstraintKinds, DataKinds, DefaultSignatures, DeriveDataTypeable, DeriveFoldable, DeriveFunctor, DeriveGeneric, DeriveTraversable, EmptyDataDecls, FlexibleContexts, FlexibleInstances, FunctionalDependencies, GADTs, GeneralizedNewtypeDeriving, LambdaCase, LiberalTypeSynonyms, MagicHash, MultiParamTypeClasses, MultiWayIf, NoImplicitPrelude, NoMonomorphismRestriction, OverloadedStrings, PatternGuards, ParallelListComp, QuasiQuotes, RankNTypes, RecordWildCards, ScopedTypeVariables, StandaloneDeriving, TemplateHaskell, TupleSections, TypeFamilies, TypeOperators, UnboxedTuples-  default-language:-    Haskell2010   build-depends:-    -- database:     hasql,-    -- testing:-    tasty >= 0.12 && < 2,-    tasty-quickcheck >= 0.9 && < 0.11,-    tasty-hunit >= 0.9 && < 0.11,-    quickcheck-instances >= 0.3.11 && < 0.4,-    QuickCheck >= 2.8.1 && < 3,-    -- general:-    data-default-class,-    -- -    rerebase < 2-+    QuickCheck >=2.8.1 && <3,+    quickcheck-instances >=0.3.11 && <0.4,+    rerebase <2,+    tasty >=0.12 && <2,+    tasty-hunit >=0.9 && <0.11,+    tasty-quickcheck >=0.9 && <0.11  test-suite threads-test-  type:-    exitcode-stdio-1.0-  hs-source-dirs:-    threads-test-  main-is:-    Main.hs+  type: exitcode-stdio-1.0+  hs-source-dirs: threads-test+  main-is: Main.hs+  default-extensions:+    Arrows, BangPatterns, ConstraintKinds, DataKinds, DefaultSignatures, DeriveDataTypeable, DeriveFoldable, DeriveFunctor, DeriveGeneric, DeriveTraversable, EmptyDataDecls, FlexibleContexts, FlexibleInstances, FunctionalDependencies, GADTs, GeneralizedNewtypeDeriving, LambdaCase, LiberalTypeSynonyms, MagicHash, MultiParamTypeClasses, MultiWayIf, NoImplicitPrelude, NoMonomorphismRestriction, OverloadedStrings, PatternGuards, ParallelListComp, QuasiQuotes, RankNTypes, RecordWildCards, ScopedTypeVariables, StandaloneDeriving, TemplateHaskell, TupleSections, TypeFamilies, TypeOperators, UnboxedTuples+  default-language:+    Haskell2010   other-modules:     Main.Statements   ghc-options:     -O2     -threaded     "-with-rtsopts=-N"-  default-extensions:-    Arrows, BangPatterns, ConstraintKinds, DataKinds, DefaultSignatures, DeriveDataTypeable, DeriveFoldable, DeriveFunctor, DeriveGeneric, DeriveTraversable, EmptyDataDecls, FlexibleContexts, FlexibleInstances, FunctionalDependencies, GADTs, GeneralizedNewtypeDeriving, LambdaCase, LiberalTypeSynonyms, MagicHash, MultiParamTypeClasses, MultiWayIf, NoImplicitPrelude, NoMonomorphismRestriction, OverloadedStrings, PatternGuards, ParallelListComp, QuasiQuotes, RankNTypes, RecordWildCards, ScopedTypeVariables, StandaloneDeriving, TemplateHaskell, TupleSections, TypeFamilies, TypeOperators, UnboxedTuples-  default-language:-    Haskell2010   build-depends:-    -- database:     hasql,-    --      rebase - benchmark benchmarks-  type: -    exitcode-stdio-1.0-  hs-source-dirs:-    benchmarks-  main-is:-    Main.hs+  type: exitcode-stdio-1.0+  hs-source-dirs: benchmarks+  main-is: Main.hs+  default-extensions: Arrows, BangPatterns, ConstraintKinds, DataKinds, DefaultSignatures, DeriveDataTypeable, DeriveFoldable, DeriveFunctor, DeriveGeneric, DeriveTraversable, EmptyDataDecls, FlexibleContexts, FlexibleInstances, FunctionalDependencies, GADTs, GeneralizedNewtypeDeriving, LambdaCase, LiberalTypeSynonyms, MagicHash, MultiParamTypeClasses, MultiWayIf, NoImplicitPrelude, NoMonomorphismRestriction, OverloadedStrings, PatternGuards, ParallelListComp, QuasiQuotes, RankNTypes, RecordWildCards, ScopedTypeVariables, StandaloneDeriving, TemplateHaskell, TupleSections, TypeFamilies, TypeOperators, UnboxedTuples+  default-language: Haskell2010   ghc-options:     -O2     -threaded     "-with-rtsopts=-N"     -rtsopts     -funbox-strict-fields-  default-extensions:-    Arrows, BangPatterns, ConstraintKinds, DataKinds, DefaultSignatures, DeriveDataTypeable, DeriveFoldable, DeriveFunctor, DeriveGeneric, DeriveTraversable, EmptyDataDecls, FlexibleContexts, FlexibleInstances, FunctionalDependencies, GADTs, GeneralizedNewtypeDeriving, LambdaCase, LiberalTypeSynonyms, MagicHash, MultiParamTypeClasses, MultiWayIf, NoImplicitPrelude, NoMonomorphismRestriction, OverloadedStrings, PatternGuards, ParallelListComp, QuasiQuotes, RankNTypes, RecordWildCards, ScopedTypeVariables, StandaloneDeriving, TemplateHaskell, TupleSections, TypeFamilies, TypeOperators, UnboxedTuples-  default-language:-    Haskell2010   build-depends:+    bug ==1.*,+    criterion >=1.1 && <2,     hasql,-    -- benchmarking:-    criterion >= 1.1 && < 2,-    -- general:-    bug == 1.*,-    rerebase < 2-+    rerebase <2  test-suite profiling-  type:-    exitcode-stdio-1.0-  hs-source-dirs:-    profiling-  main-is:-    Main.hs+  type: exitcode-stdio-1.0+  hs-source-dirs: profiling+  main-is: Main.hs+  default-extensions: Arrows, BangPatterns, ConstraintKinds, DataKinds, DefaultSignatures, DeriveDataTypeable, DeriveFoldable, DeriveFunctor, DeriveGeneric, DeriveTraversable, EmptyDataDecls, FlexibleContexts, FlexibleInstances, FunctionalDependencies, GADTs, GeneralizedNewtypeDeriving, LambdaCase, LiberalTypeSynonyms, MagicHash, MultiParamTypeClasses, MultiWayIf, NoImplicitPrelude, NoMonomorphismRestriction, OverloadedStrings, PatternGuards, ParallelListComp, QuasiQuotes, RankNTypes, RecordWildCards, ScopedTypeVariables, StandaloneDeriving, TemplateHaskell, TupleSections, TypeFamilies, TypeOperators, UnboxedTuples+  default-language: Haskell2010   ghc-options:     -O2     -threaded     -rtsopts-  default-extensions:-    Arrows, BangPatterns, ConstraintKinds, DataKinds, DefaultSignatures, DeriveDataTypeable, DeriveFoldable, DeriveFunctor, DeriveGeneric, DeriveTraversable, EmptyDataDecls, FlexibleContexts, FlexibleInstances, FunctionalDependencies, GADTs, GeneralizedNewtypeDeriving, LambdaCase, LiberalTypeSynonyms, MagicHash, MultiParamTypeClasses, MultiWayIf, NoImplicitPrelude, NoMonomorphismRestriction, OverloadedStrings, PatternGuards, ParallelListComp, QuasiQuotes, RankNTypes, RecordWildCards, ScopedTypeVariables, StandaloneDeriving, TemplateHaskell, TupleSections, TypeFamilies, TypeOperators, UnboxedTuples-  default-language:-    Haskell2010   build-depends:+    bug ==1.*,     hasql,-    bug == 1.*,-    rerebase == 1.*+    rerebase ==1.*
library/Hasql/Decoders.hs view
@@ -1,10 +1,11 @@--- |--- A DSL for declaration of result decoders.+{-|+A DSL for declaration of result decoders.+-} module Hasql.Decoders (   -- * Result   Result,-  unit,+  noResult,   rowsAffected,   singleRow,   -- ** Specialized multi-row results@@ -17,7 +18,10 @@   -- * Row   Row,   column,-  nullableColumn,+  -- * Nullability+  NullableOrNot,+  nonNullable,+  nullable,   -- * Value   Value,   bool,@@ -43,6 +47,8 @@   jsonb,   jsonbBytes,   array,+  listArray,+  vectorArray,   composite,   hstore,   enum,@@ -51,663 +57,10 @@   Array,   dimension,   element,-  nullableElement,   -- * Composite   Composite,   field,-  nullableField, ) where -import Hasql.Private.Prelude hiding (maybe, bool)-import qualified Data.Vector as Vector-import qualified PostgreSQL.Binary.Decoding as A-import qualified PostgreSQL.Binary.Data as B-import qualified Hasql.Private.Decoders.Results as Results-import qualified Hasql.Private.Decoders.Result as Result-import qualified Hasql.Private.Decoders.Row as Row-import qualified Hasql.Private.Decoders.Value as Value-import qualified Hasql.Private.Decoders.Array as Array-import qualified Hasql.Private.Decoders.Composite as Composite-import qualified Hasql.Private.Prelude as Prelude---- * Result------------------------------ |--- Decoder of a query result.--- -newtype Result a =-  Result (Results.Results a)-  deriving (Functor)---- |--- Decode no value from the result.--- --- Useful for statements like @INSERT@ or @CREATE@.--- -{-# INLINABLE unit #-}-unit :: Result ()-unit =-  Result (Results.single Result.unit)---- |--- Get the amount of rows affected by such statements as--- @UPDATE@ or @DELETE@.--- -{-# INLINABLE rowsAffected #-}-rowsAffected :: Result Int64-rowsAffected =-  Result (Results.single Result.rowsAffected)---- |--- Exactly one row.--- Will raise the 'Hasql.Errors.UnexpectedAmountOfRows' error if it's any other.--- -{-# INLINABLE singleRow #-}-singleRow :: Row a -> Result a-singleRow (Row row) =-  Result (Results.single (Result.single row))---- ** Multi-row traversers------------------------------ |--- Foldl multiple rows.--- -{-# INLINABLE foldlRows #-}-foldlRows :: (a -> b -> a) -> a -> Row b -> Result a-foldlRows step init (Row row) =-  Result (Results.single (Result.foldl step init row))---- |--- Foldr multiple rows.--- -{-# INLINABLE foldrRows #-}-foldrRows :: (b -> a -> a) -> a -> Row b -> Result a-foldrRows step init (Row row) =-  Result (Results.single (Result.foldr step init row))---- ** Specialized multi-row results------------------------------ |--- Maybe one row or none.--- -{-# INLINABLE rowMaybe #-}-rowMaybe :: Row a -> Result (Maybe a)-rowMaybe (Row row) =-  Result (Results.single (Result.maybe row))---- |--- Zero or more rows packed into the vector.--- --- It's recommended to prefer this function to 'rowList',--- since it performs notably better.--- -{-# INLINABLE rowVector #-}-rowVector :: Row a -> Result (Vector a)-rowVector (Row row) =-  Result (Results.single (Result.vector row))---- |--- Zero or more rows packed into the list.--- -{-# INLINABLE rowList #-}-rowList :: Row a -> Result [a]-rowList =-  foldrRows strictCons []----- ** Instances------------------------------ | Maps to 'unit'.-instance Default (Result ()) where-  {-# INLINE def #-}-  def =-    unit---- | Maps to 'rowsAffected'.-instance Default (Result Int64) where-  {-# INLINE def #-}-  def =-    rowsAffected---- | Maps to @('rowMaybe' def)@.-instance Default (Row a) => Default (Result (Maybe a)) where-  {-# INLINE def #-}-  def =-    rowMaybe def---- | Maps to @('rowVector' def)@.-instance Default (Row a) => Default (Result (Vector a)) where-  {-# INLINE def #-}-  def =-    rowVector def---- | Maps to @('rowList' def)@.-instance Default (Row a) => Default (Result ([] a)) where-  {-# INLINE def #-}-  def =-    rowList def---- | Maps to @(fmap Identity ('singleRow' def)@.-instance Default (Row a) => Default (Result (Identity a)) where-  {-# INLINE def #-}-  def =-    fmap Identity (singleRow def)----- * Row------------------------------ |--- Decoder of an individual row,--- which gets composed of column value decoders.--- --- E.g.:--- --- >x :: Row (Maybe Int64, Text, TimeOfDay)--- >x =--- >  (,,) <$> nullableColumn int8 <*> column text <*> column time--- -newtype Row a =-  Row (Row.Row a)-  deriving (Functor, Applicative, Monad)---- |--- Lift an individual non-nullable value decoder to a composable row decoder.--- -{-# INLINABLE column #-}-column :: Value a -> Row a-column (Value imp) =-  Row (Row.nonNullValue imp)---- |--- Lift an individual nullable value decoder to a composable row decoder.--- -{-# INLINABLE nullableColumn #-}-nullableColumn :: Value a -> Row (Maybe a)-nullableColumn (Value imp) =-  Row (Row.value imp)----- ** Instances----------------------------instance Default (Value a) => Default (Row (Identity a)) where-  {-# INLINE def #-}-  def =-    fmap Identity (column def)--instance Default (Value a) => Default (Row (Maybe a)) where-  {-# INLINE def #-}-  def =-    nullableColumn def--instance (Default (Value a1), Default (Value a2)) => Default (Row (a1, a2)) where-  {-# INLINE def #-}-  def =-    ap (fmap (,) (column def)) (column def)----- * Value------------------------------ |--- Decoder of an individual value.--- -newtype Value a =-  Value (Value.Value a)-  deriving (Functor)----- ** Plain value decoders------------------------------ |--- Decoder of the @BOOL@ values.--- -{-# INLINABLE bool #-}-bool :: Value Bool-bool =-  Value (Value.decoder (const A.bool))---- |--- Decoder of the @INT2@ values.--- -{-# INLINABLE int2 #-}-int2 :: Value Int16-int2 =-  Value (Value.decoder (const A.int))---- |--- Decoder of the @INT4@ values.--- -{-# INLINABLE int4 #-}-int4 :: Value Int32-int4 =-  Value (Value.decoder (const A.int))---- |--- Decoder of the @INT8@ values.--- -{-# INLINABLE int8 #-}-int8 :: Value Int64-int8 =-  {-# SCC "int8" #-} -  Value (Value.decoder (const ({-# SCC "int8.int" #-} A.int)))---- |--- Decoder of the @FLOAT4@ values.--- -{-# INLINABLE float4 #-}-float4 :: Value Float-float4 =-  Value (Value.decoder (const A.float4))---- |--- Decoder of the @FLOAT8@ values.--- -{-# INLINABLE float8 #-}-float8 :: Value Double-float8 =-  Value (Value.decoder (const A.float8))---- |--- Decoder of the @NUMERIC@ values.--- -{-# INLINABLE numeric #-}-numeric :: Value B.Scientific-numeric =-  Value (Value.decoder (const A.numeric))---- |--- Decoder of the @CHAR@ values.--- Note that it supports UTF-8 values.-{-# INLINABLE char #-}-char :: Value Char-char =-  Value (Value.decoder (const A.char))---- |--- Decoder of the @TEXT@ values.--- -{-# INLINABLE text #-}-text :: Value Text-text =-  Value (Value.decoder (const A.text_strict))---- |--- Decoder of the @BYTEA@ values.--- -{-# INLINABLE bytea #-}-bytea :: Value ByteString-bytea =-  Value (Value.decoder (const A.bytea_strict))---- |--- Decoder of the @DATE@ values.--- -{-# INLINABLE date #-}-date :: Value B.Day-date =-  Value (Value.decoder (const A.date))---- |--- Decoder of the @TIMESTAMP@ values.--- -{-# INLINABLE timestamp #-}-timestamp :: Value B.LocalTime-timestamp =-  Value (Value.decoder (Prelude.bool A.timestamp_float A.timestamp_int))---- |--- Decoder of the @TIMESTAMPTZ@ values.--- --- /NOTICE/--- --- Postgres does not store the timezone information of @TIMESTAMPTZ@.--- Instead it stores a UTC value and performs silent conversions--- to the currently set timezone, when dealt with in the text format.--- However this library bypasses the silent conversions--- and communicates with Postgres using the UTC values directly.-{-# INLINABLE timestamptz #-}-timestamptz :: Value B.UTCTime-timestamptz =-  Value (Value.decoder (Prelude.bool A.timestamptz_float A.timestamptz_int))---- |--- Decoder of the @TIME@ values.--- -{-# INLINABLE time #-}-time :: Value B.TimeOfDay-time =-  Value (Value.decoder (Prelude.bool A.time_float A.time_int))---- |--- Decoder of the @TIMETZ@ values.--- --- Unlike in case of @TIMESTAMPTZ@, --- Postgres does store the timezone information for @TIMETZ@.--- However the Haskell's \"time\" library does not contain any composite type,--- that fits the task, so we use a pair of 'TimeOfDay' and 'TimeZone'--- to represent a value on the Haskell's side.-{-# INLINABLE timetz #-}-timetz :: Value (B.TimeOfDay, B.TimeZone)-timetz =-  Value (Value.decoder (Prelude.bool A.timetz_float A.timetz_int))---- |--- Decoder of the @INTERVAL@ values.--- -{-# INLINABLE interval #-}-interval :: Value B.DiffTime-interval =-  Value (Value.decoder (Prelude.bool A.interval_float A.interval_int))---- |--- Decoder of the @UUID@ values.--- -{-# INLINABLE uuid #-}-uuid :: Value B.UUID-uuid =-  Value (Value.decoder (const A.uuid))---- |--- Decoder of the @INET@ values.----{-# INLINABLE inet #-}-inet :: Value (B.NetAddr B.IP)-inet =-  Value (Value.decoder (const A.inet))---- |--- Decoder of the @JSON@ values into a JSON AST.--- -{-# INLINABLE json #-}-json :: Value B.Value-json =-  Value (Value.decoder (const A.json_ast))---- |--- Decoder of the @JSON@ values into a raw JSON 'ByteString'.--- -{-# INLINABLE jsonBytes #-}-jsonBytes :: (ByteString -> Either Text a) -> Value a-jsonBytes fn =-  Value (Value.decoder (const (A.json_bytes fn)))---- |--- Decoder of the @JSONB@ values into a JSON AST.--- -{-# INLINABLE jsonb #-}-jsonb :: Value B.Value-jsonb =-  Value (Value.decoder (const A.jsonb_ast))---- |--- Decoder of the @JSONB@ values into a raw JSON 'ByteString'.--- -{-# INLINABLE jsonbBytes #-}-jsonbBytes :: (ByteString -> Either Text a) -> Value a-jsonbBytes fn =-  Value (Value.decoder (const (A.jsonb_bytes fn)))---- |--- Lifts a custom value decoder function to a 'Value' decoder.--- -{-# INLINABLE custom #-}-custom :: (Bool -> ByteString -> Either Text a) -> Value a-custom fn =-  Value (Value.decoderFn fn)----- ** Composite value decoders------------------------------ |--- Lifts the 'Array' decoder to the 'Value' decoder.--- -{-# INLINABLE array #-}-array :: Array a -> Value a-array (Array imp) =-  Value (Value.decoder (Array.run imp))---- |--- Lifts the 'Composite' decoder to the 'Value' decoder.--- -{-# INLINABLE composite #-}-composite :: Composite a -> Value a-composite (Composite imp) =-  Value (Value.decoder (Composite.run imp))---- |--- A generic decoder of @HSTORE@ values.--- --- Here's how you can use it to construct a specific value:--- --- @--- x :: Value [(Text, Maybe Text)]--- x =---   hstore 'replicateM'--- @--- -{-# INLINABLE hstore #-}-hstore :: (forall m. Monad m => Int -> m (Text, Maybe Text) -> m a) -> Value a-hstore replicateM =-  Value (Value.decoder (const (A.hstore replicateM A.text_strict A.text_strict)))---- |--- Given a partial mapping from text to value,--- produces a decoder of that value.-enum :: (Text -> Maybe a) -> Value a-enum mapping =-  Value (Value.decoder (const (A.enum mapping)))----- ** Instances------------------------------ |--- Maps to 'bool'.-instance Default (Value Bool) where-  {-# INLINE def #-}-  def =-    bool---- |--- Maps to 'int2'.-instance Default (Value Int16) where-  {-# INLINE def #-}-  def =-    int2---- |--- Maps to 'int4'.-instance Default (Value Int32) where-  {-# INLINE def #-}-  def =-    int4---- |--- Maps to 'int8'.-instance Default (Value Int64) where-  {-# INLINE def #-}-  def =-    int8---- |--- Maps to 'float4'.-instance Default (Value Float) where-  {-# INLINE def #-}-  def =-    float4---- |--- Maps to 'float8'.-instance Default (Value Double) where-  {-# INLINE def #-}-  def =-    float8---- |--- Maps to 'numeric'.-instance Default (Value B.Scientific) where-  {-# INLINE def #-}-  def =-    numeric---- |--- Maps to 'char'.-instance Default (Value Char) where-  {-# INLINE def #-}-  def =-    char---- |--- Maps to 'text'.-instance Default (Value Text) where-  {-# INLINE def #-}-  def =-    text---- |--- Maps to 'bytea'.-instance Default (Value ByteString) where-  {-# INLINE def #-}-  def =-    bytea---- |--- Maps to 'date'.-instance Default (Value B.Day) where-  {-# INLINE def #-}-  def =-    date---- |--- Maps to 'timestamp'.-instance Default (Value B.LocalTime) where-  {-# INLINE def #-}-  def =-    timestamp---- |--- Maps to 'timestamptz'.-instance Default (Value B.UTCTime) where-  {-# INLINE def #-}-  def =-    timestamptz---- |--- Maps to 'time'.-instance Default (Value B.TimeOfDay) where-  {-# INLINE def #-}-  def =-    time---- |--- Maps to 'timetz'.-instance Default (Value (B.TimeOfDay, B.TimeZone)) where-  {-# INLINE def #-}-  def =-    timetz---- |--- Maps to 'interval'.-instance Default (Value B.DiffTime) where-  {-# INLINE def #-}-  def =-    interval---- |--- Maps to 'uuid'.-instance Default (Value B.UUID) where-  {-# INLINE def #-}-  def =-    uuid---- |--- Maps to 'json'.-instance Default (Value B.Value) where-  {-# INLINE def #-}-  def =-    json----- * Array decoders------------------------------ |--- A generic array decoder.--- --- Here's how you can use it to produce a specific array value decoder:--- --- @--- x :: Value [[Text]]--- x =---   array (dimension 'replicateM' (dimension 'replicateM' (element text)))--- @--- -newtype Array a =-  Array (Array.Array a)-  deriving (Functor)---- |--- A function for parsing a dimension of an array.--- Provides support for multi-dimensional arrays.--- --- Accepts:--- --- * An implementation of the @replicateM@ function--- (@Control.Monad.'Control.Monad.replicateM'@, @Data.Vector.'Data.Vector.replicateM'@),--- which determines the output value.--- --- * A decoder of its components, which can be either another 'dimension',--- 'element' or 'nullableElement'.--- -{-# INLINABLE dimension #-}-dimension :: (forall m. Monad m => Int -> m a -> m b) -> Array a -> Array b-dimension replicateM (Array imp) =-  Array (Array.dimension replicateM imp)---- |--- Lift a 'Value' decoder into an 'Array' decoder for parsing of non-nullable leaf values.-{-# INLINABLE element #-}-element :: Value a -> Array a-element (Value imp) =-  Array (Array.nonNullValue (Value.run imp))---- |--- Lift a 'Value' decoder into an 'Array' decoder for parsing of nullable leaf values.-{-# INLINABLE nullableElement #-}-nullableElement :: Value a -> Array (Maybe a)-nullableElement (Value imp) =-  Array (Array.value (Value.run imp))----- * Composite decoders------------------------------ |--- Composable decoder of composite values (rows, records).-newtype Composite a =-  Composite (Composite.Composite a)-  deriving (Functor, Applicative, Monad)---- |--- Lift a 'Value' decoder into a 'Composite' decoder for parsing of non-nullable leaf values.-{-# INLINABLE field #-}-field :: Value a -> Composite a-field (Value imp) =-  Composite (Composite.nonNullValue (Value.run imp))---- |--- Lift a 'Value' decoder into a 'Composite' decoder for parsing of nullable leaf values.-{-# INLINABLE nullableField #-}-nullableField :: Value a -> Composite (Maybe a)-nullableField (Value imp) =-  Composite (Composite.value (Value.run imp))-+import Hasql.Private.Decoders
library/Hasql/Encoders.hs view
@@ -1,12 +1,19 @@--- |--- A DSL for declaration of query parameter encoders.+{-|+A DSL for declaration of statement parameter encoders.++For compactness of names all the types defined here imply being an encoder.+E.g., the `Array` type is an __encoder__ of arrays, not the data-structure itself.+-} module Hasql.Encoders (-  -- * Params+  -- * Parameters product   Params,-  unit,+  noParams,   param,-  nullableParam,+  -- * Nullability+  NullableOrNot,+  nonNullable,+  nullable,   -- * Value   Value,   bool,@@ -31,529 +38,15 @@   jsonBytes,   jsonb,   jsonbBytes,-  array,   enum,   unknown,+  array,+  foldableArray,   -- * Array   Array,   element,-  nullableElement,   dimension,-  -- ** Insert Many-  -- $insertMany ) where -import Hasql.Private.Prelude hiding (bool)-import qualified PostgreSQL.Binary.Encoding as A-import qualified PostgreSQL.Binary.Data as B-import qualified Text.Builder as C-import qualified Hasql.Private.Encoders.Params as Params-import qualified Hasql.Private.Encoders.Value as Value-import qualified Hasql.Private.Encoders.Array as Array-import qualified Hasql.Private.PTI as PTI-import qualified Hasql.Private.Prelude as Prelude---- * Parameters Product Encoder------------------------------ |--- Encoder of some representation of the parameters product.--- --- Has instances of 'Contravariant', 'Divisible' and 'Monoid',--- which you can use to compose multiple parameters together.--- E.g.,--- --- @--- someParamsEncoder :: 'Params' (Int64, Maybe Text)--- someParamsEncoder =---   'contramap' 'fst' ('param' 'int8') '<>'---   'contramap' 'snd' ('nullableParam' 'text')--- @--- --- As a general solution for tuples of any arity, instead of 'fst' and 'snd',--- consider the functions of the @contrazip@ family--- from the \"contravariant-extras\" package.--- E.g., here's how you can achieve the same as the above:--- --- @--- someParamsEncoder :: 'Params' (Int64, Maybe Text)--- someParamsEncoder =---   'contrazip2' ('param' 'int8') ('nullableParam' 'text')--- @--- --- Here's how you can implement encoders for custom composite types:--- --- @--- data Person =---   Person { name :: Text, gender :: Gender, age :: Int }--- --- data Gender =---   Male | Female--- --- personParams :: 'Params' Person--- personParams =---   'contramap' name ('param' 'text') '<>'---   'contramap' gender ('param' genderValue) '<>'---   'contramap' (fromIntegral . age) ('param' 'int8')--- --- genderValue :: 'Value' Gender--- genderValue =---   'contramap' genderText 'text'---   where---     genderText gender =---       case gender of---         Male -> "male"---         Female -> "female"--- @--- -newtype Params a =-  Params (Params.Params a)-  deriving (Contravariant, Divisible, Decidable, Monoid, Semigroup)---- |--- Encode no parameters.--- -{-# INLINABLE unit #-}-unit :: Params ()-unit =-  Params mempty---- |--- Lift an individual value encoder to a parameters encoder.--- -{-# INLINABLE param #-}-param :: Value a -> Params a-param (Value x) =-  Params (Params.value x)---- |--- Lift an individual nullable value encoder to a parameters encoder.--- -{-# INLINABLE nullableParam #-}-nullableParam :: Value a -> Params (Maybe a)-nullableParam (Value x) =-  Params (Params.nullableValue x)----- ** Instances------------------------------ |--- Maps to 'unit'.-instance Default (Params ()) where-  {-# INLINE def #-}-  def =-    unit--instance Default (Value a) => Default (Params (Identity a)) where-  {-# INLINE def #-}-  def =-    contramap runIdentity (param def)--instance (Default (Value a1), Default (Value a2)) => Default (Params (a1, a2)) where-  {-# INLINE def #-}-  def =-    contrazip2 (param def) (param def)--instance (Default (Value a1), Default (Value a2), Default (Value a3)) => Default (Params (a1, a2, a3)) where-  {-# INLINE def #-}-  def =-    contrazip3 (param def) (param def) (param def)--instance (Default (Value a1), Default (Value a2), Default (Value a3), Default (Value a4)) => Default (Params (a1, a2, a3, a4)) where-  {-# INLINE def #-}-  def =-    contrazip4 (param def) (param def) (param def) (param def)--instance (Default (Value a1), Default (Value a2), Default (Value a3), Default (Value a4), Default (Value a5)) => Default (Params (a1, a2, a3, a4, a5)) where-  {-# INLINE def #-}-  def =-    contrazip5 (param def) (param def) (param def) (param def) (param def)----- * Value Encoder------------------------------ |--- An individual value encoder.--- Will be mapped to a single placeholder in the query.--- -newtype Value a =-  Value (Value.Value a)-  deriving (Contravariant)---- |--- Encoder of @BOOL@ values.-{-# INLINABLE bool #-}-bool :: Value Bool-bool =-  Value (Value.unsafePTIWithShow PTI.bool (const A.bool))---- |--- Encoder of @INT2@ values.-{-# INLINABLE int2 #-}-int2 :: Value Int16-int2 =-  Value (Value.unsafePTIWithShow PTI.int2 (const A.int2_int16))---- |--- Encoder of @INT4@ values.-{-# INLINABLE int4 #-}-int4 :: Value Int32-int4 =-  Value (Value.unsafePTIWithShow PTI.int4 (const A.int4_int32))---- |--- Encoder of @INT8@ values.-{-# INLINABLE int8 #-}-int8 :: Value Int64-int8 =-  Value (Value.unsafePTIWithShow PTI.int8 (const A.int8_int64))---- |--- Encoder of @FLOAT4@ values.-{-# INLINABLE float4 #-}-float4 :: Value Float-float4 =-  Value (Value.unsafePTIWithShow PTI.float4 (const A.float4))---- |--- Encoder of @FLOAT8@ values.-{-# INLINABLE float8 #-}-float8 :: Value Double-float8 =-  Value (Value.unsafePTIWithShow PTI.float8 (const A.float8))---- |--- Encoder of @NUMERIC@ values.-{-# INLINABLE numeric #-}-numeric :: Value B.Scientific-numeric =-  Value (Value.unsafePTIWithShow PTI.numeric (const A.numeric))---- |--- Encoder of @CHAR@ values.--- Note that it supports UTF-8 values and--- identifies itself under the @TEXT@ OID because of that.-{-# INLINABLE char #-}-char :: Value Char-char =-  Value (Value.unsafePTIWithShow PTI.text (const A.char_utf8))---- |--- Encoder of @TEXT@ values.-{-# INLINABLE text #-}-text :: Value Text-text =-  Value (Value.unsafePTIWithShow PTI.text (const A.text_strict))---- |--- Encoder of @BYTEA@ values.-{-# INLINABLE bytea #-}-bytea :: Value ByteString-bytea =-  Value (Value.unsafePTIWithShow PTI.bytea (const A.bytea_strict))---- |--- Encoder of @DATE@ values.-{-# INLINABLE date #-}-date :: Value B.Day-date =-  Value (Value.unsafePTIWithShow PTI.date (const A.date))---- |--- Encoder of @TIMESTAMP@ values.-{-# INLINABLE timestamp #-}-timestamp :: Value B.LocalTime-timestamp =-  Value (Value.unsafePTIWithShow PTI.timestamp (Prelude.bool A.timestamp_float A.timestamp_int))---- |--- Encoder of @TIMESTAMPTZ@ values.-{-# INLINABLE timestamptz #-}-timestamptz :: Value B.UTCTime-timestamptz =-  Value (Value.unsafePTIWithShow PTI.timestamptz (Prelude.bool A.timestamptz_float A.timestamptz_int))---- |--- Encoder of @TIME@ values.-{-# INLINABLE time #-}-time :: Value B.TimeOfDay-time =-  Value (Value.unsafePTIWithShow PTI.time (Prelude.bool A.time_float A.time_int))---- |--- Encoder of @TIMETZ@ values.-{-# INLINABLE timetz #-}-timetz :: Value (B.TimeOfDay, B.TimeZone)-timetz =-  Value (Value.unsafePTIWithShow PTI.timetz (Prelude.bool A.timetz_float A.timetz_int))---- |--- Encoder of @INTERVAL@ values.-{-# INLINABLE interval #-}-interval :: Value B.DiffTime-interval =-  Value (Value.unsafePTIWithShow PTI.interval (Prelude.bool A.interval_float A.interval_int))---- |--- Encoder of @UUID@ values.-{-# INLINABLE uuid #-}-uuid :: Value B.UUID-uuid =-  Value (Value.unsafePTIWithShow PTI.uuid (const A.uuid))---- |--- Encoder of @INET@ values.-{-# INLINABLE inet #-}-inet :: Value (B.NetAddr B.IP)-inet =-  Value (Value.unsafePTIWithShow PTI.inet (const A.inet))---- |--- Encoder of @JSON@ values from JSON AST.-{-# INLINABLE json #-}-json :: Value B.Value-json =-  Value (Value.unsafePTIWithShow PTI.json (const A.json_ast))---- |--- Encoder of @JSON@ values from raw JSON.-{-# INLINABLE jsonBytes #-}-jsonBytes :: Value ByteString-jsonBytes =-  Value (Value.unsafePTIWithShow PTI.json (const A.json_bytes))---- |--- Encoder of @JSONB@ values from JSON AST.-{-# INLINABLE jsonb #-}-jsonb :: Value B.Value-jsonb =-  Value (Value.unsafePTIWithShow PTI.jsonb (const A.jsonb_ast))---- |--- Encoder of @JSONB@ values from raw JSON.-{-# INLINABLE jsonbBytes #-}-jsonbBytes :: Value ByteString-jsonbBytes =-  Value (Value.unsafePTIWithShow PTI.jsonb (const A.jsonb_bytes))---- |--- Unlifts the 'Array' encoder to the plain 'Value' encoder.-{-# INLINABLE array #-}-array :: Array a -> Value a-array (Array (Array.Array valueOID arrayOID arrayEncoder renderer)) =-  let-    encoder env input =-      A.array (PTI.oidWord32 valueOID) (arrayEncoder env input)-    in Value (Value.Value arrayOID arrayOID encoder renderer)---- |--- Given a function,--- which maps the value into the textual enum label from the DB side,--- produces a encoder of that value.-{-# INLINABLE enum #-}-enum :: (a -> Text) -> Value a-enum mapping =-  Value (Value.unsafePTI PTI.text (const (A.text_strict . mapping)) (C.text . mapping))---- |--- Identifies the value with the PostgreSQL's \"unknown\" type,--- thus leaving it up to Postgres to infer the actual type of the value.--- --- The value transimitted is any value encoded in the Postgres' Text data format.--- For reference, see the--- <https://www.postgresql.org/docs/10/static/protocol-overview.html#protocol-format-codes Formats and Format Codes>--- section of the Postgres' documentation.-{-# INLINABLE unknown #-}-unknown :: Value ByteString-unknown =-  Value (Value.unsafePTIWithShow PTI.unknown (const A.bytea_strict))----- ** Instances------------------------------ | Maps to 'bool'.-instance Default (Value Bool) where-  {-# INLINE def #-}-  def =-    bool---- | Maps to 'int2'.-instance Default (Value Int16) where-  {-# INLINE def #-}-  def =-    int2---- | Maps to 'int4'.-instance Default (Value Int32) where-  {-# INLINE def #-}-  def =-    int4---- | Maps to 'int8'.-instance Default (Value Int64) where-  {-# INLINE def #-}-  def =-    int8---- | Maps to 'float4'.-instance Default (Value Float) where-  {-# INLINE def #-}-  def =-    float4---- | Maps to 'float8'.-instance Default (Value Double) where-  {-# INLINE def #-}-  def =-    float8---- | Maps to 'numeric'.-instance Default (Value B.Scientific) where-  {-# INLINE def #-}-  def =-    numeric---- | Maps to 'char'.-instance Default (Value Char) where-  {-# INLINE def #-}-  def =-    char---- | Maps to 'text'.-instance Default (Value Text) where-  {-# INLINE def #-}-  def =-    text---- | Maps to 'bytea'.-instance Default (Value ByteString) where-  {-# INLINE def #-}-  def =-    bytea---- | Maps to 'date'.-instance Default (Value B.Day) where-  {-# INLINE def #-}-  def =-    date---- | Maps to 'timestamp'.-instance Default (Value B.LocalTime) where-  {-# INLINE def #-}-  def =-    timestamp---- | Maps to 'timestamptz'.-instance Default (Value B.UTCTime) where-  {-# INLINE def #-}-  def =-    timestamptz---- | Maps to 'time'.-instance Default (Value B.TimeOfDay) where-  {-# INLINE def #-}-  def =-    time---- | Maps to 'timetz'.-instance Default (Value (B.TimeOfDay, B.TimeZone)) where-  {-# INLINE def #-}-  def =-    timetz---- | Maps to 'interval'.-instance Default (Value B.DiffTime) where-  {-# INLINE def #-}-  def =-    interval---- | Maps to 'uuid'.-instance Default (Value B.UUID) where-  {-# INLINE def #-}-  def =-    uuid---- | Maps to 'json'.-instance Default (Value B.Value) where-  {-# INLINE def #-}-  def =-    json----- * Array------------------------------ |--- A generic array encoder.--- --- Here's an example of its usage:--- --- >x :: Value [[Int64]]--- >x =--- >  array (dimension foldl' (dimension foldl' (element int8)))--- --- Please note that the PostgreSQL __IN__ keyword does not "accept" an array, but rather a syntactical list of--- values, thus this encoder is not suited for that. Use a **field** = ANY($1) query instead.----newtype Array a =-  Array (Array.Array a)---- |--- Lifts the 'Value' encoder into the 'Array' encoder of a non-nullable value.-{-# INLINABLE element #-}-element :: Value a -> Array a-element (Value (Value.Value elementOID arrayOID encoder renderer)) =-  Array (Array.value elementOID arrayOID encoder renderer)---- |--- Lifts the 'Value' encoder into the 'Array' encoder of a nullable value.-{-# INLINABLE nullableElement #-}-nullableElement :: Value a -> Array (Maybe a)-nullableElement (Value (Value.Value elementOID arrayOID encoder renderer)) =-  Array (Array.nullableValue elementOID arrayOID encoder renderer)---- |--- An encoder of an array dimension,--- which thus provides support for multidimensional arrays.--- --- Accepts:--- --- * An implementation of the left-fold operation,--- such as @Data.Foldable.'foldl''@,--- which determines the input value.--- --- * A component encoder, which can be either another 'dimension',--- 'element' or 'nullableElement'.--- -{-# INLINABLE dimension #-}-dimension :: (forall a. (a -> b -> a) -> a -> c -> a) -> Array b -> Array c-dimension foldl (Array imp) =-  Array (Array.dimension foldl imp)---- $insertMany--- It is not currently possible to pass in an array of encodable values--- to use in an 'insert many' statement using Hasql. Instead, PostgreSQL's---  (9.4 or later) `unnest` function can be used to in an analogous way--- to haskell's `zip` function by passing in multiple arrays of values--- to be zipped into the rows we want to insert:------ @---   insertMultipleLocations :: Statement (Vector (UUID, Double, Double)) ()---   insertMultipleLocations =---     statement sql encoder decoder True---     where---       sql =---         "insert into location (id, x, y) select * from unnest ($1, $2, $3)"---       encoder =---         contramap Vector.unzip3 $---         contrazip3 (vector Encoders.uuid) (vector Encoders.float8) (vector Encoders.float8)---         where---           vector value =---             Encoders.param (Encoders.array (Encoders.dimension foldl' (Encoders.element value)))---       decoder =---         Decoders.unit--- @+import Hasql.Private.Encoders
+ library/Hasql/Private/Decoders.hs view
@@ -0,0 +1,459 @@+{-|+A DSL for declaration of result decoders.+-}+module Hasql.Private.Decoders+where++import Hasql.Private.Prelude hiding (maybe, bool)+import qualified Data.Vector as Vector+import qualified PostgreSQL.Binary.Decoding as A+import qualified PostgreSQL.Binary.Data as B+import qualified Hasql.Private.Decoders.Results as Results+import qualified Hasql.Private.Decoders.Result as Result+import qualified Hasql.Private.Decoders.Row as Row+import qualified Hasql.Private.Decoders.Value as Value+import qualified Hasql.Private.Decoders.Array as Array+import qualified Hasql.Private.Decoders.Composite as Composite+import qualified Hasql.Private.Prelude as Prelude+import qualified Data.Vector.Generic as GenericVector++-- * Result+-------------------------++{-|+Decoder of a query result.+-}+newtype Result a = Result (Results.Results a) deriving (Functor)++{-|+Decode no value from the result.++Useful for statements like @INSERT@ or @CREATE@.+-}+{-# INLINABLE noResult #-}+noResult :: Result ()+noResult = Result (Results.single Result.noResult)++{-|+Get the amount of rows affected by such statements as+@UPDATE@ or @DELETE@.+-}+{-# INLINABLE rowsAffected #-}+rowsAffected :: Result Int64+rowsAffected = Result (Results.single Result.rowsAffected)++{-|+Exactly one row.+Will raise the 'Hasql.Errors.UnexpectedAmountOfRows' error if it's any other.+-}+{-# INLINABLE singleRow #-}+singleRow :: Row a -> Result a+singleRow (Row row) = Result (Results.single (Result.single row))++-- ** Multi-row traversers+-------------------------++{-|+Foldl multiple rows.+-}+{-# INLINABLE foldlRows #-}+foldlRows :: (a -> b -> a) -> a -> Row b -> Result a+foldlRows step init (Row row) = Result (Results.single (Result.foldl step init row))++{-|+Foldr multiple rows.+-}+{-# INLINABLE foldrRows #-}+foldrRows :: (b -> a -> a) -> a -> Row b -> Result a+foldrRows step init (Row row) = Result (Results.single (Result.foldr step init row))++-- ** Specialized multi-row results+-------------------------++{-|+Maybe one row or none.+-}+{-# INLINABLE rowMaybe #-}+rowMaybe :: Row a -> Result (Maybe a)+rowMaybe (Row row) = Result (Results.single (Result.maybe row))++{-|+Zero or more rows packed into the vector.++It's recommended to prefer this function to 'rowList',+since it performs notably better.+-}+{-# INLINABLE rowVector #-}+rowVector :: Row a -> Result (Vector a)+rowVector (Row row) = Result (Results.single (Result.vector row))++{-|+Zero or more rows packed into the list.+-}+{-# INLINABLE rowList #-}+rowList :: Row a -> Result [a]+rowList = foldrRows strictCons []+++-- * Row+-------------------------++{-|+Decoder of an individual row,+which gets composed of column value decoders.++E.g.:++@+x :: 'Row' (Maybe Int64, Text, TimeOfDay)+x = (,,) '<$>' ('column' . 'nullable') 'int8' '<*>' ('column' . 'nonNullable') 'text' '<*>' ('column' . 'nonNullable') 'time'+@+-}+newtype Row a = Row (Row.Row a)+  deriving (Functor, Applicative, Monad)++{-|+Lift an individual non-nullable value decoder to a composable row decoder.+-}+{-# INLINABLE column #-}+column :: NullableOrNot Value a -> Row a+column = \ case+  NonNullable (Value imp) -> Row (Row.nonNullValue imp)+  Nullable (Value imp) -> Row (Row.value imp)+++-- * Nullability+-------------------------++{-|+Extensional specification of nullability over a generic decoder.+-}+data NullableOrNot decoder a where+  NonNullable :: decoder a -> NullableOrNot decoder a+  Nullable :: decoder a -> NullableOrNot decoder (Maybe a)++{-|+Specify that a decoder produces a non-nullable value.+-}+nonNullable :: decoder a -> NullableOrNot decoder a+nonNullable = NonNullable++{-|+Specify that a decoder produces a nullable value.+-}+nullable :: decoder a -> NullableOrNot decoder (Maybe a)+nullable = Nullable+++-- * Value+-------------------------++{-|+Decoder of a value.+-}+newtype Value a = Value (Value.Value a)+  deriving (Functor)++{-|+Decoder of the @BOOL@ values.+-}+{-# INLINABLE bool #-}+bool :: Value Bool+bool = Value (Value.decoder (const A.bool))++{-|+Decoder of the @INT2@ values.+-}+{-# INLINABLE int2 #-}+int2 :: Value Int16+int2 = Value (Value.decoder (const A.int))++{-|+Decoder of the @INT4@ values.+-}+{-# INLINABLE int4 #-}+int4 :: Value Int32+int4 = Value (Value.decoder (const A.int))++{-|+Decoder of the @INT8@ values.+-}+{-# INLINABLE int8 #-}+int8 :: Value Int64+int8 = {-# SCC "int8" #-}+  Value (Value.decoder (const ({-# SCC "int8.int" #-} A.int)))++{-|+Decoder of the @FLOAT4@ values.+-}+{-# INLINABLE float4 #-}+float4 :: Value Float+float4 = Value (Value.decoder (const A.float4))++{-|+Decoder of the @FLOAT8@ values.+-}+{-# INLINABLE float8 #-}+float8 :: Value Double+float8 = Value (Value.decoder (const A.float8))++{-|+Decoder of the @NUMERIC@ values.+-}+{-# INLINABLE numeric #-}+numeric :: Value B.Scientific+numeric = Value (Value.decoder (const A.numeric))++{-|+Decoder of the @CHAR@ values.+Note that it supports Unicode values.+-}+{-# INLINABLE char #-}+char :: Value Char+char = Value (Value.decoder (const A.char))++{-|+Decoder of the @TEXT@ values.+-}+{-# INLINABLE text #-}+text :: Value Text+text = Value (Value.decoder (const A.text_strict))++{-|+Decoder of the @BYTEA@ values.+-}+{-# INLINABLE bytea #-}+bytea :: Value ByteString+bytea = Value (Value.decoder (const A.bytea_strict))++{-|+Decoder of the @DATE@ values.+-}+{-# INLINABLE date #-}+date :: Value B.Day+date = Value (Value.decoder (const A.date))++{-|+Decoder of the @TIMESTAMP@ values.+-}+{-# INLINABLE timestamp #-}+timestamp :: Value B.LocalTime+timestamp = Value (Value.decoder (Prelude.bool A.timestamp_float A.timestamp_int))++{-|+Decoder of the @TIMESTAMPTZ@ values.++/NOTICE/++Postgres does not store the timezone information of @TIMESTAMPTZ@.+Instead it stores a UTC value and performs silent conversions+to the currently set timezone, when dealt with in the text format.+However this library bypasses the silent conversions+and communicates with Postgres using the UTC values directly.+-}+{-# INLINABLE timestamptz #-}+timestamptz :: Value B.UTCTime+timestamptz = Value (Value.decoder (Prelude.bool A.timestamptz_float A.timestamptz_int))++{-|+Decoder of the @TIME@ values.+-}+{-# INLINABLE time #-}+time :: Value B.TimeOfDay+time = Value (Value.decoder (Prelude.bool A.time_float A.time_int))++{-|+Decoder of the @TIMETZ@ values.++Unlike in case of @TIMESTAMPTZ@, +Postgres does store the timezone information for @TIMETZ@.+However the Haskell's \"time\" library does not contain any composite type,+that fits the task, so we use a pair of 'TimeOfDay' and 'TimeZone'+to represent a value on the Haskell's side.+-}+{-# INLINABLE timetz #-}+timetz :: Value (B.TimeOfDay, B.TimeZone)+timetz = Value (Value.decoder (Prelude.bool A.timetz_float A.timetz_int))++{-|+Decoder of the @INTERVAL@ values.+-}+{-# INLINABLE interval #-}+interval :: Value B.DiffTime+interval = Value (Value.decoder (Prelude.bool A.interval_float A.interval_int))++{-|+Decoder of the @UUID@ values.+-}+{-# INLINABLE uuid #-}+uuid :: Value B.UUID+uuid = Value (Value.decoder (const A.uuid))++{-|+Decoder of the @INET@ values.+-}+{-# INLINABLE inet #-}+inet :: Value (B.NetAddr B.IP)+inet = Value (Value.decoder (const A.inet))++{-|+Decoder of the @JSON@ values into a JSON AST.+-}+{-# INLINABLE json #-}+json :: Value B.Value+json = Value (Value.decoder (const A.json_ast))++{-|+Decoder of the @JSON@ values into a raw JSON 'ByteString'.+-}+{-# INLINABLE jsonBytes #-}+jsonBytes :: (ByteString -> Either Text a) -> Value a+jsonBytes fn = Value (Value.decoder (const (A.json_bytes fn)))++{-|+Decoder of the @JSONB@ values into a JSON AST.+-}+{-# INLINABLE jsonb #-}+jsonb :: Value B.Value+jsonb = Value (Value.decoder (const A.jsonb_ast))++{-|+Decoder of the @JSONB@ values into a raw JSON 'ByteString'.+-}+{-# INLINABLE jsonbBytes #-}+jsonbBytes :: (ByteString -> Either Text a) -> Value a+jsonbBytes fn = Value (Value.decoder (const (A.jsonb_bytes fn)))++{-|+Lift a custom value decoder function to a 'Value' decoder.+-}+{-# INLINABLE custom #-}+custom :: (Bool -> ByteString -> Either Text a) -> Value a+custom fn = Value (Value.decoderFn fn)++{-|+A generic decoder of @HSTORE@ values.++Here's how you can use it to construct a specific value:++@+x :: Value [(Text, Maybe Text)]+x = hstore 'replicateM'+@+-}+{-# INLINABLE hstore #-}+hstore :: (forall m. Monad m => Int -> m (Text, Maybe Text) -> m a) -> Value a+hstore replicateM = Value (Value.decoder (const (A.hstore replicateM A.text_strict A.text_strict)))++{-|+Given a partial mapping from text to value,+produces a decoder of that value.+-}+enum :: (Text -> Maybe a) -> Value a+enum mapping = Value (Value.decoder (const (A.enum mapping)))++{-|+Lift an 'Array' decoder to a 'Value' decoder.+-}+{-# INLINABLE array #-}+array :: Array a -> Value a+array (Array imp) = Value (Value.decoder (Array.run imp))++{-|+Lift a value decoder of element into a unidimensional array decoder producing a list.++This function is merely a shortcut to the following expression:++@+('array' . 'dimension' Control.Monad.'replicateM' . 'element')+@++Please notice that in case of multidimensional arrays nesting 'listArray' decoder+won't work. You have to explicitly construct the array decoder using 'array'.+-}+{-# INLINE listArray #-}+listArray :: NullableOrNot Value element -> Value [element]+listArray = array . dimension replicateM . element++{-|+Lift a value decoder of element into a unidimensional array decoder producing a generic vector.++This function is merely a shortcut to the following expression:++@+('array' . 'dimension' Data.Vector.Generic.'GenericVector.replicateM' . 'element')+@++Please notice that in case of multidimensional arrays nesting 'vectorArray' decoder+won't work. You have to explicitly construct the array decoder using 'array'.+-}+{-# INLINE vectorArray #-}+vectorArray :: GenericVector.Vector vector element => NullableOrNot Value element -> Value (vector element)+vectorArray = array . dimension GenericVector.replicateM . element++{-|+Lift a 'Composite' decoder to a 'Value' decoder.+-}+{-# INLINABLE composite #-}+composite :: Composite a -> Value a+composite (Composite imp) = Value (Value.decoder (Composite.run imp))+++-- * Array decoders+-------------------------++{-|+A generic array decoder.++Here's how you can use it to produce a specific array value decoder:++@+x :: 'Value' [[Text]]+x = 'array' ('dimension' 'replicateM' ('dimension' 'replicateM' ('element' ('nonNullable' 'text'))))+@+-}+newtype Array a = Array (Array.Array a)+  deriving (Functor)++{-|+A function for parsing a dimension of an array.+Provides support for multi-dimensional arrays.++Accepts:++* An implementation of the @replicateM@ function+(@Control.Monad.'Control.Monad.replicateM'@, @Data.Vector.'Data.Vector.replicateM'@),+which determines the output value.++* A decoder of its components, which can be either another 'dimension' or 'element'.+-}+{-# INLINABLE dimension #-}+dimension :: (forall m. Monad m => Int -> m a -> m b) -> Array a -> Array b+dimension replicateM (Array imp) = Array (Array.dimension replicateM imp)++{-|+Lift a 'Value' decoder into an 'Array' decoder for parsing of leaf values.+-}+{-# INLINABLE element #-}+element :: NullableOrNot Value a -> Array a+element = \ case+  NonNullable (Value imp) -> Array (Array.nonNullValue (Value.run imp))+  Nullable (Value imp) -> Array (Array.value (Value.run imp))+++-- * Composite decoders+-------------------------++{-|+Composable decoder of composite values (rows, records).+-}+newtype Composite a = Composite (Composite.Composite a)+  deriving (Functor, Applicative, Monad)++{-|+Lift a 'Value' decoder into a 'Composite' decoder for parsing of component values.+-}+field :: NullableOrNot Value a -> Composite a+field = \ case+  NonNullable (Value imp) -> Composite (Composite.nonNullValue (Value.run imp))+  Nullable (Value imp) -> Composite (Composite.value (Value.run imp))
library/Hasql/Private/Decoders/Result.hs view
@@ -20,9 +20,9 @@ run (Result reader) env =   runExceptT (runReaderT reader env) -{-# INLINE unit #-}-unit :: Result ()-unit =+{-# INLINE noResult #-}+noResult :: Result ()+noResult =   checkExecStatus $ \case     LibPQ.CommandOk -> True     LibPQ.TuplesOk -> True
library/Hasql/Private/Decoders/Results.hs view
@@ -81,4 +81,4 @@           loop integerDatetimes connection <* checkErrors           where             checkErrors =-              ExceptT $ fmap (mapLeft ResultError) $ Result.run Result.unit (integerDatetimes, result)+              ExceptT $ fmap (mapLeft ResultError) $ Result.run Result.noResult (integerDatetimes, result)
+ library/Hasql/Private/Encoders.hs view
@@ -0,0 +1,371 @@+{-|+A DSL for declaration of query parameter encoders.+-}+module Hasql.Private.Encoders+where++import Hasql.Private.Prelude hiding (bool)+import qualified PostgreSQL.Binary.Encoding as A+import qualified PostgreSQL.Binary.Data as B+import qualified Text.Builder as C+import qualified Hasql.Private.Encoders.Params as Params+import qualified Hasql.Private.Encoders.Value as Value+import qualified Hasql.Private.Encoders.Array as Array+import qualified Hasql.Private.PTI as PTI+import qualified Hasql.Private.Prelude as Prelude+++-- * Parameters Product Encoder+-------------------------++{-|+Encoder of some representation of a parameters product.++Has instances of 'Contravariant', 'Divisible' and 'Monoid',+which you can use to compose multiple parameters together.+E.g.,++@+someParamsEncoder :: 'Params' (Int64, Maybe Text)+someParamsEncoder =+  ('fst' '>$<' 'param' ('nonNullable' 'int8')) '<>'+  ('snd' '>$<' 'param' ('nullable' 'text'))+@++As a general solution for tuples of any arity, instead of 'fst' and 'snd',+consider the functions of the @contrazip@ family+from the \"contravariant-extras\" package.+E.g., here's how you can achieve the same as the above:++@+someParamsEncoder :: 'Params' (Int64, Maybe Text)+someParamsEncoder =+  'contrazip2' ('param' ('nonNullable' 'int8')) ('param' ('nullable' 'text'))+@++Here's how you can implement encoders for custom composite types:++@+data Person = Person { name :: Text, gender :: Gender, age :: Int }++data Gender = Male | Female++personParams :: 'Params' Person+personParams =+  (name '>$<' 'param' ('nonNullable' 'text')) '<>'+  (gender '>$<' 'param' ('nonNullable' genderValue)) '<>'+  ('fromIntegral' . age '>$<' 'param' ('nonNullable' 'int8'))++genderValue :: 'Value' Gender+genderValue = 'enum' genderText 'text' where+  genderText gender = case gender of+    Male -> "male"+    Female -> "female"+@+-}+newtype Params a = Params (Params.Params a)+  deriving (Contravariant, Divisible, Decidable, Monoid, Semigroup)++{-|+No parameters. Same as `mempty` and `conquered`.+-}+noParams :: Params ()+noParams = mempty++{-|+Lift a single parameter encoder, with its nullability specified,+associating it with a single placeholder.+-}+param :: NullableOrNot Value a -> Params a+param = \ case+  NonNullable (Value valueEnc) -> Params (Params.value valueEnc)+  Nullable (Value valueEnc) -> Params (Params.nullableValue valueEnc)+++-- * Nullability+-------------------------++{-|+Extensional specification of nullability over a generic encoder.+-}+data NullableOrNot encoder a where+  NonNullable :: encoder a -> NullableOrNot encoder a+  Nullable :: encoder a -> NullableOrNot encoder (Maybe a)++{-|+Specify that an encoder produces a non-nullable value.+-}+nonNullable :: encoder a -> NullableOrNot encoder a+nonNullable = NonNullable++{-|+Specify that an encoder produces a nullable value.+-}+nullable :: encoder a -> NullableOrNot encoder (Maybe a)+nullable = Nullable+++-- * Value+-------------------------++{-|+Value encoder.+-}+newtype Value a = Value (Value.Value a)+  deriving (Contravariant)++{-|+Encoder of @BOOL@ values.+-}+{-# INLINABLE bool #-}+bool :: Value Bool+bool = Value (Value.unsafePTIWithShow PTI.bool (const A.bool))++{-|+Encoder of @INT2@ values.+-}+{-# INLINABLE int2 #-}+int2 :: Value Int16+int2 = Value (Value.unsafePTIWithShow PTI.int2 (const A.int2_int16))++{-|+Encoder of @INT4@ values.+-}+{-# INLINABLE int4 #-}+int4 :: Value Int32+int4 = Value (Value.unsafePTIWithShow PTI.int4 (const A.int4_int32))++{-|+Encoder of @INT8@ values.+-}+{-# INLINABLE int8 #-}+int8 :: Value Int64+int8 = Value (Value.unsafePTIWithShow PTI.int8 (const A.int8_int64))++{-|+Encoder of @FLOAT4@ values.+-}+{-# INLINABLE float4 #-}+float4 :: Value Float+float4 = Value (Value.unsafePTIWithShow PTI.float4 (const A.float4))++{-|+Encoder of @FLOAT8@ values.+-}+{-# INLINABLE float8 #-}+float8 :: Value Double+float8 = Value (Value.unsafePTIWithShow PTI.float8 (const A.float8))++{-|+Encoder of @NUMERIC@ values.+-}+{-# INLINABLE numeric #-}+numeric :: Value B.Scientific+numeric = Value (Value.unsafePTIWithShow PTI.numeric (const A.numeric))++{-|+Encoder of @CHAR@ values.++Note that it supports Unicode values and+identifies itself under the @TEXT@ OID because of that.+-}+{-# INLINABLE char #-}+char :: Value Char+char = Value (Value.unsafePTIWithShow PTI.text (const A.char_utf8))++{-|+Encoder of @TEXT@ values.+-}+{-# INLINABLE text #-}+text :: Value Text+text = Value (Value.unsafePTIWithShow PTI.text (const A.text_strict))++{-|+Encoder of @BYTEA@ values.+-}+{-# INLINABLE bytea #-}+bytea :: Value ByteString+bytea = Value (Value.unsafePTIWithShow PTI.bytea (const A.bytea_strict))++{-|+Encoder of @DATE@ values.+-}+{-# INLINABLE date #-}+date :: Value B.Day+date = Value (Value.unsafePTIWithShow PTI.date (const A.date))++{-|+Encoder of @TIMESTAMP@ values.+-}+{-# INLINABLE timestamp #-}+timestamp :: Value B.LocalTime+timestamp = Value (Value.unsafePTIWithShow PTI.timestamp (Prelude.bool A.timestamp_float A.timestamp_int))++{-|+Encoder of @TIMESTAMPTZ@ values.+-}+{-# INLINABLE timestamptz #-}+timestamptz :: Value B.UTCTime+timestamptz = Value (Value.unsafePTIWithShow PTI.timestamptz (Prelude.bool A.timestamptz_float A.timestamptz_int))++{-|+Encoder of @TIME@ values.+-}+{-# INLINABLE time #-}+time :: Value B.TimeOfDay+time = Value (Value.unsafePTIWithShow PTI.time (Prelude.bool A.time_float A.time_int))++{-|+Encoder of @TIMETZ@ values.+-}+{-# INLINABLE timetz #-}+timetz :: Value (B.TimeOfDay, B.TimeZone)+timetz = Value (Value.unsafePTIWithShow PTI.timetz (Prelude.bool A.timetz_float A.timetz_int))++{-|+Encoder of @INTERVAL@ values.+-}+{-# INLINABLE interval #-}+interval :: Value B.DiffTime+interval = Value (Value.unsafePTIWithShow PTI.interval (Prelude.bool A.interval_float A.interval_int))++{-|+Encoder of @UUID@ values.+-}+{-# INLINABLE uuid #-}+uuid :: Value B.UUID+uuid = Value (Value.unsafePTIWithShow PTI.uuid (const A.uuid))++{-|+Encoder of @INET@ values.+-}+{-# INLINABLE inet #-}+inet :: Value (B.NetAddr B.IP)+inet = Value (Value.unsafePTIWithShow PTI.inet (const A.inet))++{-|+Encoder of @JSON@ values from JSON AST.+-}+{-# INLINABLE json #-}+json :: Value B.Value+json = Value (Value.unsafePTIWithShow PTI.json (const A.json_ast))++{-|+Encoder of @JSON@ values from raw JSON.+-}+{-# INLINABLE jsonBytes #-}+jsonBytes :: Value ByteString+jsonBytes = Value (Value.unsafePTIWithShow PTI.json (const A.json_bytes))++{-|+Encoder of @JSONB@ values from JSON AST.+-}+{-# INLINABLE jsonb #-}+jsonb :: Value B.Value+jsonb = Value (Value.unsafePTIWithShow PTI.jsonb (const A.jsonb_ast))++{-|+Encoder of @JSONB@ values from raw JSON.+-}+{-# INLINABLE jsonbBytes #-}+jsonbBytes :: Value ByteString+jsonbBytes = Value (Value.unsafePTIWithShow PTI.jsonb (const A.jsonb_bytes))++{-|+Given a function,+which maps a value into a textual enum label used on the DB side,+produces an encoder of that value.+-}+{-# INLINABLE enum #-}+enum :: (a -> Text) -> Value a+enum mapping = Value (Value.unsafePTI PTI.text (const (A.text_strict . mapping)) (C.text . mapping))++{-|+Identifies the value with the PostgreSQL's \"unknown\" type,+thus leaving it up to Postgres to infer the actual type of the value.++The value transimitted is any value encoded in the Postgres' Text data format.+For reference, see the+<https://www.postgresql.org/docs/10/static/protocol-overview.html#protocol-format-codes Formats and Format Codes>+section of the Postgres' documentation.+-}+{-# INLINABLE unknown #-}+unknown :: Value ByteString+unknown = Value (Value.unsafePTIWithShow PTI.unknown (const A.bytea_strict))++{-|+Lift an array encoder into a parameter encoder.+-}+array :: Array a -> Value a+array (Array (Array.Array valueOID arrayOID arrayEncoder renderer)) = let+  encoder env input = A.array (PTI.oidWord32 valueOID) (arrayEncoder env input)+  in Value (Value.Value arrayOID arrayOID encoder renderer)++{-|+Lift a value encoder of element into a unidimensional array encoder of a foldable value.++E.g.,++@+vectorOfInts :: Value (Vector Int64)+vectorOfInts = 'foldableArray' ('nonNullable' 'int8')+@++This function is merely a shortcut to the following expression:++@+('array' . 'dimension' 'foldl'' . 'element')+@++Please notice that in case of multidimensional arrays nesting 'foldableArray' encoder+won't work. You have to explicitly construct the array encoder using 'array'.+-}+{-# INLINE foldableArray #-}+foldableArray :: Foldable foldable => NullableOrNot Value element -> Value (foldable element)+foldableArray = array . dimension foldl' . element+++-- * Array+-------------------------++{-|+Generic array encoder.++Here's an example of its usage:++@+someParamsEncoder :: 'Params' [[Int64]]+someParamsEncoder = 'param' ('nonNullable' ('array' ('dimension' 'foldl'' ('dimension' 'foldl'' ('element' ('nonNullable' 'int8'))))))+@++Please note that the PostgreSQL @IN@ keyword does not accept an array, but rather a syntactical list of+values, thus this encoder is not suited for that. Use a @value = ANY($1)@ condition instead.+-}+newtype Array a = Array (Array.Array a)+  deriving (Contravariant)++{-|+Lifts a 'Value' encoder into an 'Array' encoder.+-}+element :: NullableOrNot Value a -> Array a+element = \ case+  NonNullable (Value (Value.Value elementOID arrayOID encoder renderer)) ->+    Array (Array.value elementOID arrayOID encoder renderer)+  Nullable (Value (Value.Value elementOID arrayOID encoder renderer)) ->+    Array (Array.nullableValue elementOID arrayOID encoder renderer)++{-|+Encoder of an array dimension,+which thus provides support for multidimensional arrays.++Accepts:++* An implementation of the left-fold operation,+such as @Data.Foldable.'foldl''@,+which determines the input value.++* A component encoder, which can be either another 'dimension' or 'element'.+-}+{-# INLINABLE dimension #-}+dimension :: (forall a. (a -> b -> a) -> a -> c -> a) -> Array b -> Array c+dimension foldl (Array imp) = Array (Array.dimension foldl imp)
library/Hasql/Private/Encoders/Array.hs view
@@ -9,6 +9,10 @@ data Array a =   Array B.OID B.OID (Bool -> a -> A.Array) (a -> C.Builder) +instance Contravariant Array where+  contramap fn (Array valueOid arrayOid encoder renderer) =+    Array valueOid arrayOid (\ intDateTimes -> encoder intDateTimes . fn) (renderer . fn)+ {-# INLINE value #-} value :: B.OID -> B.OID -> (Bool -> a -> A.Encoding) -> (a -> C.Builder) -> Array a value valueOID arrayOID encoder =
library/Hasql/Private/IO.hs view
@@ -88,7 +88,7 @@         sent <- LibPQ.sendPrepare connection key template (mfilter (not . null) (Just oidList))         let resultsDecoder =                if sent-                then ResultsDecoders.single ResultDecoders.unit+                then ResultsDecoders.single ResultDecoders.noResult                 else ResultsDecoders.clientError         fmap resultsMapping $ getResults connection undefined resultsDecoder       where
library/Hasql/Private/Prelude.hs view
@@ -36,10 +36,6 @@ ------------------------- import Control.Monad.Error.Class as Exports (MonadError (..)) --- data-default-class---------------------------import Data.Default.Class as Exports- -- profunctors ------------------------- import Data.Profunctor.Unsafe as Exports@@ -84,6 +80,10 @@ -- loch-th ------------------------- import Debug.Trace.LocationTH as Exports++-- postgresql-binary+-------------------------+import PostgreSQL.Binary.Data as Exports (UUID)  -- custom -------------------------
library/Hasql/Private/Session.hs view
@@ -7,6 +7,7 @@ import qualified Hasql.Private.Decoders.Results as Decoders.Results import qualified Hasql.Private.Decoders.Result as Decoders.Result import qualified Hasql.Private.Encoders.Params as Encoders.Params+import qualified Hasql.Private.Encoders as Encoders import qualified Hasql.Private.Settings as Settings import qualified Hasql.Private.IO as IO import qualified Hasql.Statement as Statement@@ -39,21 +40,21 @@       return $ r1 *> r2   where     decoder =-      Decoders.Results.single Decoders.Result.unit+      Decoders.Results.single Decoders.Result.noResult  -- | -- Parameters and a specification of a parametric single-statement query to apply them to. statement :: params -> Statement.Statement params result -> Session result-statement input (Statement.Statement template encoder decoder preparable) =+statement input (Statement.Statement template (Encoders.Params paramsEncoder) decoder preparable) =   Session $ ReaderT $ \(Connection.Connection pqConnectionRef integerDatetimes registry) ->     ExceptT $ fmap (mapLeft (QueryError template inputReps)) $ withMVar pqConnectionRef $ \pqConnection -> do-      r1 <- IO.sendParametricStatement pqConnection integerDatetimes registry template (unsafeCoerce encoder) preparable input+      r1 <- IO.sendParametricStatement pqConnection integerDatetimes registry template paramsEncoder preparable input       r2 <- IO.getResults pqConnection integerDatetimes (unsafeCoerce decoder)       return $ r1 *> r2   where     inputReps =       let-        Encoders.Params.Params (Op encoderOp) = (unsafeCoerce encoder)+        Encoders.Params.Params (Op encoderOp) = paramsEncoder         step (_, _, _, rendering) acc =           rendering : acc         in foldr step [] (encoderOp input)
library/Hasql/Statement.hs view
@@ -1,47 +1,53 @@ module Hasql.Statement+(+  Statement(..),+  -- * Recipies++  -- ** Insert many+  -- $insertMany++  -- ** IN and NOT IN+  -- $inAndNotIn+) where  import Hasql.Private.Prelude import qualified Hasql.Decoders as Decoders import qualified Hasql.Encoders as Encoders +{-|+Specification of a strictly single-statement query, which can be parameterized and prepared. --- |--- A specification of a strictly single-statement query, which can be parameterized and prepared.--- --- Consists of the following:--- --- * SQL template,--- * params encoder,--- * result decoder,--- * a flag, determining whether it should be prepared.--- --- The SQL template must be formatted according to Postgres' standard,--- with any non-ASCII characters of the template encoded using UTF-8.--- According to the format,--- parameters must be referred to using the positional notation, as in the following:--- @$1@, @$2@, @$3@ and etc.--- Those references must be used to refer to the values of the 'Encoders.Params' encoder.--- --- Following is an example of the declaration of a prepared statement with its associated codecs.--- --- @--- selectSum :: Hasql.Statement.'Statement' (Int64, Int64) Int64--- selectSum =---   Hasql.Statement.'Statement' sql encoder decoder True---   where---     sql =---       "select ($1 + $2)"---     encoder =---       'contramap' 'fst' (Hasql.Encoders.'Hasql.Encoders.param' Hasql.Encoders.'Hasql.Encoders.int8') '<>'---       'contramap' 'snd' (Hasql.Encoders.'Hasql.Encoders.param' Hasql.Encoders.'Hasql.Encoders.int8')---     decoder =---       Hasql.Decoders.'Hasql.Decoders.singleRow' (Hasql.Decoders.'Hasql.Decoders.column' Hasql.Decoders.'Hasql.Decoders.int8')--- @--- --- The statement above accepts a product of two parameters of type 'Int64'--- and produces a single result of type 'Int64'.--- +Consists of the following:++* SQL template,+* params encoder,+* result decoder,+* a flag, determining whether it should be prepared.++The SQL template must be formatted according to Postgres' standard,+with any non-ASCII characters of the template encoded using UTF-8.+According to the format,+parameters must be referred to using a positional notation, as in the following:+@$1@, @$2@, @$3@ and etc.+Those references must be used in accordance to the order in which the according+value encoders are specified in 'Encoders.Params'.++Following is an example of a declaration of a prepared statement with its associated codecs.++@+selectSum :: 'Statement' (Int64, Int64) Int64+selectSum = 'Statement' sql encoder decoder True where+  sql = "select ($1 + $2)"+  encoder =+    ('fst' '>$<' Encoders.'Hasql.Encoders.param' (Encoders.'Hasql.Encoders.nonNullable' Encoders.'Hasql.Encoders.int8')) '<>'+    ('snd' '>$<' Encoders.'Hasql.Encoders.param' (Encoders.'Hasql.Encoders.nullable' Encoders.'Hasql.Encoders.text'))+  decoder = Decoders.'Hasql.Decoders.singleRow' (Decoders.'Hasql.Decoders.column' (Decoders.'Hasql.Decoders.nonNullable' Decoders.'Hasql.Decoders.int8'))+@++The statement above accepts a product of two parameters of type 'Int64'+and produces a single result of type 'Int64'.+-} data Statement a b =   Statement ByteString (Encoders.Params a) (Decoders.Result b) Bool @@ -53,3 +59,53 @@   {-# INLINE dimap #-}   dimap f1 f2 (Statement template encoder decoder preparable) =     Statement template (contramap f1 encoder) (fmap f2 decoder) preparable+++{- $insertMany++It is not currently possible to pass in an array of encodable values+to use in an insert many statement. Instead, PostgreSQL's+(9.4 or later) @unnest@ function can be used in an analogous way+to haskell's `zip` function by passing in multiple arrays of values+to be zipped into the rows we want to insert:++@+insertMultipleLocations :: 'Statement' (Vector (UUID, Double, Double)) ()+insertMultipleLocations = 'Statement' sql encoder decoder True where+  sql = "insert into location (id, x, y) select * from unnest ($1, $2, $3)"+  encoder =+    contramap Vector.'Data.Vector.unzip3' $+    contrazip3 (vector Encoders.'Encoders.uuid') (vector Encoders.'Encoders.float8') (vector Encoders.'Encoders.float8')+    where+      vector =+        Encoders.'Encoders.param' .+        Encoders.'Encoders.nonNullable' .+        Encoders.'Encoders.array' .+        Encoders.'Encoders.dimension' 'foldl'' .+        Encoders.'Encoders.element' .+        Encoders.'Encoders.nonNullable'+  decoder = Decoders.'Decoders.noResult'+@++This approach is much more efficient than executing a single-row Insert+statement multiple times.+-}++{- $inAndNotIn++There is a common misconception that Postgresql supports array+as a parameter for the @IN@ operator.+However Postgres only supports a syntactical list of values with it,+i.e., you have to specify each option as an individual parameter+(@something IN ($1, $2, $3)@).++Clearly it would be much more convenient to provide an array as a single parameter,+but the @IN@ operator does not support that.+Fortunately, Postgres does provide such functionality with other operators:++* Use @something = ANY($1)@ instead of @something IN ($1)@+* Use @something <> ALL($1)@ instead of @something NOT IN ($1)@++For details see+<https://www.postgresql.org/docs/9.6/static/functions-comparisons.html#AEN20944 the Postgresql docs>.+-}
profiling/Main.hs view
@@ -70,7 +70,7 @@       D.singleRow row       where         row =-          tuple <$> D.column D.int8 <*> D.column D.int8+          tuple <$> (D.column . D.nonNullable) D.int8 <*> (D.column . D.nonNullable) D.int8           where             tuple !a !b =               (a, b)@@ -84,7 +84,7 @@     encoder =       conquer     rowDecoder =-      tuple <$> D.column D.int8 <*> D.column D.int8+      tuple <$> (D.column . D.nonNullable) D.int8 <*> (D.column . D.nonNullable) D.int8       where         tuple !a !b =           (a, b)
tasty/Main.hs view
@@ -22,6 +22,26 @@   localOption (NumThreads 1) $   testGroup "All tests"   [+    testGroup "Roundtrips" $ let+      roundtrip encoder decoder input = let+        session = let+          statement = Statement.Statement "select $1" encoder decoder True+          in Session.statement input statement+        in unsafePerformIO $ do+          x <- Connection.with (Session.run session)+          return (Right (Right input) === x)+      in [+          testProperty "Array" $ let+            encoder = Encoders.param (Encoders.nonNullable (Encoders.array (Encoders.dimension foldl' (Encoders.element (Encoders.nonNullable Encoders.int8)))))+            decoder = Decoders.singleRow (Decoders.column (Decoders.nonNullable (Decoders.array (Decoders.dimension replicateM (Decoders.element (Decoders.nonNullable Decoders.int8))))))+            in roundtrip encoder decoder+          ,+          testProperty "2D Array" $ let+            encoder = Encoders.param (Encoders.nonNullable (Encoders.array (Encoders.dimension foldl' (Encoders.dimension foldl' (Encoders.element (Encoders.nonNullable Encoders.int8))))))+            decoder = Decoders.singleRow (Decoders.column (Decoders.nonNullable (Decoders.array (Decoders.dimension replicateM (Decoders.dimension replicateM (Decoders.element (Decoders.nonNullable Decoders.int8)))))))+            in \ list -> list /= [] ==> roundtrip encoder decoder (replicate 3 list)+        ]+    ,     testCase "Failed query" $     let       statement =@@ -29,10 +49,10 @@         where           encoder =             contrazip2-              (Encoders.param (Encoders.array (Encoders.dimension foldl' (Encoders.element Encoders.int8))))-              (Encoders.param Encoders.text)+              (Encoders.param (Encoders.nonNullable (Encoders.array (Encoders.dimension foldl' (Encoders.element (Encoders.nonNullable Encoders.int8))))))+              (Encoders.param (Encoders.nonNullable (Encoders.text)))           decoder =-            fmap (maybe False (const True)) (Decoders.rowMaybe (Decoders.column Decoders.bool))+            fmap (maybe False (const True)) (Decoders.rowMaybe ((Decoders.column . Decoders.nonNullable) Decoders.bool))       session =         Session.statement ([3, 7], "a") statement       in do@@ -47,9 +67,9 @@         Statement.Statement "select true where 1 = any ($1)" encoder decoder True         where           encoder =-            Encoders.param (Encoders.array (Encoders.dimension foldl' (Encoders.element Encoders.int8)))+            Encoders.param (Encoders.nonNullable (Encoders.array (Encoders.dimension foldl' (Encoders.element (Encoders.nonNullable Encoders.int8)))))           decoder =-            fmap (maybe False (const True)) (Decoders.rowMaybe (Decoders.column Decoders.bool))+            fmap (maybe False (const True)) (Decoders.rowMaybe ((Decoders.column . Decoders.nonNullable) Decoders.bool))       session =         do           result1 <- Session.statement [1, 2] statement@@ -65,9 +85,9 @@         Statement.Statement "select true where 3 <> all ($1)" encoder decoder True         where           encoder =-            Encoders.param (Encoders.array (Encoders.dimension foldl' (Encoders.element Encoders.int8)))+            Encoders.param (Encoders.nonNullable (Encoders.array (Encoders.dimension foldl' (Encoders.element (Encoders.nonNullable Encoders.int8)))))           decoder =-            fmap (maybe False (const True)) (Decoders.rowMaybe (Decoders.column Decoders.bool))+            fmap (maybe False (const True)) (Decoders.rowMaybe ((Decoders.column . Decoders.nonNullable) Decoders.bool))       session =         do           result1 <- Session.statement [1, 2] statement@@ -85,9 +105,9 @@           sql =             "select (1, true)"           encoder = -            Encoders.unit+            mempty           decoder =-            Decoders.singleRow (Decoders.column (Decoders.composite ((,) <$> Decoders.field Decoders.int8 <*> Decoders.field Decoders.bool)))+            Decoders.singleRow ((Decoders.column . Decoders.nonNullable) (Decoders.composite ((,) <$> (Decoders.field . Decoders.nonNullable) Decoders.int8 <*> (Decoders.field . Decoders.nonNullable) Decoders.bool)))       session =         Session.statement () statement       in do@@ -102,17 +122,17 @@           sql =             "select (1, true) as entity1, ('hello', 3) as entity2"           encoder =-            Encoders.unit+            mempty           decoder =             Decoders.singleRow $-            (,) <$> Decoders.column entity1 <*> Decoders.column entity2+            (,) <$> (Decoders.column . Decoders.nonNullable) entity1 <*> (Decoders.column . Decoders.nonNullable) entity2             where               entity1 =                 Decoders.composite $-                (,) <$> Decoders.field Decoders.int8 <*> Decoders.field Decoders.bool+                (,) <$> (Decoders.field . Decoders.nonNullable) Decoders.int8 <*> (Decoders.field . Decoders.nonNullable) Decoders.bool               entity2 =                 Decoders.composite $-                (,) <$> Decoders.field Decoders.text <*> Decoders.field Decoders.int8+                (,) <$> (Decoders.field . Decoders.nonNullable) Decoders.text <*> (Decoders.field . Decoders.nonNullable) Decoders.int8       session =         Session.statement () statement       in do@@ -135,9 +155,9 @@                   sql =                     "select array[]::int8[]"                   encoder =-                    Encoders.unit+                    mempty                   decoder =-                    Decoders.singleRow (Decoders.column (Decoders.array (Decoders.dimension replicateM (Decoders.element Decoders.int8))))+                    Decoders.singleRow ((Decoders.column . Decoders.nonNullable) (Decoders.array (Decoders.dimension replicateM (Decoders.element (Decoders.nonNullable Decoders.int8)))))       in io     ,     testCase "Failing prepared statements" $@@ -162,9 +182,9 @@                       sql =                         "absurd"                       encoder =-                        Encoders.unit+                        mempty                       decoder =-                        Decoders.unit+                        Decoders.noResult       in io     ,     testCase "Prepared statements after error" $@@ -185,9 +205,9 @@                       sql =                         "select $1 :: int8"                       encoder =-                        Encoders.param Encoders.int8+                        Encoders.param (Encoders.nonNullable (Encoders.int8))                       decoder =-                        Decoders.singleRow $ Decoders.column Decoders.int8+                        Decoders.singleRow $ (Decoders.column . Decoders.nonNullable) Decoders.int8               fail =                 catchError (Session.sql "absurd") (const (pure ()))       in io@@ -201,10 +221,10 @@           sql =             "select ($1 + $2)"           encoder =-            contramap fst (Encoders.param Encoders.int8) <>-            contramap snd (Encoders.param Encoders.int8)+            contramap fst (Encoders.param (Encoders.nonNullable (Encoders.int8))) <>+            contramap snd (Encoders.param (Encoders.nonNullable (Encoders.int8)))           decoder =-            Decoders.singleRow (Decoders.column Decoders.int8)+            Decoders.singleRow ((Decoders.column . Decoders.nonNullable) Decoders.int8)       sumSession :: Session.Session Int64       sumSession =         Session.sql "begin" *> Session.statement (1, 1) sumStatement <* Session.sql "end"@@ -226,10 +246,10 @@           sql =             "select ($1 + $2)"           encoder =-            contramap fst (Encoders.param Encoders.int8) <>-            contramap snd (Encoders.param Encoders.int8)+            contramap fst (Encoders.param (Encoders.nonNullable (Encoders.int8))) <>+            contramap snd (Encoders.param (Encoders.nonNullable (Encoders.int8)))           decoder =-            Decoders.singleRow (Decoders.column Decoders.int8)+            Decoders.singleRow ((Decoders.column . Decoders.nonNullable) Decoders.int8)       session :: Session.Session Int64       session =         do@@ -253,9 +273,9 @@                 sql =                   "select $1 = interval '10 seconds'"                 decoder =-                  (Decoders.singleRow (Decoders.column (Decoders.bool)))+                  (Decoders.singleRow ((Decoders.column . Decoders.nonNullable) (Decoders.bool)))                 encoder =-                  Encoders.param (Encoders.interval)+                  Encoders.param (Encoders.nonNullable (Encoders.interval))             in DSL.statement (10 :: DiffTime) statement       in actualIO >>= \x -> assertEqual (show x) (Right True) x     ,@@ -270,9 +290,9 @@                 sql =                   "select interval '10 seconds'"                 decoder =-                  (Decoders.singleRow (Decoders.column (Decoders.interval)))+                  (Decoders.singleRow ((Decoders.column . Decoders.nonNullable) (Decoders.interval)))                 encoder =-                  Encoders.unit+                  Encoders.noParams             in DSL.statement () statement       in actualIO >>= \x -> assertEqual (show x) (Right (10 :: DiffTime)) x     ,@@ -287,9 +307,9 @@                 sql =                   "select $1"                 decoder =-                  (Decoders.singleRow (Decoders.column (Decoders.interval)))+                  (Decoders.singleRow ((Decoders.column . Decoders.nonNullable) (Decoders.interval)))                 encoder =-                  Encoders.param (Encoders.interval)+                  Encoders.param (Encoders.nonNullable (Encoders.interval))             in DSL.statement (10 :: DiffTime) statement       in actualIO >>= \x -> assertEqual (show x) (Right (10 :: DiffTime)) x     ,@@ -299,14 +319,14 @@         DSL.session $ do           let             statement =-              Statement.Statement sql mempty Decoders.unit True+              Statement.Statement sql mempty Decoders.noResult True               where                 sql =                   "drop type if exists mood"             in DSL.statement () statement           let             statement =-              Statement.Statement sql mempty Decoders.unit True+              Statement.Statement sql mempty Decoders.noResult True               where                 sql =                   "create type mood as enum ('sad', 'ok', 'happy')"@@ -318,9 +338,9 @@                 sql =                   "select $1 = ('ok' :: mood)"                 decoder =-                  (Decoders.singleRow (Decoders.column (Decoders.bool)))+                  (Decoders.singleRow ((Decoders.column . Decoders.nonNullable) (Decoders.bool)))                 encoder =-                  Encoders.param (Encoders.unknown)+                  Encoders.param (Encoders.nonNullable (Encoders.unknown))             in DSL.statement "ok" statement       in actualIO >>= assertEqual "" (Right True)     ,@@ -330,14 +350,14 @@         DSL.session $ do           let             statement =-              Statement.Statement sql mempty Decoders.unit True+              Statement.Statement sql mempty Decoders.noResult True               where                 sql =                   "create or replace function overloaded(a int, b int) returns int as $$ select a + b $$ language sql;"             in DSL.statement () statement           let             statement =-              Statement.Statement sql mempty Decoders.unit True+              Statement.Statement sql mempty Decoders.noResult True               where                 sql =                   "create or replace function overloaded(a text, b text, c text) returns text as $$ select a || b || c $$ language sql;"@@ -349,9 +369,9 @@                 sql =                   "select overloaded($1, $2) || overloaded($3, $4, $5)"                 decoder =-                  (Decoders.singleRow (Decoders.column (Decoders.text)))+                  (Decoders.singleRow ((Decoders.column . Decoders.nonNullable) (Decoders.text)))                 encoder =-                  contramany (Encoders.param Encoders.unknown)+                  contramany (Encoders.param (Encoders.nonNullable (Encoders.unknown)))             in DSL.statement ["1", "2", "4", "5", "6"] statement       in actualIO >>= assertEqual "" (Right "3456")     ,@@ -361,14 +381,14 @@         DSL.session $ do           let             statement =-              Statement.Statement sql mempty Decoders.unit True+              Statement.Statement sql mempty Decoders.noResult True               where                 sql =                   "drop type if exists mood"             in DSL.statement () statement           let             statement =-              Statement.Statement sql mempty Decoders.unit True+              Statement.Statement sql mempty Decoders.noResult True               where                 sql =                   "create type mood as enum ('sad', 'ok', 'happy')"@@ -380,9 +400,9 @@                 sql =                   "select ($1 :: mood)"                 decoder =-                  (Decoders.singleRow (Decoders.column (Decoders.enum (Just . id))))+                  (Decoders.singleRow ((Decoders.column . Decoders.nonNullable) (Decoders.enum (Just . id))))                 encoder =-                  Encoders.param (Encoders.enum id)+                  Encoders.param (Encoders.nonNullable ((Encoders.enum id)))             in DSL.statement "ok" statement       in actualIO >>= assertEqual "" (Right "ok")     ,@@ -400,9 +420,9 @@                     sql =                       "select $1"                     encoder =-                      Encoders.param Encoders.text+                      Encoders.param (Encoders.nonNullable (Encoders.text))                     decoder =-                      (Decoders.singleRow (Decoders.column (Decoders.text)))+                      (Decoders.singleRow ((Decoders.column . Decoders.nonNullable) (Decoders.text)))             effect2 =               DSL.statement 1 statement               where@@ -412,9 +432,9 @@                     sql =                       "select $1"                     encoder =-                      Encoders.param Encoders.int8+                      Encoders.param (Encoders.nonNullable (Encoders.int8))                     decoder =-                      (Decoders.singleRow (Decoders.column Decoders.int8))+                      (Decoders.singleRow ((Decoders.column . Decoders.nonNullable) Decoders.int8))             in (,) <$> effect1 <*> effect2       in actualIO >>= assertEqual "" (Right ("ok", 1))     ,@@ -438,7 +458,7 @@             DSL.statement () $ Statements.plain $             "insert into a (name) values ('a')"             deleteRows =-            DSL.statement () $ Statement.Statement sql def decoder False+            DSL.statement () $ Statement.Statement sql mempty decoder False             where               sql =                 "delete from a"@@ -452,8 +472,8 @@         DSL.session $ do           DSL.statement () $ Statements.plain $ "drop table if exists a"           DSL.statement () $ Statements.plain $ "create table a (id serial not null, v char not null, primary key (id))"-          id1 <- DSL.statement () $ Statement.Statement "insert into a (v) values ('a') returning id" def (Decoders.singleRow (Decoders.column Decoders.int4)) False-          id2 <- DSL.statement () $ Statement.Statement "insert into a (v) values ('b') returning id" def (Decoders.singleRow (Decoders.column Decoders.int4)) False+          id1 <- DSL.statement () $ Statement.Statement "insert into a (v) values ('a') returning id" mempty (Decoders.singleRow ((Decoders.column . Decoders.nonNullable) Decoders.int4)) False+          id2 <- DSL.statement () $ Statement.Statement "insert into a (v) values ('b') returning id" mempty (Decoders.singleRow ((Decoders.column . Decoders.nonNullable) Decoders.int4)) False           DSL.statement () $ Statements.plain $ "drop table if exists a"           pure (id1, id2)       in assertEqual "" (Right (1, 2)) =<< actualIO
tasty/Main/Prelude.hs view
@@ -8,7 +8,3 @@ -- rerebase ------------------------- import Prelude as Exports---- data-default-class---------------------------import Data.Default.Class as Exports
tasty/Main/Statements.hs view
@@ -1,19 +1,15 @@ module Main.Statements where -import Main.Prelude hiding (def)+import Main.Prelude import qualified Hasql.Statement as HQ import qualified Hasql.Encoders as HE import qualified Hasql.Decoders as HD import qualified Main.Prelude as Prelude  -def :: ByteString -> HQ.Statement () ()-def sql =-  HQ.Statement sql Prelude.def Prelude.def False- plain :: ByteString -> HQ.Statement () () plain sql =-  HQ.Statement sql mempty HD.unit False+  HQ.Statement sql mempty HD.noResult False  dropType :: ByteString -> HQ.Statement () () dropType name =@@ -33,4 +29,4 @@     sql =       "values (1,2), (3,4), (5,6)"     decoder =-      HD.rowList ((,) <$> HD.column HD.int8 <*> HD.column HD.int8)+      HD.rowList ((,) <$> (HD.column . HD.nonNullable) HD.int8 <*> (HD.column . HD.nonNullable) HD.int8)
threads-test/Main/Statements.hs view
@@ -13,8 +13,8 @@     sql =       "select pg_sleep($1)"     encoder =-      E.param E.float8+      E.param (E.nonNullable E.float8)     decoder =-      D.unit+      D.noResult