diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -52,6 +52,15 @@
 
 # Tutorials
 
+## Videos
+
+There's several videos on Hasql done as part of a nice intro-level series of live Haskell+Bazel coding by the "Ants Are Everywhere" YouTube channel:
+
+- [Coding Day 20: Switching from postgresql-simple to Hasql](https://youtu.be/ce7bGKETtoA?si=RmY_yDG24EX6i38I)
+- [Coding Day 21: Refactoring the Hasql code](https://youtu.be/a9mPNXbT-qw?si=RTtXe6BXnZSQZzh-)
+
+## Articles
+
 - [Organization of Hasql code in a dedicated library](https://github.com/nikita-volkov/hasql-tutorial1)
 
 # Short Example
diff --git a/benchmarks/Main.hs b/benchmarks/Main.hs
--- a/benchmarks/Main.hs
+++ b/benchmarks/Main.hs
@@ -2,10 +2,10 @@
 
 import Criterion
 import Criterion.Main
-import qualified Hasql.Connection as A
-import qualified Hasql.Decoders as D
-import qualified Hasql.Session as B
-import qualified Hasql.Statement as C
+import Hasql.Connection qualified as A
+import Hasql.Decoders qualified as D
+import Hasql.Session qualified as B
+import Hasql.Statement qualified as C
 import Prelude
 
 main :: IO ()
diff --git a/hasql.cabal b/hasql.cabal
--- a/hasql.cabal
+++ b/hasql.cabal
@@ -1,33 +1,32 @@
-cabal-version:      3.0
-name:               hasql
-version:            1.6.4.3
-category:           Hasql, Database, PostgreSQL
-synopsis:           An efficient PostgreSQL driver with a flexible mapping API
+cabal-version: 3.0
+name: hasql
+version: 1.6.4.4
+category: Hasql, Database, PostgreSQL
+synopsis: An efficient PostgreSQL driver with a flexible mapping API
 description:
   Root of the \"hasql\" ecosystem.
   For details and tutorials see
   <https://github.com/nikita-volkov/hasql the readme>.
   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
+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
 extra-source-files:
   CHANGELOG.md
   README.md
 
 source-repository head
-  type:     git
+  type: git
   location: git://github.com/nikita-volkov/hasql.git
 
 common base
+  default-language: Haskell2010
   default-extensions:
-    NoImplicitPrelude
-    NoMonomorphismRestriction
     Arrows
     BangPatterns
     ConstraintKinds
@@ -44,11 +43,14 @@
     FunctionalDependencies
     GADTs
     GeneralizedNewtypeDeriving
+    ImportQualifiedPost
     LambdaCase
     LiberalTypeSynonyms
     MagicHash
     MultiParamTypeClasses
     MultiWayIf
+    NoImplicitPrelude
+    NoMonomorphismRestriction
     OverloadedStrings
     ParallelListComp
     PatternGuards
@@ -64,20 +66,24 @@
     TypeOperators
     UnboxedTuples
 
-  default-language:   Haskell2010
-
 common executable
-  import:      base
+  import: base
   ghc-options:
-    -O2 -threaded -with-rtsopts=-N -rtsopts -funbox-strict-fields
+    -O2
+    -threaded
+    -with-rtsopts=-N
+    -rtsopts
+    -funbox-strict-fields
 
 common test
-  import:      base
-  ghc-options: -threaded -with-rtsopts=-N
+  import: base
+  ghc-options:
+    -threaded
+    -with-rtsopts=-N
 
 library
-  import:          base
-  hs-source-dirs:  library
+  import: base
+  hs-source-dirs: library
   exposed-modules:
     Hasql.Connection
     Hasql.Decoders
@@ -101,81 +107,96 @@
     Hasql.Encoders.Value
     Hasql.Errors
     Hasql.IO
+    Hasql.PostgresTypeInfo
     Hasql.Prelude
     Hasql.PreparedStatementRegistry
-    Hasql.PTI
     Hasql.Session.Core
     Hasql.Settings
 
   build-depends:
-    , aeson >=2 && <3
-    , attoparsec >=0.10 && <0.15
-    , base >=4.13 && <5
-    , bytestring >=0.10 && <0.13
-    , bytestring-strict-builder >=0.4.5.1 && <0.5
-    , contravariant >=1.3 && <2
-    , dlist >=0.8 && <0.9 || >=1 && <2
-    , hashable >=1.2 && <2
-    , hashtables >=1.1 && <2
-    , mtl >=2 && <3
-    , network-ip >=0.3.0.3 && <0.4
-    , postgresql-binary >=0.13.1 && <0.14
-    , postgresql-libpq >=0.9 && <0.11
-    , profunctors >=5.1 && <6
-    , scientific >=0.3 && <0.4
-    , text >=1 && <3
-    , text-builder >=0.6.7 && <0.7
-    , time >=1.9 && <2
-    , transformers >=0.3 && <0.7
-    , uuid >=1.3 && <2
-    , vector >=0.10 && <0.14
+    aeson >=2 && <3,
+    attoparsec >=0.10 && <0.15,
+    base >=4.14 && <5,
+    bytestring >=0.10 && <0.13,
+    bytestring-strict-builder >=0.4.5.1 && <0.5,
+    contravariant >=1.3 && <2,
+    dlist >=0.8 && <0.9 || >=1 && <2,
+    hashable >=1.2 && <2,
+    hashtables >=1.1 && <2,
+    mtl >=2 && <3,
+    network-ip >=0.3.0.3 && <0.4,
+    postgresql-binary >=0.13.1 && <0.14,
+    postgresql-libpq >=0.9 && <0.11,
+    profunctors >=5.1 && <6,
+    scientific >=0.3 && <0.4,
+    text >=1 && <3,
+    text-builder >=0.6.7 && <0.7,
+    time >=1.9 && <2,
+    transformers >=0.3 && <0.7,
+    uuid >=1.3 && <2,
+    vector >=0.10 && <0.14,
 
+library testing-utils
+  import: base
+  hs-source-dirs: testing-utils
+  exposed-modules:
+    Hasql.TestingUtils.Constants
+    Hasql.TestingUtils.TestingDsl
+
+  build-depends:
+    hasql,
+    rerebase <2,
+
 test-suite tasty
-  import:         base
-  type:           exitcode-stdio-1.0
+  import: base
+  type: exitcode-stdio-1.0
   hs-source-dirs: tasty
-  main-is:        Main.hs
+  main-is: Main.hs
   other-modules:
     Main.Connection
-    Main.DSL
     Main.Prelude
     Main.Statements
 
   build-depends:
-    , contravariant-extras >=0.3.5.2 && <0.4
-    , hasql
-    , 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
+    contravariant-extras >=0.3.5.2 && <0.4,
+    hasql,
+    hasql:testing-utils,
+    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
-  import:         test
-  type:           exitcode-stdio-1.0
+  import: test
+  type: exitcode-stdio-1.0
   hs-source-dirs: threads-test
-  main-is:        Main.hs
-  other-modules:  Main.Statements
+  main-is: Main.hs
+  other-modules: Main.Statements
   build-depends:
-    , hasql
-    , rerebase
+    hasql,
+    rerebase,
 
 benchmark benchmarks
-  import:         executable
-  type:           exitcode-stdio-1.0
+  import: executable
+  type: exitcode-stdio-1.0
   hs-source-dirs: benchmarks
-  main-is:        Main.hs
+  main-is: Main.hs
   build-depends:
-    , criterion >=1.6 && <2
-    , hasql
-    , rerebase <2
+    criterion >=1.6 && <2,
+    hasql,
+    rerebase <2,
 
 test-suite profiling
-  import:         base
-  type:           exitcode-stdio-1.0
+  import: base
+  type: exitcode-stdio-1.0
   hs-source-dirs: profiling
-  main-is:        Main.hs
-  ghc-options:    -O2 -threaded -rtsopts
+  main-is: Main.hs
+  ghc-options:
+    -O2
+    -threaded
+    -rtsopts
+
   build-depends:
-    , hasql
-    , rerebase >=1 && <2
+    hasql,
+    rerebase >=1 && <2,
diff --git a/library/Hasql/Commands.hs b/library/Hasql/Commands.hs
--- a/library/Hasql/Commands.hs
+++ b/library/Hasql/Commands.hs
@@ -6,8 +6,8 @@
   )
 where
 
-import qualified Data.ByteString.Builder as BB
-import qualified Data.ByteString.Lazy as BL
+import Data.ByteString.Builder qualified as BB
+import Data.ByteString.Lazy qualified as BL
 import Hasql.Prelude
 
 newtype Commands
diff --git a/library/Hasql/Connection/Core.hs b/library/Hasql/Connection/Core.hs
--- a/library/Hasql/Connection/Core.hs
+++ b/library/Hasql/Connection/Core.hs
@@ -2,11 +2,11 @@
 -- This module provides a low-level effectful API dealing with the connections to the database.
 module Hasql.Connection.Core where
 
-import qualified Database.PostgreSQL.LibPQ as LibPQ
-import qualified Hasql.IO as IO
+import Database.PostgreSQL.LibPQ qualified as LibPQ
+import Hasql.IO qualified as IO
 import Hasql.Prelude
-import qualified Hasql.PreparedStatementRegistry as PreparedStatementRegistry
-import qualified Hasql.Settings as Settings
+import Hasql.PreparedStatementRegistry qualified as PreparedStatementRegistry
+import Hasql.Settings qualified as Settings
 
 -- |
 -- A single connection to the database.
diff --git a/library/Hasql/Decoders/All.hs b/library/Hasql/Decoders/All.hs
--- a/library/Hasql/Decoders/All.hs
+++ b/library/Hasql/Decoders/All.hs
@@ -2,18 +2,18 @@
 -- A DSL for declaration of result decoders.
 module Hasql.Decoders.All where
 
-import qualified Data.Aeson as Aeson
-import qualified Data.Vector.Generic as GenericVector
-import qualified Hasql.Decoders.Array as Array
-import qualified Hasql.Decoders.Composite as Composite
-import qualified Hasql.Decoders.Result as Result
-import qualified Hasql.Decoders.Results as Results
-import qualified Hasql.Decoders.Row as Row
-import qualified Hasql.Decoders.Value as Value
+import Data.Aeson qualified as Aeson
+import Data.Vector.Generic qualified as GenericVector
+import Hasql.Decoders.Array qualified as Array
+import Hasql.Decoders.Composite qualified as Composite
+import Hasql.Decoders.Result qualified as Result
+import Hasql.Decoders.Results qualified as Results
+import Hasql.Decoders.Row qualified as Row
+import Hasql.Decoders.Value qualified as Value
 import Hasql.Prelude hiding (bool, maybe)
-import qualified Hasql.Prelude as Prelude
-import qualified Network.IP.Addr as NetworkIp
-import qualified PostgreSQL.Binary.Decoding as A
+import Hasql.Prelude qualified as Prelude
+import Network.IP.Addr qualified as NetworkIp
+import PostgreSQL.Binary.Decoding qualified as A
 
 -- * Result
 
diff --git a/library/Hasql/Decoders/Array.hs b/library/Hasql/Decoders/Array.hs
--- a/library/Hasql/Decoders/Array.hs
+++ b/library/Hasql/Decoders/Array.hs
@@ -1,7 +1,7 @@
 module Hasql.Decoders.Array where
 
 import Hasql.Prelude
-import qualified PostgreSQL.Binary.Decoding as A
+import PostgreSQL.Binary.Decoding qualified as A
 
 newtype Array a
   = Array (ReaderT Bool A.Array a)
diff --git a/library/Hasql/Decoders/Composite.hs b/library/Hasql/Decoders/Composite.hs
--- a/library/Hasql/Decoders/Composite.hs
+++ b/library/Hasql/Decoders/Composite.hs
@@ -1,7 +1,7 @@
 module Hasql.Decoders.Composite where
 
 import Hasql.Prelude
-import qualified PostgreSQL.Binary.Decoding as A
+import PostgreSQL.Binary.Decoding qualified as A
 
 newtype Composite a
   = Composite (ReaderT Bool A.Composite a)
diff --git a/library/Hasql/Decoders/Result.hs b/library/Hasql/Decoders/Result.hs
--- a/library/Hasql/Decoders/Result.hs
+++ b/library/Hasql/Decoders/Result.hs
@@ -1,14 +1,14 @@
 module Hasql.Decoders.Result where
 
-import qualified Data.Attoparsec.ByteString.Char8 as Attoparsec
-import qualified Data.ByteString as ByteString
-import qualified Data.Vector as Vector
-import qualified Data.Vector.Mutable as MutableVector
-import qualified Database.PostgreSQL.LibPQ as LibPQ
-import qualified Hasql.Decoders.Row as Row
+import Data.Attoparsec.ByteString.Char8 qualified as Attoparsec
+import Data.ByteString qualified as ByteString
+import Data.Vector qualified as Vector
+import Data.Vector.Mutable qualified as MutableVector
+import Database.PostgreSQL.LibPQ qualified as LibPQ
+import Hasql.Decoders.Row qualified as Row
 import Hasql.Errors
 import Hasql.Prelude hiding (many, maybe)
-import qualified Hasql.Prelude as Prelude
+import Hasql.Prelude qualified as Prelude
 
 newtype Result a
   = Result (ReaderT (Bool, LibPQ.Result) (ExceptT ResultError IO) a)
diff --git a/library/Hasql/Decoders/Results.hs b/library/Hasql/Decoders/Results.hs
--- a/library/Hasql/Decoders/Results.hs
+++ b/library/Hasql/Decoders/Results.hs
@@ -10,11 +10,11 @@
 -- * Row-by-row fetching.
 module Hasql.Decoders.Results where
 
-import qualified Database.PostgreSQL.LibPQ as LibPQ
-import qualified Hasql.Decoders.Result as Result
+import Database.PostgreSQL.LibPQ qualified as LibPQ
+import Hasql.Decoders.Result qualified as Result
 import Hasql.Errors
 import Hasql.Prelude hiding (many, maybe)
-import qualified Hasql.Prelude as Prelude
+import Hasql.Prelude qualified as Prelude
 
 newtype Results a
   = Results (ReaderT (Bool, LibPQ.Connection) (ExceptT CommandError IO) a)
diff --git a/library/Hasql/Decoders/Row.hs b/library/Hasql/Decoders/Row.hs
--- a/library/Hasql/Decoders/Row.hs
+++ b/library/Hasql/Decoders/Row.hs
@@ -1,10 +1,10 @@
 module Hasql.Decoders.Row where
 
-import qualified Database.PostgreSQL.LibPQ as LibPQ
-import qualified Hasql.Decoders.Value as Value
+import Database.PostgreSQL.LibPQ qualified as LibPQ
+import Hasql.Decoders.Value qualified as Value
 import Hasql.Errors
 import Hasql.Prelude hiding (error)
-import qualified PostgreSQL.Binary.Decoding as A
+import PostgreSQL.Binary.Decoding qualified as A
 
 newtype Row a
   = Row (ReaderT Env (ExceptT RowError IO) a)
diff --git a/library/Hasql/Decoders/Value.hs b/library/Hasql/Decoders/Value.hs
--- a/library/Hasql/Decoders/Value.hs
+++ b/library/Hasql/Decoders/Value.hs
@@ -1,7 +1,7 @@
 module Hasql.Decoders.Value where
 
 import Hasql.Prelude
-import qualified PostgreSQL.Binary.Decoding as A
+import PostgreSQL.Binary.Decoding qualified as A
 
 newtype Value a
   = Value (Bool -> A.Value a)
diff --git a/library/Hasql/Encoders/All.hs b/library/Hasql/Encoders/All.hs
--- a/library/Hasql/Encoders/All.hs
+++ b/library/Hasql/Encoders/All.hs
@@ -2,17 +2,17 @@
 -- A DSL for declaration of query parameter encoders.
 module Hasql.Encoders.All where
 
-import qualified Data.Aeson as Aeson
-import qualified Data.ByteString.Lazy as LazyByteString
-import qualified Hasql.Encoders.Array as Array
-import qualified Hasql.Encoders.Params as Params
-import qualified Hasql.Encoders.Value as Value
-import qualified Hasql.PTI as PTI
+import Data.Aeson qualified as Aeson
+import Data.ByteString.Lazy qualified as LazyByteString
+import Hasql.Encoders.Array qualified as Array
+import Hasql.Encoders.Params qualified as Params
+import Hasql.Encoders.Value qualified as Value
+import Hasql.PostgresTypeInfo qualified as PTI
 import Hasql.Prelude hiding (bool)
-import qualified Hasql.Prelude as Prelude
-import qualified Network.IP.Addr as NetworkIp
-import qualified PostgreSQL.Binary.Encoding as A
-import qualified Text.Builder as C
+import Hasql.Prelude qualified as Prelude
+import Network.IP.Addr qualified as NetworkIp
+import PostgreSQL.Binary.Encoding qualified as A
+import Text.Builder qualified as C
 
 -- * Parameters Product Encoder
 
diff --git a/library/Hasql/Encoders/Array.hs b/library/Hasql/Encoders/Array.hs
--- a/library/Hasql/Encoders/Array.hs
+++ b/library/Hasql/Encoders/Array.hs
@@ -1,9 +1,9 @@
 module Hasql.Encoders.Array where
 
-import qualified Hasql.PTI as B
+import Hasql.PostgresTypeInfo qualified as B
 import Hasql.Prelude
-import qualified PostgreSQL.Binary.Encoding as A
-import qualified Text.Builder as C
+import PostgreSQL.Binary.Encoding qualified as A
+import Text.Builder qualified as C
 
 data Array a
   = Array B.OID B.OID (Bool -> a -> A.Array) (a -> C.Builder)
diff --git a/library/Hasql/Encoders/Params.hs b/library/Hasql/Encoders/Params.hs
--- a/library/Hasql/Encoders/Params.hs
+++ b/library/Hasql/Encoders/Params.hs
@@ -1,11 +1,11 @@
 module Hasql.Encoders.Params where
 
-import qualified Database.PostgreSQL.LibPQ as A
-import qualified Hasql.Encoders.Value as C
-import qualified Hasql.PTI as D
+import Database.PostgreSQL.LibPQ qualified as A
+import Hasql.Encoders.Value qualified as C
+import Hasql.PostgresTypeInfo qualified as D
 import Hasql.Prelude
-import qualified PostgreSQL.Binary.Encoding as B
-import qualified Text.Builder as E
+import PostgreSQL.Binary.Encoding qualified as B
+import Text.Builder qualified as E
 
 -- |
 -- Encoder of some representation of a parameters product.
diff --git a/library/Hasql/Encoders/Value.hs b/library/Hasql/Encoders/Value.hs
--- a/library/Hasql/Encoders/Value.hs
+++ b/library/Hasql/Encoders/Value.hs
@@ -1,9 +1,9 @@
 module Hasql.Encoders.Value where
 
-import qualified Hasql.PTI as PTI
+import Hasql.PostgresTypeInfo qualified as PTI
 import Hasql.Prelude
-import qualified PostgreSQL.Binary.Encoding as B
-import qualified Text.Builder as C
+import PostgreSQL.Binary.Encoding qualified as B
+import Text.Builder qualified as C
 
 data Value a
   = Value PTI.OID PTI.OID (Bool -> a -> B.Encoding) (a -> C.Builder)
diff --git a/library/Hasql/Errors.hs b/library/Hasql/Errors.hs
--- a/library/Hasql/Errors.hs
+++ b/library/Hasql/Errors.hs
@@ -10,7 +10,7 @@
 -- * Row-by-row fetching.
 module Hasql.Errors where
 
-import qualified Data.ByteString.Char8 as BC
+import Data.ByteString.Char8 qualified as BC
 import Hasql.Prelude
 
 -- |
diff --git a/library/Hasql/IO.hs b/library/Hasql/IO.hs
--- a/library/Hasql/IO.hs
+++ b/library/Hasql/IO.hs
@@ -2,14 +2,14 @@
 -- An API of low-level IO operations.
 module Hasql.IO where
 
-import qualified Database.PostgreSQL.LibPQ as LibPQ
-import qualified Hasql.Commands as Commands
-import qualified Hasql.Decoders.Result as ResultDecoders
-import qualified Hasql.Decoders.Results as ResultsDecoders
-import qualified Hasql.Encoders.Params as ParamsEncoders
+import Database.PostgreSQL.LibPQ qualified as LibPQ
+import Hasql.Commands qualified as Commands
+import Hasql.Decoders.Result qualified as ResultDecoders
+import Hasql.Decoders.Results qualified as ResultsDecoders
+import Hasql.Encoders.Params qualified as ParamsEncoders
 import Hasql.Errors
 import Hasql.Prelude
-import qualified Hasql.PreparedStatementRegistry as PreparedStatementRegistry
+import Hasql.PreparedStatementRegistry qualified as PreparedStatementRegistry
 
 {-# INLINE acquireConnection #-}
 acquireConnection :: ByteString -> IO LibPQ.Connection
diff --git a/library/Hasql/PTI.hs b/library/Hasql/PTI.hs
deleted file mode 100644
--- a/library/Hasql/PTI.hs
+++ /dev/null
@@ -1,230 +0,0 @@
-module Hasql.PTI where
-
-import qualified Database.PostgreSQL.LibPQ as LibPQ
-import Hasql.Prelude hiding (bool)
-
--- | A Postgresql type info
-data PTI = PTI {ptiOID :: !OID, ptiArrayOID :: !(Maybe OID)}
-
--- | A Word32 and a LibPQ representation of an OID
-data OID = OID {oidWord32 :: !Word32, oidPQ :: !LibPQ.Oid, oidFormat :: !LibPQ.Format}
-
-mkOID :: LibPQ.Format -> Word32 -> OID
-mkOID format x =
-  OID x ((LibPQ.Oid . fromIntegral) x) format
-
-mkPTI :: LibPQ.Format -> Word32 -> Maybe Word32 -> PTI
-mkPTI format oid arrayOID =
-  PTI (mkOID format oid) (fmap (mkOID format) arrayOID)
-
--- * Constants
-
-abstime :: PTI
-abstime = mkPTI LibPQ.Binary 702 (Just 1023)
-
-aclitem :: PTI
-aclitem = mkPTI LibPQ.Binary 1033 (Just 1034)
-
-bit :: PTI
-bit = mkPTI LibPQ.Binary 1560 (Just 1561)
-
-bool :: PTI
-bool = mkPTI LibPQ.Binary 16 (Just 1000)
-
-box :: PTI
-box = mkPTI LibPQ.Binary 603 (Just 1020)
-
-bpchar :: PTI
-bpchar = mkPTI LibPQ.Binary 1042 (Just 1014)
-
-bytea :: PTI
-bytea = mkPTI LibPQ.Binary 17 (Just 1001)
-
-char :: PTI
-char = mkPTI LibPQ.Binary 18 (Just 1002)
-
-cid :: PTI
-cid = mkPTI LibPQ.Binary 29 (Just 1012)
-
-cidr :: PTI
-cidr = mkPTI LibPQ.Binary 650 (Just 651)
-
-circle :: PTI
-circle = mkPTI LibPQ.Binary 718 (Just 719)
-
-cstring :: PTI
-cstring = mkPTI LibPQ.Binary 2275 (Just 1263)
-
-date :: PTI
-date = mkPTI LibPQ.Binary 1082 (Just 1182)
-
-daterange :: PTI
-daterange = mkPTI LibPQ.Binary 3912 (Just 3913)
-
-float4 :: PTI
-float4 = mkPTI LibPQ.Binary 700 (Just 1021)
-
-float8 :: PTI
-float8 = mkPTI LibPQ.Binary 701 (Just 1022)
-
-gtsvector :: PTI
-gtsvector = mkPTI LibPQ.Binary 3642 (Just 3644)
-
-inet :: PTI
-inet = mkPTI LibPQ.Binary 869 (Just 1041)
-
-int2 :: PTI
-int2 = mkPTI LibPQ.Binary 21 (Just 1005)
-
-int2vector :: PTI
-int2vector = mkPTI LibPQ.Binary 22 (Just 1006)
-
-int4 :: PTI
-int4 = mkPTI LibPQ.Binary 23 (Just 1007)
-
-int4range :: PTI
-int4range = mkPTI LibPQ.Binary 3904 (Just 3905)
-
-int8 :: PTI
-int8 = mkPTI LibPQ.Binary 20 (Just 1016)
-
-int8range :: PTI
-int8range = mkPTI LibPQ.Binary 3926 (Just 3927)
-
-interval :: PTI
-interval = mkPTI LibPQ.Binary 1186 (Just 1187)
-
-json :: PTI
-json = mkPTI LibPQ.Binary 114 (Just 199)
-
-jsonb :: PTI
-jsonb = mkPTI LibPQ.Binary 3802 (Just 3807)
-
-line :: PTI
-line = mkPTI LibPQ.Binary 628 (Just 629)
-
-lseg :: PTI
-lseg = mkPTI LibPQ.Binary 601 (Just 1018)
-
-macaddr :: PTI
-macaddr = mkPTI LibPQ.Binary 829 (Just 1040)
-
-money :: PTI
-money = mkPTI LibPQ.Binary 790 (Just 791)
-
-name :: PTI
-name = mkPTI LibPQ.Binary 19 (Just 1003)
-
-numeric :: PTI
-numeric = mkPTI LibPQ.Binary 1700 (Just 1231)
-
-numrange :: PTI
-numrange = mkPTI LibPQ.Binary 3906 (Just 3907)
-
-oid :: PTI
-oid = mkPTI LibPQ.Binary 26 (Just 1028)
-
-oidvector :: PTI
-oidvector = mkPTI LibPQ.Binary 30 (Just 1013)
-
-path :: PTI
-path = mkPTI LibPQ.Binary 602 (Just 1019)
-
-point :: PTI
-point = mkPTI LibPQ.Binary 600 (Just 1017)
-
-polygon :: PTI
-polygon = mkPTI LibPQ.Binary 604 (Just 1027)
-
-record :: PTI
-record = mkPTI LibPQ.Binary 2249 (Just 2287)
-
-refcursor :: PTI
-refcursor = mkPTI LibPQ.Binary 1790 (Just 2201)
-
-regclass :: PTI
-regclass = mkPTI LibPQ.Binary 2205 (Just 2210)
-
-regconfig :: PTI
-regconfig = mkPTI LibPQ.Binary 3734 (Just 3735)
-
-regdictionary :: PTI
-regdictionary = mkPTI LibPQ.Binary 3769 (Just 3770)
-
-regoper :: PTI
-regoper = mkPTI LibPQ.Binary 2203 (Just 2208)
-
-regoperator :: PTI
-regoperator = mkPTI LibPQ.Binary 2204 (Just 2209)
-
-regproc :: PTI
-regproc = mkPTI LibPQ.Binary 24 (Just 1008)
-
-regprocedure :: PTI
-regprocedure = mkPTI LibPQ.Binary 2202 (Just 2207)
-
-regtype :: PTI
-regtype = mkPTI LibPQ.Binary 2206 (Just 2211)
-
-reltime :: PTI
-reltime = mkPTI LibPQ.Binary 703 (Just 1024)
-
-text :: PTI
-text = mkPTI LibPQ.Binary 25 (Just 1009)
-
-tid :: PTI
-tid = mkPTI LibPQ.Binary 27 (Just 1010)
-
-time :: PTI
-time = mkPTI LibPQ.Binary 1083 (Just 1183)
-
-timestamp :: PTI
-timestamp = mkPTI LibPQ.Binary 1114 (Just 1115)
-
-timestamptz :: PTI
-timestamptz = mkPTI LibPQ.Binary 1184 (Just 1185)
-
-timetz :: PTI
-timetz = mkPTI LibPQ.Binary 1266 (Just 1270)
-
-tinterval :: PTI
-tinterval = mkPTI LibPQ.Binary 704 (Just 1025)
-
-tsquery :: PTI
-tsquery = mkPTI LibPQ.Binary 3615 (Just 3645)
-
-tsrange :: PTI
-tsrange = mkPTI LibPQ.Binary 3908 (Just 3909)
-
-tstzrange :: PTI
-tstzrange = mkPTI LibPQ.Binary 3910 (Just 3911)
-
-tsvector :: PTI
-tsvector = mkPTI LibPQ.Binary 3614 (Just 3643)
-
-txid_snapshot :: PTI
-txid_snapshot = mkPTI LibPQ.Binary 2970 (Just 2949)
-
-textUnknown :: PTI
-textUnknown = mkPTI LibPQ.Text 705 (Just 705)
-
-binaryUnknown :: PTI
-binaryUnknown = mkPTI LibPQ.Binary 705 (Just 705)
-
-uuid :: PTI
-uuid = mkPTI LibPQ.Binary 2950 (Just 2951)
-
-varbit :: PTI
-varbit = mkPTI LibPQ.Binary 1562 (Just 1563)
-
-varchar :: PTI
-varchar = mkPTI LibPQ.Binary 1043 (Just 1015)
-
-void :: PTI
-void = mkPTI LibPQ.Binary 2278 Nothing
-
-xid :: PTI
-xid = mkPTI LibPQ.Binary 28 (Just 1011)
-
-xml :: PTI
-xml = mkPTI LibPQ.Binary 142 (Just 143)
diff --git a/library/Hasql/PostgresTypeInfo.hs b/library/Hasql/PostgresTypeInfo.hs
new file mode 100644
--- /dev/null
+++ b/library/Hasql/PostgresTypeInfo.hs
@@ -0,0 +1,230 @@
+module Hasql.PostgresTypeInfo where
+
+import Database.PostgreSQL.LibPQ qualified as LibPQ
+import Hasql.Prelude hiding (bool)
+
+-- | A Postgresql type info
+data PTI = PTI {ptiOID :: !OID, ptiArrayOID :: !(Maybe OID)}
+
+-- | A Word32 and a LibPQ representation of an OID
+data OID = OID {oidWord32 :: !Word32, oidPQ :: !LibPQ.Oid, oidFormat :: !LibPQ.Format}
+
+mkOID :: LibPQ.Format -> Word32 -> OID
+mkOID format x =
+  OID x ((LibPQ.Oid . fromIntegral) x) format
+
+mkPTI :: LibPQ.Format -> Word32 -> Maybe Word32 -> PTI
+mkPTI format oid arrayOID =
+  PTI (mkOID format oid) (fmap (mkOID format) arrayOID)
+
+-- * Constants
+
+abstime :: PTI
+abstime = mkPTI LibPQ.Binary 702 (Just 1023)
+
+aclitem :: PTI
+aclitem = mkPTI LibPQ.Binary 1033 (Just 1034)
+
+bit :: PTI
+bit = mkPTI LibPQ.Binary 1560 (Just 1561)
+
+bool :: PTI
+bool = mkPTI LibPQ.Binary 16 (Just 1000)
+
+box :: PTI
+box = mkPTI LibPQ.Binary 603 (Just 1020)
+
+bpchar :: PTI
+bpchar = mkPTI LibPQ.Binary 1042 (Just 1014)
+
+bytea :: PTI
+bytea = mkPTI LibPQ.Binary 17 (Just 1001)
+
+char :: PTI
+char = mkPTI LibPQ.Binary 18 (Just 1002)
+
+cid :: PTI
+cid = mkPTI LibPQ.Binary 29 (Just 1012)
+
+cidr :: PTI
+cidr = mkPTI LibPQ.Binary 650 (Just 651)
+
+circle :: PTI
+circle = mkPTI LibPQ.Binary 718 (Just 719)
+
+cstring :: PTI
+cstring = mkPTI LibPQ.Binary 2275 (Just 1263)
+
+date :: PTI
+date = mkPTI LibPQ.Binary 1082 (Just 1182)
+
+daterange :: PTI
+daterange = mkPTI LibPQ.Binary 3912 (Just 3913)
+
+float4 :: PTI
+float4 = mkPTI LibPQ.Binary 700 (Just 1021)
+
+float8 :: PTI
+float8 = mkPTI LibPQ.Binary 701 (Just 1022)
+
+gtsvector :: PTI
+gtsvector = mkPTI LibPQ.Binary 3642 (Just 3644)
+
+inet :: PTI
+inet = mkPTI LibPQ.Binary 869 (Just 1041)
+
+int2 :: PTI
+int2 = mkPTI LibPQ.Binary 21 (Just 1005)
+
+int2vector :: PTI
+int2vector = mkPTI LibPQ.Binary 22 (Just 1006)
+
+int4 :: PTI
+int4 = mkPTI LibPQ.Binary 23 (Just 1007)
+
+int4range :: PTI
+int4range = mkPTI LibPQ.Binary 3904 (Just 3905)
+
+int8 :: PTI
+int8 = mkPTI LibPQ.Binary 20 (Just 1016)
+
+int8range :: PTI
+int8range = mkPTI LibPQ.Binary 3926 (Just 3927)
+
+interval :: PTI
+interval = mkPTI LibPQ.Binary 1186 (Just 1187)
+
+json :: PTI
+json = mkPTI LibPQ.Binary 114 (Just 199)
+
+jsonb :: PTI
+jsonb = mkPTI LibPQ.Binary 3802 (Just 3807)
+
+line :: PTI
+line = mkPTI LibPQ.Binary 628 (Just 629)
+
+lseg :: PTI
+lseg = mkPTI LibPQ.Binary 601 (Just 1018)
+
+macaddr :: PTI
+macaddr = mkPTI LibPQ.Binary 829 (Just 1040)
+
+money :: PTI
+money = mkPTI LibPQ.Binary 790 (Just 791)
+
+name :: PTI
+name = mkPTI LibPQ.Binary 19 (Just 1003)
+
+numeric :: PTI
+numeric = mkPTI LibPQ.Binary 1700 (Just 1231)
+
+numrange :: PTI
+numrange = mkPTI LibPQ.Binary 3906 (Just 3907)
+
+oid :: PTI
+oid = mkPTI LibPQ.Binary 26 (Just 1028)
+
+oidvector :: PTI
+oidvector = mkPTI LibPQ.Binary 30 (Just 1013)
+
+path :: PTI
+path = mkPTI LibPQ.Binary 602 (Just 1019)
+
+point :: PTI
+point = mkPTI LibPQ.Binary 600 (Just 1017)
+
+polygon :: PTI
+polygon = mkPTI LibPQ.Binary 604 (Just 1027)
+
+record :: PTI
+record = mkPTI LibPQ.Binary 2249 (Just 2287)
+
+refcursor :: PTI
+refcursor = mkPTI LibPQ.Binary 1790 (Just 2201)
+
+regclass :: PTI
+regclass = mkPTI LibPQ.Binary 2205 (Just 2210)
+
+regconfig :: PTI
+regconfig = mkPTI LibPQ.Binary 3734 (Just 3735)
+
+regdictionary :: PTI
+regdictionary = mkPTI LibPQ.Binary 3769 (Just 3770)
+
+regoper :: PTI
+regoper = mkPTI LibPQ.Binary 2203 (Just 2208)
+
+regoperator :: PTI
+regoperator = mkPTI LibPQ.Binary 2204 (Just 2209)
+
+regproc :: PTI
+regproc = mkPTI LibPQ.Binary 24 (Just 1008)
+
+regprocedure :: PTI
+regprocedure = mkPTI LibPQ.Binary 2202 (Just 2207)
+
+regtype :: PTI
+regtype = mkPTI LibPQ.Binary 2206 (Just 2211)
+
+reltime :: PTI
+reltime = mkPTI LibPQ.Binary 703 (Just 1024)
+
+text :: PTI
+text = mkPTI LibPQ.Binary 25 (Just 1009)
+
+tid :: PTI
+tid = mkPTI LibPQ.Binary 27 (Just 1010)
+
+time :: PTI
+time = mkPTI LibPQ.Binary 1083 (Just 1183)
+
+timestamp :: PTI
+timestamp = mkPTI LibPQ.Binary 1114 (Just 1115)
+
+timestamptz :: PTI
+timestamptz = mkPTI LibPQ.Binary 1184 (Just 1185)
+
+timetz :: PTI
+timetz = mkPTI LibPQ.Binary 1266 (Just 1270)
+
+tinterval :: PTI
+tinterval = mkPTI LibPQ.Binary 704 (Just 1025)
+
+tsquery :: PTI
+tsquery = mkPTI LibPQ.Binary 3615 (Just 3645)
+
+tsrange :: PTI
+tsrange = mkPTI LibPQ.Binary 3908 (Just 3909)
+
+tstzrange :: PTI
+tstzrange = mkPTI LibPQ.Binary 3910 (Just 3911)
+
+tsvector :: PTI
+tsvector = mkPTI LibPQ.Binary 3614 (Just 3643)
+
+txid_snapshot :: PTI
+txid_snapshot = mkPTI LibPQ.Binary 2970 (Just 2949)
+
+textUnknown :: PTI
+textUnknown = mkPTI LibPQ.Text 705 (Just 705)
+
+binaryUnknown :: PTI
+binaryUnknown = mkPTI LibPQ.Binary 705 (Just 705)
+
+uuid :: PTI
+uuid = mkPTI LibPQ.Binary 2950 (Just 2951)
+
+varbit :: PTI
+varbit = mkPTI LibPQ.Binary 1562 (Just 1563)
+
+varchar :: PTI
+varchar = mkPTI LibPQ.Binary 1043 (Just 1015)
+
+void :: PTI
+void = mkPTI LibPQ.Binary 2278 Nothing
+
+xid :: PTI
+xid = mkPTI LibPQ.Binary 28 (Just 1011)
+
+xml :: PTI
+xml = mkPTI LibPQ.Binary 142 (Just 143)
diff --git a/library/Hasql/Prelude.hs b/library/Hasql/Prelude.hs
--- a/library/Hasql/Prelude.hs
+++ b/library/Hasql/Prelude.hs
@@ -34,8 +34,8 @@
 import Data.Bits as Exports
 import Data.Bool as Exports
 import Data.ByteString as Exports (ByteString)
-import qualified Data.ByteString.Builder
-import qualified Data.ByteString.Lazy
+import Data.ByteString.Builder qualified
+import Data.ByteString.Lazy qualified
 import Data.Char as Exports
 import Data.Coerce as Exports
 import Data.Complex as Exports
@@ -68,8 +68,8 @@
 import Data.Semigroup as Exports hiding (First (..), Last (..))
 import Data.String as Exports
 import Data.Text as Exports (Text)
-import qualified Data.Text.Lazy
-import qualified Data.Text.Lazy.Builder
+import Data.Text.Lazy qualified
+import Data.Text.Lazy.Builder qualified
 import Data.Time as Exports
 import Data.Traversable as Exports
 import Data.Tuple as Exports
diff --git a/library/Hasql/PreparedStatementRegistry.hs b/library/Hasql/PreparedStatementRegistry.hs
--- a/library/Hasql/PreparedStatementRegistry.hs
+++ b/library/Hasql/PreparedStatementRegistry.hs
@@ -6,8 +6,8 @@
   )
 where
 
-import qualified ByteString.StrictBuilder as B
-import qualified Data.HashTable.IO as A
+import ByteString.StrictBuilder qualified as B
+import Data.HashTable.IO qualified as A
 import Hasql.Prelude hiding (lookup)
 
 data PreparedStatementRegistry
diff --git a/library/Hasql/Session/Core.hs b/library/Hasql/Session/Core.hs
--- a/library/Hasql/Session/Core.hs
+++ b/library/Hasql/Session/Core.hs
@@ -1,14 +1,14 @@
 module Hasql.Session.Core where
 
-import qualified Hasql.Connection.Core as Connection
-import qualified Hasql.Decoders.Result as Decoders.Result
-import qualified Hasql.Decoders.Results as Decoders.Results
-import qualified Hasql.Encoders.All as Encoders
-import qualified Hasql.Encoders.Params as Encoders.Params
+import Hasql.Connection.Core qualified as Connection
+import Hasql.Decoders.Result qualified as Decoders.Result
+import Hasql.Decoders.Results qualified as Decoders.Results
+import Hasql.Encoders.All qualified as Encoders
+import Hasql.Encoders.Params qualified as Encoders.Params
 import Hasql.Errors
-import qualified Hasql.IO as IO
+import Hasql.IO qualified as IO
 import Hasql.Prelude
-import qualified Hasql.Statement as Statement
+import Hasql.Statement qualified as Statement
 
 -- |
 -- A batch of actions to be executed in the context of a database connection.
diff --git a/library/Hasql/Settings.hs b/library/Hasql/Settings.hs
--- a/library/Hasql/Settings.hs
+++ b/library/Hasql/Settings.hs
@@ -1,8 +1,8 @@
 module Hasql.Settings where
 
-import qualified Data.ByteString as B
-import qualified Data.ByteString.Builder as BB
-import qualified Data.ByteString.Lazy as BL
+import Data.ByteString qualified as B
+import Data.ByteString.Builder qualified as BB
+import Data.ByteString.Lazy qualified as BL
 import Hasql.Prelude
 
 -- |
diff --git a/library/Hasql/Statement.hs b/library/Hasql/Statement.hs
--- a/library/Hasql/Statement.hs
+++ b/library/Hasql/Statement.hs
@@ -12,13 +12,14 @@
   )
 where
 
-import qualified Hasql.Decoders as Decoders
-import qualified Hasql.Decoders.All as Decoders
-import qualified Hasql.Encoders as Encoders
+import Hasql.Decoders qualified as Decoders
+import Hasql.Decoders.All qualified as Decoders
+import Hasql.Encoders qualified as Encoders
 import Hasql.Prelude
 
 -- |
--- Specification of a strictly single-statement query, which can be parameterized and prepared, encapsulating the mapping of parameters and results.
+-- Specification of a strictly single-statement query, which can be parameterized and prepared.
+-- It encapsulates the mapping of parameters and results in association with an SQL template.
 --
 -- Following is an example of a declaration of a prepared statement with its associated codecs.
 --
@@ -38,7 +39,7 @@
 --
 -- The statement above accepts a product of two parameters of type 'Int64'
 -- and produces a single result of type 'Int64'.
-data Statement a b
+data Statement params result
   = Statement
       -- | SQL template.
       --
@@ -50,9 +51,9 @@
       -- the value encoders are specified in the parameters encoder.
       ByteString
       -- | Parameters encoder.
-      (Encoders.Params a)
+      (Encoders.Params params)
       -- | Decoder of result.
-      (Decoders.Result b)
+      (Decoders.Result result)
       -- | Flag, determining whether it should be prepared.
       --
       -- Set it to 'True' if your application has a limited amount of queries and doesn't generate the SQL dynamically.
@@ -63,7 +64,7 @@
       -- It should be noted that starting from version @1.21.0@ @pgbouncer@ now does provide support for prepared statements.
       Bool
 
-instance Functor (Statement a) where
+instance Functor (Statement params) where
   {-# INLINE fmap #-}
   fmap = rmap
 
@@ -97,7 +98,7 @@
 --       "insert into location (id, x, y) select * from unnest ($1, $2, $3)"
 --     encoder =
 --       Data.Vector.'Data.Vector.unzip3' '>$<'
---         Contravariant.Extras.'Contravariant.Extras.contrazip3'
+--         Contravariant.Extras.contrazip3
 --           (Encoders.'Encoders.param' $ Encoders.'Encoders.nonNullable' $ Encoders.'Encoders.foldableArray' $ Encoders.'Encoders.nonNullable' Encoders.'Encoders.uuid')
 --           (Encoders.'Encoders.param' $ Encoders.'Encoders.nonNullable' $ Encoders.'Encoders.foldableArray' $ Encoders.'Encoders.nonNullable' Encoders.'Encoders.float8')
 --           (Encoders.'Encoders.param' $ Encoders.'Encoders.nonNullable' $ Encoders.'Encoders.foldableArray' $ Encoders.'Encoders.nonNullable' Encoders.'Encoders.float8')
diff --git a/profiling/Main.hs b/profiling/Main.hs
--- a/profiling/Main.hs
+++ b/profiling/Main.hs
@@ -1,10 +1,10 @@
 module Main where
 
-import qualified Data.Vector as F
-import qualified Hasql.Connection as A
-import qualified Hasql.Decoders as D
-import qualified Hasql.Session as B
-import qualified Hasql.Statement as C
+import Data.Vector qualified as F
+import Hasql.Connection qualified as A
+import Hasql.Decoders qualified as D
+import Hasql.Session qualified as B
+import Hasql.Statement qualified as C
 import Prelude
 
 main :: IO ()
diff --git a/tasty/Main.hs b/tasty/Main.hs
--- a/tasty/Main.hs
+++ b/tasty/Main.hs
@@ -1,14 +1,14 @@
 module Main where
 
 import Contravariant.Extras
-import qualified Hasql.Decoders as Decoders
-import qualified Hasql.Encoders as Encoders
-import qualified Hasql.Session as Session
-import qualified Hasql.Statement as Statement
-import qualified Main.Connection as Connection
-import qualified Main.DSL as DSL
+import Hasql.Decoders qualified as Decoders
+import Hasql.Encoders qualified as Encoders
+import Hasql.Session qualified as Session
+import Hasql.Statement qualified as Statement
+import Hasql.TestingUtils.TestingDsl qualified as Session
+import Main.Connection qualified as Connection
 import Main.Prelude hiding (assert)
-import qualified Main.Statements as Statements
+import Main.Statements qualified as Statements
 import Test.QuickCheck.Instances ()
 import Test.Tasty
 import Test.Tasty.HUnit
@@ -136,19 +136,19 @@
                   assertEqual (show x) (Right (Right ((1, True), ("hello", 3)))) x,
         testGroup "unknownEnum"
           $ [ testCase "" $ do
-                res <- DSL.session $ do
+                res <- Session.runSessionOnLocalDb $ do
                   let statement =
                         Statement.Statement sql mempty Decoders.noResult True
                         where
                           sql =
                             "drop type if exists mood"
-                   in DSL.statement () statement
+                   in Session.statement () statement
                   let statement =
                         Statement.Statement sql mempty Decoders.noResult True
                         where
                           sql =
                             "create type mood as enum ('sad', 'ok', 'happy')"
-                   in DSL.statement () statement
+                   in Session.statement () statement
                   let statement =
                         Statement.Statement sql encoder decoder True
                         where
@@ -158,7 +158,7 @@
                             (Decoders.singleRow ((Decoders.column . Decoders.nonNullable) (Decoders.enum (Just . id))))
                           encoder =
                             Encoders.param (Encoders.nonNullable (Encoders.unknownEnum id))
-                   in DSL.statement "ok" statement
+                   in Session.statement "ok" statement
 
                 assertEqual "" (Right "ok") res
             ],
@@ -301,12 +301,12 @@
                     s <- Session.statement (1, 1) sumStatement
                     Session.sql "end;"
                     return s
-             in DSL.session session >>= \x -> assertEqual (show x) (Right 2) x,
+             in Session.runSessionOnLocalDb session >>= \x -> assertEqual (show x) (Right 2) x,
         testCase "Executing the same query twice"
           $ pure (),
         testCase "Interval Encoding"
           $ let actualIO =
-                  DSL.session $ do
+                  Session.runSessionOnLocalDb $ do
                     let statement =
                           Statement.Statement sql encoder decoder True
                           where
@@ -316,11 +316,11 @@
                               (Decoders.singleRow ((Decoders.column . Decoders.nonNullable) (Decoders.bool)))
                             encoder =
                               Encoders.param (Encoders.nonNullable (Encoders.interval))
-                     in DSL.statement (10 :: DiffTime) statement
+                     in Session.statement (10 :: DiffTime) statement
              in actualIO >>= \x -> assertEqual (show x) (Right True) x,
         testCase "Interval Decoding"
           $ let actualIO =
-                  DSL.session $ do
+                  Session.runSessionOnLocalDb $ do
                     let statement =
                           Statement.Statement sql encoder decoder True
                           where
@@ -330,11 +330,11 @@
                               (Decoders.singleRow ((Decoders.column . Decoders.nonNullable) (Decoders.interval)))
                             encoder =
                               Encoders.noParams
-                     in DSL.statement () statement
+                     in Session.statement () statement
              in actualIO >>= \x -> assertEqual (show x) (Right (10 :: DiffTime)) x,
         testCase "Interval Encoding/Decoding"
           $ let actualIO =
-                  DSL.session $ do
+                  Session.runSessionOnLocalDb $ do
                     let statement =
                           Statement.Statement sql encoder decoder True
                           where
@@ -344,23 +344,23 @@
                               (Decoders.singleRow ((Decoders.column . Decoders.nonNullable) (Decoders.interval)))
                             encoder =
                               Encoders.param (Encoders.nonNullable (Encoders.interval))
-                     in DSL.statement (10 :: DiffTime) statement
+                     in Session.statement (10 :: DiffTime) statement
              in actualIO >>= \x -> assertEqual (show x) (Right (10 :: DiffTime)) x,
         testCase "Unknown"
           $ let actualIO =
-                  DSL.session $ do
+                  Session.runSessionOnLocalDb $ do
                     let statement =
                           Statement.Statement sql mempty Decoders.noResult True
                           where
                             sql =
                               "drop type if exists mood"
-                     in DSL.statement () statement
+                     in Session.statement () statement
                     let statement =
                           Statement.Statement sql mempty Decoders.noResult True
                           where
                             sql =
                               "create type mood as enum ('sad', 'ok', 'happy')"
-                     in DSL.statement () statement
+                     in Session.statement () statement
                     let statement =
                           Statement.Statement sql encoder decoder True
                           where
@@ -370,23 +370,23 @@
                               (Decoders.singleRow ((Decoders.column . Decoders.nonNullable) (Decoders.bool)))
                             encoder =
                               Encoders.param (Encoders.nonNullable (Encoders.unknown))
-                     in DSL.statement "ok" statement
+                     in Session.statement "ok" statement
              in actualIO >>= assertEqual "" (Right True),
         testCase "Textual Unknown"
           $ let actualIO =
-                  DSL.session $ do
+                  Session.runSessionOnLocalDb $ do
                     let statement =
                           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
+                     in Session.statement () statement
                     let statement =
                           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;"
-                     in DSL.statement () statement
+                     in Session.statement () statement
                     let statement =
                           Statement.Statement sql encoder decoder True
                           where
@@ -396,23 +396,23 @@
                               (Decoders.singleRow ((Decoders.column . Decoders.nonNullable) (Decoders.text)))
                             encoder =
                               contramany (Encoders.param (Encoders.nonNullable (Encoders.unknown)))
-                     in DSL.statement ["1", "2", "4", "5", "6"] statement
+                     in Session.statement ["1", "2", "4", "5", "6"] statement
              in actualIO >>= assertEqual "" (Right "3456"),
         testCase "Enum"
           $ let actualIO =
-                  DSL.session $ do
+                  Session.runSessionOnLocalDb $ do
                     let statement =
                           Statement.Statement sql mempty Decoders.noResult True
                           where
                             sql =
                               "drop type if exists mood"
-                     in DSL.statement () statement
+                     in Session.statement () statement
                     let statement =
                           Statement.Statement sql mempty Decoders.noResult True
                           where
                             sql =
                               "create type mood as enum ('sad', 'ok', 'happy')"
-                     in DSL.statement () statement
+                     in Session.statement () statement
                     let statement =
                           Statement.Statement sql encoder decoder True
                           where
@@ -422,13 +422,13 @@
                               (Decoders.singleRow ((Decoders.column . Decoders.nonNullable) (Decoders.enum (Just . id))))
                             encoder =
                               Encoders.param (Encoders.nonNullable ((Encoders.enum id)))
-                     in DSL.statement "ok" statement
+                     in Session.statement "ok" statement
              in actualIO >>= assertEqual "" (Right "ok"),
         testCase "The same prepared statement used on different types"
           $ let actualIO =
-                  DSL.session $ do
+                  Session.runSessionOnLocalDb $ do
                     let effect1 =
-                          DSL.statement "ok" statement
+                          Session.statement "ok" statement
                           where
                             statement =
                               Statement.Statement sql encoder decoder True
@@ -440,7 +440,7 @@
                                 decoder =
                                   (Decoders.singleRow ((Decoders.column . Decoders.nonNullable) (Decoders.text)))
                         effect2 =
-                          DSL.statement 1 statement
+                          Session.statement 1 statement
                           where
                             statement =
                               Statement.Statement sql encoder decoder True
@@ -456,26 +456,26 @@
         testCase "Affected rows counting"
           $ replicateM_ 13
           $ let actualIO =
-                  DSL.session $ do
+                  Session.runSessionOnLocalDb $ do
                     dropTable
                     createTable
                     replicateM_ 100 insertRow
                     deleteRows <* dropTable
                   where
                     dropTable =
-                      DSL.statement ()
+                      Session.statement ()
                         $ Statements.plain
                         $ "drop table if exists a"
                     createTable =
-                      DSL.statement ()
+                      Session.statement ()
                         $ Statements.plain
                         $ "create table a (id bigserial not null, name varchar not null, primary key (id))"
                     insertRow =
-                      DSL.statement ()
+                      Session.statement ()
                         $ Statements.plain
                         $ "insert into a (name) values ('a')"
                     deleteRows =
-                      DSL.statement () $ Statement.Statement sql mempty decoder False
+                      Session.statement () $ Statement.Statement sql mempty decoder False
                       where
                         sql =
                           "delete from a"
@@ -484,16 +484,16 @@
              in actualIO >>= assertEqual "" (Right 100),
         testCase "Result of an auto-incremented column"
           $ let actualIO =
-                  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" 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"
+                  Session.runSessionOnLocalDb $ do
+                    Session.statement () $ Statements.plain $ "drop table if exists a"
+                    Session.statement () $ Statements.plain $ "create table a (id serial not null, v char not null, primary key (id))"
+                    id1 <- Session.statement () $ Statement.Statement "insert into a (v) values ('a') returning id" mempty (Decoders.singleRow ((Decoders.column . Decoders.nonNullable) Decoders.int4)) False
+                    id2 <- Session.statement () $ Statement.Statement "insert into a (v) values ('b') returning id" mempty (Decoders.singleRow ((Decoders.column . Decoders.nonNullable) Decoders.int4)) False
+                    Session.statement () $ Statements.plain $ "drop table if exists a"
                     pure (id1, id2)
              in assertEqual "" (Right (1, 2)) =<< actualIO,
         testCase "List decoding"
           $ let actualIO =
-                  DSL.session $ DSL.statement () $ Statements.selectList
+                  Session.runSessionOnLocalDb $ Session.statement () $ Statements.selectList
              in assertEqual "" (Right [(1, 2), (3, 4), (5, 6)]) =<< actualIO
       ]
diff --git a/tasty/Main/Connection.hs b/tasty/Main/Connection.hs
--- a/tasty/Main/Connection.hs
+++ b/tasty/Main/Connection.hs
@@ -1,6 +1,6 @@
 module Main.Connection where
 
-import qualified Hasql.Connection as HC
+import Hasql.Connection qualified as HC
 import Main.Prelude
 
 with :: (HC.Connection -> IO a) -> IO (Either HC.ConnectionError a)
diff --git a/tasty/Main/DSL.hs b/tasty/Main/DSL.hs
deleted file mode 100644
--- a/tasty/Main/DSL.hs
+++ /dev/null
@@ -1,42 +0,0 @@
-module Main.DSL
-  ( Session,
-    SessionError (..),
-    session,
-    Hasql.Session.statement,
-    Hasql.Session.sql,
-  )
-where
-
-import qualified Hasql.Connection as HC
-import qualified Hasql.Session
-import Main.Prelude
-
-type Session =
-  Hasql.Session.Session
-
-data SessionError
-  = ConnectionError (HC.ConnectionError)
-  | SessionError (Hasql.Session.QueryError)
-  deriving (Show, Eq)
-
-session :: Session a -> IO (Either SessionError a)
-session session =
-  runExceptT $ acquire >>= \connection -> use connection <* release connection
-  where
-    acquire =
-      ExceptT $ fmap (mapLeft ConnectionError) $ HC.acquire settings
-      where
-        settings =
-          HC.settings host port user password database
-          where
-            host = "localhost"
-            port = 5432
-            user = "postgres"
-            password = "postgres"
-            database = "postgres"
-    use connection =
-      ExceptT
-        $ fmap (mapLeft SessionError)
-        $ Hasql.Session.run session connection
-    release connection =
-      lift $ HC.release connection
diff --git a/tasty/Main/Statements.hs b/tasty/Main/Statements.hs
--- a/tasty/Main/Statements.hs
+++ b/tasty/Main/Statements.hs
@@ -1,7 +1,7 @@
 module Main.Statements where
 
-import qualified Hasql.Decoders as HD
-import qualified Hasql.Statement as HQ
+import Hasql.Decoders qualified as HD
+import Hasql.Statement qualified as HQ
 import Main.Prelude
 
 plain :: ByteString -> HQ.Statement () ()
diff --git a/testing-utils/Hasql/TestingUtils/Constants.hs b/testing-utils/Hasql/TestingUtils/Constants.hs
new file mode 100644
--- /dev/null
+++ b/testing-utils/Hasql/TestingUtils/Constants.hs
@@ -0,0 +1,13 @@
+module Hasql.TestingUtils.Constants where
+
+import Hasql.Connection qualified as Connection
+
+localConnectionSettings :: Connection.Settings
+localConnectionSettings =
+  Connection.settings host port user password database
+  where
+    host = "localhost"
+    port = 5432
+    user = "postgres"
+    password = "postgres"
+    database = "postgres"
diff --git a/testing-utils/Hasql/TestingUtils/TestingDsl.hs b/testing-utils/Hasql/TestingUtils/TestingDsl.hs
new file mode 100644
--- /dev/null
+++ b/testing-utils/Hasql/TestingUtils/TestingDsl.hs
@@ -0,0 +1,37 @@
+module Hasql.TestingUtils.TestingDsl
+  ( Session.Session,
+    SessionError (..),
+    Session.QueryError (..),
+    Session.CommandError (..),
+    runSessionOnLocalDb,
+    runStatementInSession,
+  )
+where
+
+import Hasql.Connection qualified as Connection
+import Hasql.Session qualified as Session
+import Hasql.Statement qualified as Statement
+import Hasql.TestingUtils.Constants qualified as Constants
+import Prelude
+
+data SessionError
+  = ConnectionError (Connection.ConnectionError)
+  | SessionError (Session.QueryError)
+  deriving (Show, Eq)
+
+runSessionOnLocalDb :: Session.Session a -> IO (Either SessionError a)
+runSessionOnLocalDb session =
+  runExceptT $ acquire >>= \connection -> use connection <* release connection
+  where
+    acquire =
+      ExceptT $ fmap (mapLeft ConnectionError) $ Connection.acquire Constants.localConnectionSettings
+    use connection =
+      ExceptT
+        $ fmap (mapLeft SessionError)
+        $ Session.run session connection
+    release connection =
+      lift $ Connection.release connection
+
+runStatementInSession :: Statement.Statement a b -> a -> Session.Session b
+runStatementInSession statement params =
+  Session.statement params statement
diff --git a/threads-test/Main.hs b/threads-test/Main.hs
--- a/threads-test/Main.hs
+++ b/threads-test/Main.hs
@@ -1,8 +1,8 @@
 module Main where
 
-import qualified Hasql.Connection
-import qualified Hasql.Session
-import qualified Main.Statements as Statements
+import Hasql.Connection qualified
+import Hasql.Session qualified
+import Main.Statements qualified as Statements
 import Prelude
 
 main :: IO ()
diff --git a/threads-test/Main/Statements.hs b/threads-test/Main/Statements.hs
--- a/threads-test/Main/Statements.hs
+++ b/threads-test/Main/Statements.hs
@@ -1,7 +1,7 @@
 module Main.Statements where
 
-import qualified Hasql.Decoders as D
-import qualified Hasql.Encoders as E
+import Hasql.Decoders qualified as D
+import Hasql.Encoders qualified as E
 import Hasql.Statement
 import Prelude
 
