diff --git a/CHANGELOG.md b/CHANGELOG.md
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,18 @@
 
 ## [Unreleased]
 
+## [0.2.0.0] - 22.09.2026
+
+### Changed
+
+- Support `bluefin` versions `0.2.7 && < 0.6` in [#4](https://github.com/fpringle/bluefin-postgresql/pull/4).
+- Support `bluefin < 0.11` in [#8](https://github.com/fpringle/bluefin-postgresql/pull/8).
+
+### Added
+
+- Dynamic `PostgreSQL` effect in [#7](https://github.com/fpringle/bluefin-postgresql/pull/7).
+- Support OpenTelemetry instrumentation in [#11](https://github.com/fpringle/bluefin-postgresql/pull/11).
+
 ## [0.1.0.0] - 27.02.2026
 
 ### Added
@@ -16,5 +28,6 @@
 - Reasonably detailed READMEs.
 - CI that builds and tests the packages for each version of GHC in the `tested-with` field.
 
-[unreleased]: https://github.com/fpringle/bluefin-postgresql/compare/bluefin-postgresql-0.1.0.0...HEAD
+[unreleased]: https://github.com/fpringle/bluefin-postgresql/compare/bluefin-postgresql-0.2.0.0...HEAD
+[0.2.0.0]: https://github.com/fpringle/bluefin-postgresql/compare/bluefin-postgresql-0.1.0.0...bluefin-postgresql-0.2.0.0
 [0.1.0.0]: https://github.com/fpringle/bluefin-postgresql/releases/tag/bluefin-postgresql-0.1.0.0
diff --git a/README.md b/README.md
--- a/README.md
+++ b/README.md
@@ -1,8 +1,10 @@
 # bluefin-postgresql
 
-This package provides a `bluefin` effect for [postgresql-simple](https://hackage.haskell.org/package/postgresql-simple)'s `Connection` type.
+This package provides `bluefin` effects for [postgresql-simple](https://hackage.haskell.org/package/postgresql-simple)'s `Connection` type.
 
-It defines a dynamic effect to allow effectful functions to use a `Connection`, without worrying about where that `Connection` comes from.
+It defines:
+- a dynamic `WithConnection` effect to allow effectful functions to use a `Connection`, without worrying about where that `Connection` comes from.
+- a dynamic `PostgreSQL` effect ro run database operations from `postgresql-simple`.
 
 For a higher-level effect library using [Opaleye](https://hackage.haskell.org/package/opaleye), see [bluefin-opaleye](https://github.com/fpringle/bluefin-postgresql/blob/main/bluefin-opaleye#readme).
 
@@ -25,21 +27,19 @@
   effIO ioe $ PSQL.query conn "select * from users where first_name in ?" $ PSQL.Only $ PSQL.In ["Anna", "Boris", "Carla"]
 ```
 
-In fact, for convenience we also define lifted versions of all of the query/execute
-functions from `postgresql-simple`, so we can completely forget about `Connection` and rewrite the above to:
+The `PostgreSQL` effect lets us completely forget about `Connection` and rewrite the above to:
 
 ```haskell
 
 import Bluefin.PostgreSQL
 
 insertAndList ::
-  (e :> es, e1 :> es) =>
-  WithConnection e ->
-  IOE e1 ->
+  (e :> es) =>
+  PostgreSQL e ->
   Eff es [User]
-insertAndList wc ioe = do
-  BP.execute wc ioe "insert into users (first_name) values (?)" ["Nuala"]
-  BP.query wc ioe "select * from users where first_name in ?" $ PSQL.Only $ PSQL.In ["Anna", "Boris", "Carla"]
+insertAndList psql = do
+  BP.execute psql "insert into users (first_name) values (?)" ["Nuala"]
+  BP.query psql "select * from users where first_name in ?" $ PSQL.Only $ PSQL.In ["Anna", "Boris", "Carla"]
 ```
 
 The same goes for other functions:
@@ -47,26 +47,41 @@
 ```haskell
 -- use a transaction
 insertAndListCarefully ::
-  (e :> es, e1 :> es) =>
-  WithConnection e ->
-  IOE e1 ->
+  (e :> es) =>
+  PostgreSQL e ->
   Eff es [User]
-insertAndListCarefully wc ioe = BP.withTransaction wc ioe $ insertAndList wc ioe
+insertAndListCarefully psql = BP.withTransaction psql $ insertAndList psql
 
 -- stream + fold over results (in Eff)
 countUsersIneffeciently ::
   (e :> es, e1 :> es) =>
-  WithConnection e ->
+  PostgreSQL e ->
   IOE e1 ->
   Eff es Int
-countUsersIneffeciently wc ioe =
-  BP.fold_ wc ioe "select * from users" 0 $ \acc (row :: User) -> do
+countUsersIneffeciently psql ioe =
+  BP.fold_ psql "select * from users" 0 $ \acc (row :: User) -> do
     effIO ioe . putStrLn $ "User: " <> show row
     pure $ acc + 1
 ```
 
 ## Interpreters
 
+In order to discharge the `PostgreSQL` effect we use the `WithConnection` effect:
+
+```haskell
+dischargePostgreSQL :: (e :> es, e1 :> es) => WithConnection e -> IOE e1 -> Eff es [User]
+dischargePostgreSQL withConn ioe =
+  runPostgreSQL withConn ioe $ \psql -> insertAndListCarefully psql
+```
+
+Alternatively we can use the OpenTelemetry support provided by [hs-opentelemetry-instrumentation-postgresql-simple](https://hackage-content.haskell.org/package/hs-opentelemetry-instrumentation-postgresql-simple/docs/OpenTelemetry-Instrumentation-PostgresqlSimple.html) (note that this requires enabling the `enable-opentel` cabal flag):
+
+```haskell
+dischargePostgreSQLUsingOpenTelemetry :: (e :> es, e1 :> es) => WithConnection e -> IOE e1 -> Eff es [User]
+dischargePostgreSQLUsingOpenTelemetry withConn ioe =
+  runPostgreSQLOT withConn ioe $ \psql -> insertAndListCarefully psql
+```
+
 The simplest way of running the `WithConnection` effect is by just providing a `Connection`, which we can get in the normal ways:
 
 ```haskell
@@ -77,13 +92,16 @@
 usingConnection =
   runEff $ \ioe ->
     bracket (effIO ioe $ PSQL.connectPostgreSQL "") (effIO ioe . PSQL.close) $ \conn ->
-      BP.runWithConnection conn $ \wc -> insertAndListCarefully wc ioe >>= effIO ioe . print
+      BP.runWithConnection conn $ \wc -> 
+        BP.runPostgreSQL wc ioe $ \psql -> 
+          insertAndListCarefully wc ioe >>= effIO ioe . print
 
 usingConnectInfo :: IO ()
 usingConnectInfo =
   runEff $ \ioe ->
     BP.runWithConnectInfo ioe PSQL.defaultConnectInfo $ \wc ->
-      insertAndListCarefully wc ioe >>= effIO ioe . print
+      BP.runPostgreSQL wc ioe $ \psql -> 
+        insertAndListCarefully psql >>= effIO ioe . print
 ```
 
 Alternatively, we can use a connection pool (from [resource-pool](https://hackage.haskell.org/package/resource-pool)
diff --git a/bluefin-postgresql.cabal b/bluefin-postgresql.cabal
--- a/bluefin-postgresql.cabal
+++ b/bluefin-postgresql.cabal
@@ -1,6 +1,6 @@
 cabal-version:      3.0
 name:               bluefin-postgresql
-version:            0.1.0.0
+version:            0.2.0.0
 synopsis:
   bluefin support for mid-level PostgreSQL operations.
 description:
@@ -17,11 +17,9 @@
                     CHANGELOG.md
 
 tested-with:
-    GHC == 8.10.7
-  , GHC == 9.0.2
+    GHC == 9.0.2
   , GHC == 9.2.4
   , GHC == 9.2.8
-  , GHC == 9.4.2
   , GHC == 9.4.5
   , GHC == 9.6.1
   , GHC == 9.6.7
@@ -35,22 +33,35 @@
   default: True
   manual: False
 
+flag enable-otel
+  description: Enable OpenTelemetry instrumentation support using
+               hs-opentelemetry-instrumentation-postgresql-simple.
+  default: False
+  manual: True
+
 common warnings
   ghc-options: -Wall -Wno-unused-do-bind -Wunused-packages
 
   if flag(enable-pool)
     cpp-options: -DPOOL
 
+  if flag(enable-otel)
+    cpp-options: -DOTEL
+
 common deps
   build-depends:
     , base >= 4 && < 5
-    , bluefin >= 0.0.11 && < 0.0.18
+    , bluefin >= 0.2.7 && < 0.11
     , postgresql-simple >= 0.7 && < 0.8
 
   if flag(enable-pool)
     build-depends:
       , unliftio-pool >= 0.4.1 && < 0.5
 
+  if flag(enable-otel)
+    build-depends:
+      , hs-opentelemetry-instrumentation-postgresql-simple >= 1.0 && < 1.1
+
 common extensions
   default-extensions:
     DataKinds
@@ -70,6 +81,7 @@
     , extensions
   exposed-modules:
       Bluefin.PostgreSQL
+      Bluefin.PostgreSQL.Effect
       Bluefin.PostgreSQL.Connection
   if flag(enable-pool)
     exposed-modules:
diff --git a/src/Bluefin/PostgreSQL.hs b/src/Bluefin/PostgreSQL.hs
--- a/src/Bluefin/PostgreSQL.hs
+++ b/src/Bluefin/PostgreSQL.hs
@@ -1,9 +1,10 @@
 {-# LANGUAGE CPP #-}
 
 module Bluefin.PostgreSQL
-  ( -- * Effect
+  ( -- * Effects
     WithConnection
   , withConnection
+  , PostgreSQL
 
     -- ** Interpreters
   , runWithConnection
@@ -12,6 +13,11 @@
   , runWithConnectionPool
 #endif
 
+  , runPostgreSQL
+#if OTEL
+  , runPostgreSQLOT
+#endif
+
     -- * Lifted versions of functions from Database.PostgreSQL.Simple
 
     -- ** Queries that return results
@@ -50,335 +56,8 @@
   )
 where
 
-import Data.Int (Int64)
-import qualified Database.PostgreSQL.Simple as PSQL
-import qualified Database.PostgreSQL.Simple.FromRow as PSQL
-import Bluefin.Eff
-import Bluefin.IO
 import Bluefin.PostgreSQL.Connection as Conn
-import GHC.Stack
+import Bluefin.PostgreSQL.Effect
 #if POOL
 import Bluefin.PostgreSQL.Connection.Pool as Pool
 #endif
-
--- | Lifted 'PSQL.query'.
-query ::
-  (HasCallStack, e :> es, e1 :> es, PSQL.ToRow q, PSQL.FromRow r) =>
-  WithConnection e ->
-  IOE e1 ->
-  PSQL.Query ->
-  q ->
-  Eff es [r]
-query wc ioe q row = withConnection wc $ \conn -> effIO ioe (PSQL.query conn q row)
-
-
--- | Lifted 'PSQL.query_'.
-query_ ::
-  (HasCallStack, e :> es, e1 :> es, PSQL.FromRow r) =>
-  WithConnection e ->
-  IOE e1 ->
-  PSQL.Query ->
-  Eff es [r]
-query_ wc ioe row = withConnection wc $ \conn -> effIO ioe (PSQL.query_ conn row)
-
--- | Lifted 'PSQL.queryWith'.
-queryWith ::
-  (HasCallStack, e :> es, e1 :> es, PSQL.ToRow q) =>
-  WithConnection e ->
-  IOE e1 ->
-  PSQL.RowParser r ->
-  PSQL.Query ->
-  q ->
-  Eff es [r]
-queryWith wc ioe parser q row =
-  withConnection wc $ \conn -> effIO ioe (PSQL.queryWith parser conn q row)
-
--- | Lifted 'PSQL.queryWith_'.
-queryWith_ ::
-  (HasCallStack, e :> es, e1 :> es) =>
-  WithConnection e ->
-  IOE e1 ->
-  PSQL.RowParser r ->
-  PSQL.Query ->
-  Eff es [r]
-queryWith_ wc ioe parser row =
-  withConnection wc $ \conn -> effIO ioe (PSQL.queryWith_ parser conn row)
-
--- | Lifted 'PSQL.execute'.
-execute ::
-  (HasCallStack, e :> es, e1 :> es, PSQL.ToRow q) =>
-  WithConnection e ->
-  IOE e1 ->
-  PSQL.Query ->
-  q ->
-  Eff es Int64
-execute wc ioe q row = withConnection wc $ \conn -> effIO ioe (PSQL.execute conn q row)
-
--- | Lifted 'PSQL.execute_'.
-execute_ ::
-  (HasCallStack, e :> es, e1 :> es) =>
-  WithConnection e ->
-  IOE e1 ->
-  PSQL.Query ->
-  Eff es Int64
-execute_ wc ioe row = withConnection wc $ \conn -> effIO ioe (PSQL.execute_ conn row)
-
--- | Lifted 'PSQL.executeMany'.
-executeMany ::
-  (HasCallStack, e :> es, e1 :> es, PSQL.ToRow q) =>
-  WithConnection e ->
-  IOE e1 ->
-  PSQL.Query ->
-  [q] ->
-  Eff es Int64
-executeMany wc ioe q rows = withConnection wc $ \conn -> effIO ioe (PSQL.executeMany conn q rows)
-
--- | Lifted 'PSQL.withTransaction'.
-withTransaction ::
-  (HasCallStack, e :> es, e1 :> es) => 
-  WithConnection e ->
-  IOE e1 ->
-  Eff es a -> 
-  Eff es a
-withTransaction wc ioe f =
-  unliftWithConn wc ioe $ \conn unlift ->
-    PSQL.withTransaction conn (unlift f)
-
--- | Lifted 'PSQL.withSavepoint'.
-withSavepoint ::
-  (HasCallStack, e :> es, e1 :> es) => 
-  WithConnection e ->
-  IOE e1 ->
-  Eff es a -> Eff es a
-withSavepoint wc ioe f =
-  unliftWithConn wc ioe $ \conn unlift ->
-    PSQL.withSavepoint conn (unlift f)
-
--- | Lifted 'PSQL.begin'.
-begin ::
-  (HasCallStack, e :> es, e1 :> es) => 
-  WithConnection e ->
-  IOE e1 ->
-  Eff es ()
-begin wc ioe = withConnection wc $ effIO ioe . PSQL.begin
-
--- | Lifted 'PSQL.commit'.
-commit ::
-  (HasCallStack, e :> es, e1 :> es) => 
-  WithConnection e ->
-  IOE e1 ->
-  Eff es ()
-commit wc ioe = withConnection wc $ effIO ioe . PSQL.commit
-
--- | Lifted 'PSQL.rollback'.
-rollback ::
-  (HasCallStack, e :> es, e1 :> es) => 
-  WithConnection e ->
-  IOE e1 ->
-  Eff es ()
-rollback wc ioe = withConnection wc $ effIO ioe . PSQL.rollback
-
-(...) :: (a -> b) -> (t1 -> t2 -> a) -> t1 -> t2 -> b
-unlift ... f = \a' row -> unlift $ f a' row
-
-unliftWithConn ::
-  (HasCallStack, e :> es, e1 :> es) =>
-  WithConnection e ->
-  IOE e1 ->
-  (PSQL.Connection -> (forall b. Eff es b -> IO b) -> IO a) ->
-  Eff es a
-unliftWithConn wc ioe f =
-  withConnection wc $ \conn ->
-    withEffToIO_ ioe $ \unlift ->
-      f conn unlift
-{-# INLINE unliftWithConn #-}
-
--- | Lifted 'PSQL.fold'.
-fold ::
-  (HasCallStack, e :> es, e1 :> es, PSQL.FromRow row, PSQL.ToRow params) =>
-  WithConnection e ->
-  IOE e1 ->
-  PSQL.Query ->
-  params ->
-  a ->
-  (a -> row -> Eff es a) ->
-  Eff es a
-fold wc ioe q params a f =
-  unliftWithConn wc ioe $ \conn unlift ->
-    PSQL.fold conn q params a (unlift ... f)
-
--- | Lifted 'PSQL.foldWithOptions'.
-foldWithOptions ::
-  (HasCallStack, e :> es, e1 :> es, PSQL.FromRow row, PSQL.ToRow params) =>
-  WithConnection e ->
-  IOE e1 ->
-  PSQL.FoldOptions ->
-  PSQL.Query ->
-  params ->
-  a ->
-  (a -> row -> Eff es a) ->
-  Eff es a
-foldWithOptions wc ioe opts q params a f =
-  unliftWithConn wc ioe $ \conn unlift ->
-    PSQL.foldWithOptions opts conn q params a (unlift ... f)
-
--- | Lifted 'PSQL.fold_'.
-fold_ ::
-  (HasCallStack, e :> es, e1 :> es, PSQL.FromRow row) =>
-  WithConnection e ->
-  IOE e1 ->
-  PSQL.Query ->
-  a ->
-  (a -> row -> Eff es a) ->
-  Eff es a
-fold_ wc ioe q a f =
-  unliftWithConn wc ioe $ \conn unlift ->
-    PSQL.fold_ conn q a (unlift ... f)
-
--- | Lifted 'PSQL.foldWithOptions_'.
-foldWithOptions_ ::
-  (HasCallStack, e :> es, e1 :> es, PSQL.FromRow row) =>
-  WithConnection e ->
-  IOE e1 ->
-  PSQL.FoldOptions ->
-  PSQL.Query ->
-  a ->
-  (a -> row -> Eff es a) ->
-  Eff es a
-foldWithOptions_ wc ioe opts q a f =
-  unliftWithConn wc ioe $ \conn unlift ->
-    PSQL.foldWithOptions_ opts conn q a (unlift ... f)
-
--- | Lifted 'PSQL.forEach'.
-forEach ::
-  (HasCallStack, e :> es, e1 :> es, PSQL.FromRow r, PSQL.ToRow q) =>
-  WithConnection e ->
-  IOE e1 ->
-  PSQL.Query ->
-  q ->
-  (r -> Eff es ()) ->
-  Eff es ()
-forEach wc ioe q row forR =
-  unliftWithConn wc ioe $ \conn unlift ->
-    PSQL.forEach conn q row (unlift . forR)
-
--- | Lifted 'PSQL.forEach_'.
-forEach_ ::
-  (HasCallStack, e :> es, e1 :> es, PSQL.FromRow r) =>
-  WithConnection e ->
-  IOE e1 ->
-  PSQL.Query ->
-  (r -> Eff es ()) ->
-  Eff es ()
-forEach_ wc ioe q forR =
-  unliftWithConn wc ioe $ \conn unlift ->
-    PSQL.forEach_ conn q (unlift . forR)
-
--- | Lifted 'PSQL.returning'.
-returning ::
-  (HasCallStack, e :> es, e1 :> es, PSQL.ToRow q, PSQL.FromRow r) =>
-  WithConnection e ->
-  IOE e1 ->
-  PSQL.Query ->
-  [q] ->
-  Eff es [r]
-returning wc ioe q rows = withConnection wc $ \conn -> effIO ioe $ PSQL.returning conn q rows
-
--- | Lifted 'PSQL.foldWith'.
-foldWith ::
-  (HasCallStack, e :> es, e1 :> es, PSQL.ToRow params) =>
-  WithConnection e ->
-  IOE e1 ->
-  PSQL.RowParser row ->
-  PSQL.Query ->
-  params ->
-  a ->
-  (a -> row -> Eff es a) ->
-  Eff es a
-foldWith wc ioe parser q params a f =
-  unliftWithConn wc ioe $ \conn unlift ->
-    PSQL.foldWith parser conn q params a (unlift ... f)
-
--- | Lifted 'PSQL.foldWithOptionsAndParser'.
-foldWithOptionsAndParser ::
-  (HasCallStack, e :> es, e1 :> es, PSQL.ToRow params) =>
-  WithConnection e ->
-  IOE e1 ->
-  PSQL.FoldOptions ->
-  PSQL.RowParser row ->
-  PSQL.Query ->
-  params ->
-  a ->
-  (a -> row -> Eff es a) ->
-  Eff es a
-foldWithOptionsAndParser wc ioe opts parser q params a f =
-  unliftWithConn wc ioe $ \conn unlift ->
-    PSQL.foldWithOptionsAndParser opts parser conn q params a (unlift ... f)
-
--- | Lifted 'PSQL.foldWith_'.
-foldWith_ ::
-  (HasCallStack, e :> es, e1 :> es) =>
-  WithConnection e ->
-  IOE e1 ->
-  PSQL.RowParser row ->
-  PSQL.Query ->
-  a ->
-  (a -> row -> Eff es a) ->
-  Eff es a
-foldWith_ wc ioe parser q a f =
-  unliftWithConn wc ioe $ \conn unlift ->
-    PSQL.foldWith_ parser conn q a (unlift ... f)
-
--- | Lifted 'PSQL.foldWithOptionsAndParser_'.
-foldWithOptionsAndParser_ ::
-  (HasCallStack, e :> es, e1 :> es) =>
-  WithConnection e ->
-  IOE e1 ->
-  PSQL.FoldOptions ->
-  PSQL.RowParser row ->
-  PSQL.Query ->
-  a ->
-  (a -> row -> Eff es a) ->
-  Eff es a
-foldWithOptionsAndParser_ wc ioe opts parser q a f =
-  unliftWithConn wc ioe $ \conn unlift ->
-    PSQL.foldWithOptionsAndParser_ opts parser conn q a (unlift ... f)
-
--- | Lifted 'PSQL.forEachWith'.
-forEachWith ::
-  (HasCallStack, e :> es, e1 :> es, PSQL.ToRow q) =>
-  WithConnection e ->
-  IOE e1 ->
-  PSQL.RowParser r ->
-  PSQL.Query ->
-  q ->
-  (r -> Eff es ()) ->
-  Eff es ()
-forEachWith wc ioe parser q row forR =
-  unliftWithConn wc ioe $ \conn unlift ->
-    PSQL.forEachWith parser conn q row (unlift . forR)
-
--- | Lifted 'PSQL.forEachWith_'.
-forEachWith_ ::
-  (HasCallStack, e :> es, e1 :> es) =>
-  WithConnection e ->
-  IOE e1 ->
-  PSQL.RowParser r ->
-  PSQL.Query ->
-  (r -> Eff es ()) ->
-  Eff es ()
-forEachWith_ wc ioe parser row forR =
-  unliftWithConn wc ioe $ \conn unlift ->
-    PSQL.forEachWith_ parser conn row (unlift . forR)
-
--- | Lifted 'PSQL.returningWith'.
-returningWith ::
-  (HasCallStack, e :> es, e1 :> es, PSQL.ToRow q) =>
-  WithConnection e ->
-  IOE e1 ->
-  PSQL.RowParser r ->
-  PSQL.Query ->
-  [q] ->
-  Eff es [r]
-returningWith wc ioe parser q rows =
-  withConnection wc $ \conn -> effIO ioe $ PSQL.returningWith parser conn q rows
diff --git a/src/Bluefin/PostgreSQL/Connection.hs b/src/Bluefin/PostgreSQL/Connection.hs
--- a/src/Bluefin/PostgreSQL/Connection.hs
+++ b/src/Bluefin/PostgreSQL/Connection.hs
@@ -1,3 +1,6 @@
+{-# LANGUAGE DerivingVia #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+
 module Bluefin.PostgreSQL.Connection
   ( -- * Effect
     WithConnection (..)
@@ -28,12 +31,16 @@
   { withConnectionImpl :: forall e' a. (PSQL.Connection -> Eff e' a) -> Eff (e' :& e) a
   -- ^ Use a 'PSQL.Connection' provided by an interpreter.
   }
+  deriving (Handle) via OneWayCoercibleHandle WithConnection
 
-instance Handle WithConnection where
-  mapHandle h =
-    MkWithConnection
-      { withConnectionImpl = useImplUnder . withConnectionImpl h
-      }
+mapHandleWithConnection :: (e :> es) => WithConnection e -> WithConnection es
+mapHandleWithConnection h =
+  MkWithConnection
+    { withConnectionImpl = useImplUnder . withConnectionImpl h
+    }
+
+instance (e :> es) => OneWayCoercible (WithConnection e) (WithConnection es) where
+  oneWayCoercibleImpl = oneWayCoercibleTrustMe mapHandleWithConnection
 
 -- | Use a 'PSQL.Connection' provided by an interpreter.
 withConnection :: (e :> es) => WithConnection e -> (PSQL.Connection -> Eff es a) -> Eff es a
diff --git a/src/Bluefin/PostgreSQL/Effect.hs b/src/Bluefin/PostgreSQL/Effect.hs
new file mode 100644
--- /dev/null
+++ b/src/Bluefin/PostgreSQL/Effect.hs
@@ -0,0 +1,1059 @@
+{-# LANGUAGE CPP #-}
+{-# LANGUAGE DerivingVia #-}
+{-# LANGUAGE MultiParamTypeClasses #-}
+{-# LANGUAGE RecordWildCards #-}
+
+module Bluefin.PostgreSQL.Effect
+  ( -- * Effect
+    PostgreSQL (..)
+
+    -- ** Interpreters
+  , runPostgreSQL
+#if OTEL
+  , runPostgreSQLOT
+#endif
+
+    -- * Lifted versions of functions from Database.PostgreSQL.Simple
+
+    -- ** Queries that return results
+  , query
+  , query_
+  , queryWith
+  , queryWith_
+
+    -- ** Statements that do not return results
+  , execute
+  , execute_
+  , executeMany
+
+    -- ** Transaction handling
+  , withTransaction
+  , withTransactionLevel
+  , PSQL.IsolationLevel (..)
+  , withTransactionMode
+  , PSQL.TransactionMode (..)
+  , PSQL.ReadWriteMode (..)
+  , withTransactionModeRetry
+  , withTransactionModeRetry'
+  , withTransactionSerializable
+  , withTransactionSerialisable
+  , withSavepoint
+  , begin
+  , commit
+  , rollback
+
+    -- ** Queries that stream results
+  , fold
+  , foldWithOptions
+  , fold_
+  , foldWithOptions_
+  , forEach
+  , forEach_
+  , returning
+  , foldWith
+  , foldWithOptionsAndParser
+  , foldWith_
+  , foldWithOptionsAndParser_
+  , forEachWith
+  , forEachWith_
+  , returningWith
+  )
+where
+
+import Bluefin.Compound
+import Bluefin.Eff
+import Bluefin.IO
+import Bluefin.PostgreSQL.Connection
+import qualified Control.Exception as E
+import Data.Int (Int64)
+import qualified Database.PostgreSQL.Simple as PSQL
+import qualified Database.PostgreSQL.Simple.FromRow as PSQL
+import qualified Database.PostgreSQL.Simple.Transaction as PSQL
+import GHC.Stack
+#if OTEL
+import qualified OpenTelemetry.Instrumentation.PostgresqlSimple as OT
+#endif
+
+-- | Dynamic effect representing all the Postgres operations we want to perform.
+data PostgreSQL (e :: Effects) = MkPostgreSQL
+  { queryImpl :: forall q r. (PSQL.ToRow q, PSQL.FromRow r) => PSQL.Query -> q -> Eff e [r]
+  -- ^ Lifted 'PSQL.query'.
+  , queryWithImpl :: forall q r. (PSQL.ToRow q) => PSQL.RowParser r -> PSQL.Query -> q -> Eff e [r]
+  -- ^ Lifted 'PSQL.queryWith'.
+  , query_Impl :: forall r. (PSQL.FromRow r) => PSQL.Query -> Eff e [r]
+  -- ^ Lifted 'PSQL.query_'.
+  , queryWith_Impl :: forall r. PSQL.RowParser r -> PSQL.Query -> Eff e [r]
+  -- ^ Lifted 'PSQL.queryWith_'.
+  , --
+
+    executeImpl :: forall q. (PSQL.ToRow q) => PSQL.Query -> q -> Eff e Int64
+  -- ^ Lifted 'PSQL.execute'.
+  , execute_Impl :: PSQL.Query -> Eff e Int64
+  -- ^ Lifted 'PSQL.execute_'.
+  , executeManyImpl :: forall q. (PSQL.ToRow q) => PSQL.Query -> [q] -> Eff e Int64
+  -- ^ Lifted 'PSQL.executeMany'.
+  , --
+
+    withTransactionImpl :: forall e' a. Eff e' a -> Eff (e' :& e) a
+  -- ^ Lifted 'PSQL.withTransaction'.
+  , withTransactionLevelImpl :: forall e' a. PSQL.IsolationLevel -> Eff e' a -> Eff (e' :& e) a
+  -- ^ Lifted 'PSQL.withTransactionLevel'.
+  , withTransactionModeImpl :: forall e' a. PSQL.TransactionMode -> Eff e' a -> Eff (e' :& e) a
+  -- ^ Lifted 'PSQL.withTransactionMode'.
+  , withTransactionModeRetryImpl :: forall e' a. PSQL.TransactionMode -> (PSQL.SqlError -> Bool) -> Eff e' a -> Eff (e' :& e) a
+  -- ^ Lifted 'PSQL.withTransactionModeRetry'.
+  , withTransactionModeRetry'Impl :: forall exc e' a. (E.Exception exc) => PSQL.TransactionMode -> (exc -> Bool) -> Eff e' a -> Eff (e' :& e) a
+  -- ^ Lifted 'PSQL.withTransactionModeRetry''.
+  , withTransactionSerializableImpl :: forall e' a. Eff e' a -> Eff (e' :& e) a
+  -- ^ Lifted 'PSQL.withTransactionSerializable'.
+  , withSavepointImpl :: forall e' a. Eff e' a -> Eff (e' :& e) a
+  -- ^ Lifted 'PSQL.withSavepoint'.
+  , beginImpl :: Eff e ()
+  -- ^ Lifted 'PSQL.begin'.
+  , commitImpl :: Eff e ()
+  -- ^ Lifted 'PSQL.commit'.
+  , rollbackImpl :: Eff e ()
+  -- ^ Lifted 'PSQL.rollback'.
+  , --
+
+    foldImpl ::
+      forall row params e' a.
+      (PSQL.FromRow row, PSQL.ToRow params) =>
+      PSQL.Query ->
+      params ->
+      a ->
+      (a -> row -> Eff e' a) ->
+      Eff (e' :& e) a
+  -- ^ Lifted 'PSQL.fold'.
+  , fold_Impl ::
+      forall row e' a.
+      (PSQL.FromRow row) =>
+      PSQL.Query ->
+      a ->
+      (a -> row -> Eff e' a) ->
+      Eff (e' :& e) a
+  -- ^ Lifted 'PSQL.fold_'.
+  , foldWithOptionsImpl ::
+      forall row params e' a.
+      (PSQL.FromRow row, PSQL.ToRow params) =>
+      PSQL.FoldOptions ->
+      PSQL.Query ->
+      params ->
+      a ->
+      (a -> row -> Eff e' a) ->
+      Eff (e' :& e) a
+  -- ^ Lifted 'PSQL.foldWithOptions'.
+  , foldWithOptions_Impl ::
+      forall row e' a.
+      (PSQL.FromRow row) =>
+      PSQL.FoldOptions ->
+      PSQL.Query ->
+      a ->
+      (a -> row -> Eff e' a) ->
+      Eff (e' :& e) a
+  -- ^ Lifted 'PSQL.foldWithOptions_'.
+  , forEachImpl ::
+      forall r q e'.
+      (PSQL.FromRow r, PSQL.ToRow q) =>
+      PSQL.Query ->
+      q ->
+      (r -> Eff e' ()) ->
+      Eff (e' :& e) ()
+  -- ^ Lifted 'PSQL.forEach'.
+  , forEach_Impl ::
+      forall r e'.
+      (PSQL.FromRow r) =>
+      PSQL.Query ->
+      (r -> Eff e' ()) ->
+      Eff (e' :& e) ()
+  -- ^ Lifted 'PSQL.forEach_'.
+  , returningImpl ::
+      forall r q.
+      (PSQL.ToRow q, PSQL.FromRow r) =>
+      PSQL.Query ->
+      [q] ->
+      Eff e [r]
+  -- ^ Lifted 'PSQL.returning'.
+  , foldWithImpl ::
+      forall row params e' a.
+      (PSQL.ToRow params) =>
+      PSQL.RowParser row ->
+      PSQL.Query ->
+      params ->
+      a ->
+      (a -> row -> Eff e' a) ->
+      Eff (e' :& e) a
+  -- ^ Lifted 'PSQL.foldWith'.
+  , foldWithOptionsAndParserImpl ::
+      forall row params e' a.
+      (PSQL.ToRow params) =>
+      PSQL.FoldOptions ->
+      PSQL.RowParser row ->
+      PSQL.Query ->
+      params ->
+      a ->
+      (a -> row -> Eff e' a) ->
+      Eff (e' :& e) a
+  -- ^ Lifted 'PSQL.foldWithOptionsAndParser'.
+  , foldWith_Impl ::
+      forall row e' a.
+      () =>
+      PSQL.RowParser row ->
+      PSQL.Query ->
+      a ->
+      (a -> row -> Eff e' a) ->
+      Eff (e' :& e) a
+  -- ^ Lifted 'PSQL.foldWith_'.
+  , foldWithOptionsAndParser_Impl ::
+      forall row e' a.
+      () =>
+      PSQL.FoldOptions ->
+      PSQL.RowParser row ->
+      PSQL.Query ->
+      a ->
+      (a -> row -> Eff e' a) ->
+      Eff (e' :& e) a
+  -- ^ Lifted 'PSQL.foldWithOptionsAndParser_'.
+  , forEachWithImpl ::
+      forall r q e'.
+      (PSQL.ToRow q) =>
+      PSQL.RowParser r ->
+      PSQL.Query ->
+      q ->
+      (r -> Eff e' ()) ->
+      Eff (e' :& e) ()
+  -- ^ Lifted 'PSQL.forEachWith'.
+  , forEachWith_Impl ::
+      forall r e'.
+      () =>
+      PSQL.RowParser r ->
+      PSQL.Query ->
+      (r -> Eff e' ()) ->
+      Eff (e' :& e) ()
+  -- ^ Lifted 'PSQL.forEachWith_'.
+  , returningWithImpl ::
+      forall r q.
+      (PSQL.ToRow q) =>
+      PSQL.RowParser r ->
+      PSQL.Query ->
+      [q] ->
+      Eff e [r]
+  -- ^ Lifted 'PSQL.returningWith'.
+  }
+  deriving (Handle) via OneWayCoercibleHandle PostgreSQL
+
+mapHandlePostgreSQL :: (e :> es) => PostgreSQL e -> PostgreSQL es
+mapHandlePostgreSQL psql =
+  MkPostgreSQL
+    { queryImpl = \q row -> useImpl (queryImpl psql q row)
+    , queryWithImpl = \parser q row -> useImpl (queryWithImpl psql parser q row)
+    , query_Impl = useImpl . query_Impl psql
+    , queryWith_Impl = \parser q -> useImpl (queryWith_Impl psql parser q)
+    , executeImpl = \q row -> useImpl (executeImpl psql q row)
+    , execute_Impl = useImpl . execute_Impl psql
+    , executeManyImpl = \parser qs -> useImpl (executeManyImpl psql parser qs)
+    , withTransactionImpl = useImplUnder . withTransactionImpl psql
+    , withTransactionLevelImpl = \level -> useImplUnder . withTransactionLevelImpl psql level
+    , withTransactionModeImpl = \mode -> useImplUnder . withTransactionModeImpl psql mode
+    , withTransactionModeRetryImpl = \mode shouldRetry -> useImplUnder . withTransactionModeRetryImpl psql mode shouldRetry
+    , withTransactionModeRetry'Impl = \mode shouldRetry -> useImplUnder . withTransactionModeRetry'Impl psql mode shouldRetry
+    , withTransactionSerializableImpl = useImplUnder . withTransactionSerializableImpl psql
+    , withSavepointImpl = useImplUnder . withSavepointImpl psql
+    , beginImpl = useImpl (beginImpl psql)
+    , commitImpl = useImpl (commitImpl psql)
+    , rollbackImpl = useImpl (rollbackImpl psql)
+    , foldImpl = \q params a f -> useImplUnder (foldImpl psql q params a f)
+    , fold_Impl = \q a f -> useImplUnder (fold_Impl psql q a f)
+    , foldWithOptionsImpl = \opts q params a f -> useImplUnder (foldWithOptionsImpl psql opts q params a f)
+    , foldWithOptions_Impl = \opts q a f -> useImplUnder (foldWithOptions_Impl psql opts q a f)
+    , forEachImpl = \q row f -> useImplUnder (forEachImpl psql q row f)
+    , forEach_Impl = \q f -> useImplUnder (forEach_Impl psql q f)
+    , returningImpl = \q rows -> useImpl (returningImpl psql q rows)
+    , foldWithImpl = \parser q params a f -> useImplUnder (foldWithImpl psql parser q params a f)
+    , foldWithOptionsAndParserImpl = \opts parser q params a f -> useImplUnder (foldWithOptionsAndParserImpl psql opts parser q params a f)
+    , foldWith_Impl = \parser params a f -> useImplUnder (foldWith_Impl psql parser params a f)
+    , foldWithOptionsAndParser_Impl = \opts parser params a f -> useImplUnder (foldWithOptionsAndParser_Impl psql opts parser params a f)
+    , forEachWithImpl = \parser q row f -> useImplUnder (forEachWithImpl psql parser q row f)
+    , forEachWith_Impl = \parser row f -> useImplUnder (forEachWith_Impl psql parser row f)
+    , returningWithImpl = \parser q rows -> useImpl (returningWithImpl psql parser q rows)
+    }
+
+instance (e :> es) => OneWayCoercible (PostgreSQL e) (PostgreSQL es) where
+  oneWayCoercibleImpl = oneWayCoercibleTrustMe mapHandlePostgreSQL
+
+-- | Lifted 'PSQL.query'.
+query ::
+  forall q r e es.
+  (HasCallStack, e :> es, PSQL.ToRow q, PSQL.FromRow r) =>
+  PostgreSQL e ->
+  PSQL.Query ->
+  q ->
+  Eff es [r]
+query psql q row = makeOp (queryImpl (mapHandle psql) q row)
+
+-- | Lifted 'PSQL.query_'.
+query_ ::
+  (HasCallStack, e :> es, PSQL.FromRow r) =>
+  PostgreSQL e ->
+  PSQL.Query ->
+  Eff es [r]
+query_ psql row = makeOp (query_Impl (mapHandle psql) row)
+
+-- | Lifted 'PSQL.queryWith'.
+queryWith ::
+  (HasCallStack, e :> es, PSQL.ToRow q) =>
+  PostgreSQL e ->
+  PSQL.RowParser r ->
+  PSQL.Query ->
+  q ->
+  Eff es [r]
+queryWith psql parser q row = makeOp (queryWithImpl (mapHandle psql) parser q row)
+
+-- | Lifted 'PSQL.queryWith_'.
+queryWith_ ::
+  (HasCallStack, e :> es) =>
+  PostgreSQL e ->
+  PSQL.RowParser r ->
+  PSQL.Query ->
+  Eff es [r]
+queryWith_ psql parser row = makeOp (queryWith_Impl (mapHandle psql) parser row)
+
+-- | Lifted 'PSQL.execute'.
+execute ::
+  (HasCallStack, e :> es, PSQL.ToRow q) =>
+  PostgreSQL e ->
+  PSQL.Query ->
+  q ->
+  Eff es Int64
+execute psql q row = makeOp (executeImpl (mapHandle psql) q row)
+
+-- | Lifted 'PSQL.execute_'.
+execute_ ::
+  (HasCallStack, e :> es) =>
+  PostgreSQL e ->
+  PSQL.Query ->
+  Eff es Int64
+execute_ psql row = makeOp (execute_Impl (mapHandle psql) row)
+
+-- | Lifted 'PSQL.executeMany'.
+executeMany ::
+  (HasCallStack, e :> es, PSQL.ToRow q) =>
+  PostgreSQL e ->
+  PSQL.Query ->
+  [q] ->
+  Eff es Int64
+executeMany psql q rows = makeOp (executeManyImpl (mapHandle psql) q rows)
+
+-- | Lifted 'PSQL.withTransaction'.
+withTransaction ::
+  (HasCallStack, e :> es) =>
+  PostgreSQL e ->
+  Eff es a ->
+  Eff es a
+withTransaction psql f = makeOp (withTransactionImpl (mapHandle psql) f)
+
+-- | Lifted 'PSQL.withTransactionLevel'.
+withTransactionLevel ::
+  (HasCallStack, e :> es) =>
+  PostgreSQL e ->
+  PSQL.IsolationLevel ->
+  Eff es a ->
+  Eff es a
+withTransactionLevel psql level f = makeOp (withTransactionLevelImpl (mapHandle psql) level f)
+
+-- | Lifted 'PSQL.withTransactionMode'.
+withTransactionMode ::
+  (HasCallStack, e :> es) =>
+  PostgreSQL e ->
+  PSQL.TransactionMode ->
+  Eff es a ->
+  Eff es a
+withTransactionMode psql mode f = makeOp (withTransactionModeImpl (mapHandle psql) mode f)
+
+-- | Lifted 'PSQL.withTransactionMode'.
+withTransactionModeRetry ::
+  (HasCallStack, e :> es) =>
+  PostgreSQL e ->
+  PSQL.TransactionMode ->
+  (PSQL.SqlError -> Bool) ->
+  Eff es a ->
+  Eff es a
+withTransactionModeRetry psql mode shouldRetry f = makeOp (withTransactionModeRetryImpl (mapHandle psql) mode shouldRetry f)
+
+-- | Lifted 'PSQL.withTransactionMode'.
+withTransactionModeRetry' ::
+  (HasCallStack, e :> es, E.Exception exc) =>
+  PostgreSQL e ->
+  PSQL.TransactionMode ->
+  (exc -> Bool) ->
+  Eff es a ->
+  Eff es a
+withTransactionModeRetry' psql mode shouldRetry f = makeOp (withTransactionModeRetry'Impl (mapHandle psql) mode shouldRetry f)
+
+-- | Lifted 'PSQL.withTransaction'.
+withTransactionSerializable ::
+  (HasCallStack, e :> es) =>
+  PostgreSQL e ->
+  Eff es a ->
+  Eff es a
+withTransactionSerializable psql f = makeOp (withTransactionSerializableImpl (mapHandle psql) f)
+
+-- | British alias of 'withTransactionSerializable'.
+withTransactionSerialisable ::
+  (HasCallStack, e :> es) =>
+  PostgreSQL e ->
+  Eff es a ->
+  Eff es a
+withTransactionSerialisable = withTransactionSerializable
+{-# INLINE withTransactionSerialisable #-}
+
+-- | Lifted 'PSQL.withSavepoint'.
+withSavepoint ::
+  (HasCallStack, e :> es) =>
+  PostgreSQL e ->
+  Eff es a ->
+  Eff es a
+withSavepoint psql f = makeOp (withSavepointImpl (mapHandle psql) f)
+
+-- | Lifted 'PSQL.begin'.
+begin ::
+  (HasCallStack, e :> es) =>
+  PostgreSQL e ->
+  Eff es ()
+begin psql = makeOp (beginImpl (mapHandle psql))
+
+-- | Lifted 'PSQL.commit'.
+commit ::
+  (HasCallStack, e :> es) =>
+  PostgreSQL e ->
+  Eff es ()
+commit psql = makeOp (commitImpl (mapHandle psql))
+
+-- | Lifted 'PSQL.rollback'.
+rollback ::
+  (HasCallStack, e :> es) =>
+  PostgreSQL e ->
+  Eff es ()
+rollback psql = makeOp (rollbackImpl (mapHandle psql))
+
+-- | Lifted 'PSQL.fold'.
+fold ::
+  (HasCallStack, e :> es, PSQL.FromRow row, PSQL.ToRow params) =>
+  PostgreSQL e ->
+  PSQL.Query ->
+  params ->
+  a ->
+  (a -> row -> Eff es a) ->
+  Eff es a
+fold psql q params a f = makeOp (foldImpl (mapHandle psql) q params a f)
+
+-- | Lifted 'PSQL.foldWithOptions'.
+foldWithOptions ::
+  (HasCallStack, e :> es, PSQL.FromRow row, PSQL.ToRow params) =>
+  PostgreSQL e ->
+  PSQL.FoldOptions ->
+  PSQL.Query ->
+  params ->
+  a ->
+  (a -> row -> Eff es a) ->
+  Eff es a
+foldWithOptions psql opts q params a f = makeOp (foldWithOptionsImpl (mapHandle psql) opts q params a f)
+
+-- | Lifted 'PSQL.fold_'.
+fold_ ::
+  (HasCallStack, e :> es, PSQL.FromRow row) =>
+  PostgreSQL e ->
+  PSQL.Query ->
+  a ->
+  (a -> row -> Eff es a) ->
+  Eff es a
+fold_ psql q a f = makeOp (fold_Impl (mapHandle psql) q a f)
+
+-- | Lifted 'PSQL.foldWithOptions_'.
+foldWithOptions_ ::
+  (HasCallStack, e :> es, PSQL.FromRow row) =>
+  PostgreSQL e ->
+  PSQL.FoldOptions ->
+  PSQL.Query ->
+  a ->
+  (a -> row -> Eff es a) ->
+  Eff es a
+foldWithOptions_ psql opts q a f = makeOp (foldWithOptions_Impl (mapHandle psql) opts q a f)
+
+-- | Lifted 'PSQL.forEach'.
+forEach ::
+  (HasCallStack, e :> es, PSQL.FromRow r, PSQL.ToRow q) =>
+  PostgreSQL e ->
+  PSQL.Query ->
+  q ->
+  (r -> Eff es ()) ->
+  Eff es ()
+forEach psql q row forR = makeOp (forEachImpl (mapHandle psql) q row forR)
+
+-- | Lifted 'PSQL.forEach_'.
+forEach_ ::
+  (HasCallStack, e :> es, PSQL.FromRow r) =>
+  PostgreSQL e ->
+  PSQL.Query ->
+  (r -> Eff es ()) ->
+  Eff es ()
+forEach_ psql q forR = makeOp (forEach_Impl (mapHandle psql) q forR)
+
+-- | Lifted 'PSQL.returning'.
+returning ::
+  (HasCallStack, e :> es, PSQL.ToRow q, PSQL.FromRow r) =>
+  PostgreSQL e ->
+  PSQL.Query ->
+  [q] ->
+  Eff es [r]
+returning psql q rows = makeOp (returningImpl (mapHandle psql) q rows)
+
+-- | Lifted 'PSQL.foldWith'.
+foldWith ::
+  (HasCallStack, e :> es, PSQL.ToRow params) =>
+  PostgreSQL e ->
+  PSQL.RowParser row ->
+  PSQL.Query ->
+  params ->
+  a ->
+  (a -> row -> Eff es a) ->
+  Eff es a
+foldWith psql parser q params a f = makeOp (foldWithImpl (mapHandle psql) parser q params a f)
+
+-- | Lifted 'PSQL.foldWithOptionsAndParser'.
+foldWithOptionsAndParser ::
+  (HasCallStack, e :> es, PSQL.ToRow params) =>
+  PostgreSQL e ->
+  PSQL.FoldOptions ->
+  PSQL.RowParser row ->
+  PSQL.Query ->
+  params ->
+  a ->
+  (a -> row -> Eff es a) ->
+  Eff es a
+foldWithOptionsAndParser psql opts parser q params a f = makeOp (foldWithOptionsAndParserImpl (mapHandle psql) opts parser q params a f)
+
+-- | Lifted 'PSQL.foldWith_'.
+foldWith_ ::
+  (HasCallStack, e :> es) =>
+  PostgreSQL e ->
+  PSQL.RowParser row ->
+  PSQL.Query ->
+  a ->
+  (a -> row -> Eff es a) ->
+  Eff es a
+foldWith_ psql parser q a f = makeOp (foldWith_Impl (mapHandle psql) parser q a f)
+
+-- | Lifted 'PSQL.foldWithOptionsAndParser_'.
+foldWithOptionsAndParser_ ::
+  (HasCallStack, e :> es) =>
+  PostgreSQL e ->
+  PSQL.FoldOptions ->
+  PSQL.RowParser row ->
+  PSQL.Query ->
+  a ->
+  (a -> row -> Eff es a) ->
+  Eff es a
+foldWithOptionsAndParser_ psql opts parser q a f = makeOp (foldWithOptionsAndParser_Impl (mapHandle psql) opts parser q a f)
+
+-- | Lifted 'PSQL.forEachWith'.
+forEachWith ::
+  (HasCallStack, e :> es, PSQL.ToRow q) =>
+  PostgreSQL e ->
+  PSQL.RowParser r ->
+  PSQL.Query ->
+  q ->
+  (r -> Eff es ()) ->
+  Eff es ()
+forEachWith psql parser q row forR = makeOp (forEachWithImpl (mapHandle psql) parser q row forR)
+
+-- | Lifted 'PSQL.forEachWith_'.
+forEachWith_ ::
+  (HasCallStack, e :> es) =>
+  PostgreSQL e ->
+  PSQL.RowParser r ->
+  PSQL.Query ->
+  (r -> Eff es ()) ->
+  Eff es ()
+forEachWith_ psql parser row forR = makeOp (forEachWith_Impl (mapHandle psql) parser row forR)
+
+-- | Lifted 'PSQL.returningWith'.
+returningWith ::
+  (HasCallStack, e :> es, PSQL.ToRow q) =>
+  PostgreSQL e ->
+  PSQL.RowParser r ->
+  PSQL.Query ->
+  [q] ->
+  Eff es [r]
+returningWith psql parser q rows = makeOp (returningWithImpl (mapHandle psql) parser q rows)
+
+unliftWithConn ::
+  (HasCallStack, e :> es, e1 :> es) =>
+  WithConnection e ->
+  IOE e1 ->
+  (PSQL.Connection -> (forall b. Eff es b -> IO b) -> IO a) ->
+  Eff es a
+unliftWithConn wc ioe f =
+  withConnection wc $ \conn ->
+    withEffToIO_ ioe $ \unlift ->
+      f conn unlift
+{-# INLINE unliftWithConn #-}
+
+(...) :: (a -> b) -> (t1 -> t2 -> a) -> t1 -> t2 -> b
+unlift ... f = \a' row -> unlift $ f a' row
+
+{- | Obvious interepreter for 'PostgreSQL'. Just gets a 'PSQL.Connection' from 'WithConnection' and calls the
+corresponding function from "Database.PostgreSQL.Simple".
+-}
+runPostgreSQL ::
+  forall e1 e2 es b.
+  (HasCallStack, e1 :> es, e2 :> es) =>
+  WithConnection e1 ->
+  IOE e2 ->
+  (forall e. PostgreSQL e -> Eff (e :& es) b) ->
+  Eff es b
+runPostgreSQL withConn ioe k =
+  useImplIn k MkPostgreSQL {..}
+  where
+    queryImpl :: forall q r. (PSQL.ToRow q, PSQL.FromRow r) => PSQL.Query -> q -> Eff es [r]
+    queryImpl q row = withConnection withConn $ \conn -> effIO ioe (PSQL.query conn q row)
+
+    queryWithImpl :: forall q r. (PSQL.ToRow q) => PSQL.RowParser r -> PSQL.Query -> q -> Eff es [r]
+    queryWithImpl parser q row =
+      withConnection withConn $ \conn -> effIO ioe (PSQL.queryWith parser conn q row)
+
+    query_Impl :: forall r. (PSQL.FromRow r) => PSQL.Query -> Eff es [r]
+    query_Impl row =
+      withConnection withConn $ \conn -> effIO ioe (PSQL.query_ conn row)
+
+    queryWith_Impl :: forall r. PSQL.RowParser r -> PSQL.Query -> Eff es [r]
+    queryWith_Impl parser row =
+      withConnection withConn $ \conn -> effIO ioe (PSQL.queryWith_ parser conn row)
+
+    executeImpl :: forall q. (PSQL.ToRow q) => PSQL.Query -> q -> Eff es Int64
+    executeImpl q row = withConnection withConn $ \conn -> effIO ioe (PSQL.execute conn q row)
+
+    execute_Impl :: PSQL.Query -> Eff es Int64
+    execute_Impl q = withConnection withConn $ \conn -> effIO ioe (PSQL.execute_ conn q)
+
+    executeManyImpl :: forall q. (PSQL.ToRow q) => PSQL.Query -> [q] -> Eff es Int64
+    executeManyImpl q row = withConnection withConn $ \conn -> effIO ioe (PSQL.executeMany conn q row)
+
+    withTransactionImpl :: forall e' a. Eff e' a -> Eff (e' :& es) a
+    withTransactionImpl f = unliftWithConn withConn ioe $ \conn unlift -> PSQL.withTransaction conn (unlift $ useImpl f)
+
+    withTransactionLevelImpl :: forall e' a. PSQL.IsolationLevel -> Eff e' a -> Eff (e' :& es) a
+    withTransactionLevelImpl level f = unliftWithConn withConn ioe $ \conn unlift -> PSQL.withTransactionLevel level conn (unlift $ useImpl f)
+
+    withTransactionModeImpl :: forall e' a. PSQL.TransactionMode -> Eff e' a -> Eff (e' :& es) a
+    withTransactionModeImpl mode f = unliftWithConn withConn ioe $ \conn unlift -> PSQL.withTransactionMode mode conn (unlift $ useImpl f)
+
+    withTransactionModeRetryImpl :: forall e' a. PSQL.TransactionMode -> (PSQL.SqlError -> Bool) -> Eff e' a -> Eff (e' :& es) a
+    withTransactionModeRetryImpl mode shouldRetry f = unliftWithConn withConn ioe $ \conn unlift -> PSQL.withTransactionModeRetry mode shouldRetry conn (unlift $ useImpl f)
+
+    withTransactionModeRetry'Impl :: forall exc e' a. (E.Exception exc) => PSQL.TransactionMode -> (exc -> Bool) -> Eff e' a -> Eff (e' :& es) a
+    withTransactionModeRetry'Impl mode shouldRetry f = unliftWithConn withConn ioe $ \conn unlift -> PSQL.withTransactionModeRetry' mode shouldRetry conn (unlift $ useImpl f)
+
+    withTransactionSerializableImpl :: forall e' a. Eff e' a -> Eff (e' :& es) a
+    withTransactionSerializableImpl f = unliftWithConn withConn ioe $ \conn unlift -> PSQL.withTransactionSerializable conn (unlift $ useImpl f)
+
+    withSavepointImpl :: forall e' a. Eff e' a -> Eff (e' :& es) a
+    withSavepointImpl f = unliftWithConn withConn ioe $ \conn unlift -> PSQL.withSavepoint conn (unlift $ useImpl f)
+
+    beginImpl :: Eff es ()
+    beginImpl = withConnection withConn $ effIO ioe . PSQL.begin
+
+    commitImpl :: Eff es ()
+    commitImpl = withConnection withConn $ effIO ioe . PSQL.commit
+
+    rollbackImpl :: Eff es ()
+    rollbackImpl = withConnection withConn $ effIO ioe . PSQL.rollback
+
+    foldImpl ::
+      forall row params e' a.
+      (PSQL.FromRow row, PSQL.ToRow params) =>
+      PSQL.Query ->
+      params ->
+      a ->
+      (a -> row -> Eff e' a) ->
+      Eff (e' :& es) a
+    foldImpl q params a f =
+      unliftWithConn withConn ioe $ \conn unlift ->
+        PSQL.fold conn q params a (unlift ... (useImpl ... f))
+
+    fold_Impl ::
+      forall row e' a.
+      (PSQL.FromRow row) =>
+      PSQL.Query ->
+      a ->
+      (a -> row -> Eff e' a) ->
+      Eff (e' :& es) a
+    fold_Impl q a f =
+      unliftWithConn withConn ioe $ \conn unlift ->
+        PSQL.fold_ conn q a (unlift ... (useImpl ... f))
+
+    foldWithOptionsImpl ::
+      forall row params e' a.
+      (PSQL.FromRow row, PSQL.ToRow params) =>
+      PSQL.FoldOptions ->
+      PSQL.Query ->
+      params ->
+      a ->
+      (a -> row -> Eff e' a) ->
+      Eff (e' :& es) a
+    foldWithOptionsImpl opts q params a f =
+      unliftWithConn withConn ioe $ \conn unlift ->
+        PSQL.foldWithOptions opts conn q params a (unlift ... (useImpl ... f))
+
+    foldWithOptions_Impl ::
+      forall row e' a.
+      (PSQL.FromRow row) =>
+      PSQL.FoldOptions ->
+      PSQL.Query ->
+      a ->
+      (a -> row -> Eff e' a) ->
+      Eff (e' :& es) a
+    foldWithOptions_Impl opts q a f =
+      unliftWithConn withConn ioe $ \conn unlift ->
+        PSQL.foldWithOptions_ opts conn q a (unlift ... (useImpl ... f))
+
+    forEachImpl ::
+      forall r q e'.
+      (PSQL.FromRow r, PSQL.ToRow q) =>
+      PSQL.Query ->
+      q ->
+      (r -> Eff e' ()) ->
+      Eff (e' :& es) ()
+    forEachImpl q row forR =
+      unliftWithConn withConn ioe $ \conn unlift ->
+        PSQL.forEach conn q row (unlift . useImpl . forR)
+
+    forEach_Impl ::
+      forall r e'.
+      (PSQL.FromRow r) =>
+      PSQL.Query ->
+      (r -> Eff e' ()) ->
+      Eff (e' :& es) ()
+    forEach_Impl q forR =
+      unliftWithConn withConn ioe $ \conn unlift ->
+        PSQL.forEach_ conn q (unlift . useImpl . forR)
+
+    returningImpl ::
+      forall r q.
+      (PSQL.ToRow q, PSQL.FromRow r) =>
+      PSQL.Query ->
+      [q] ->
+      Eff es [r]
+    returningImpl q rows = withConnection withConn $ \conn -> effIO ioe $ PSQL.returning conn q rows
+
+    foldWithImpl ::
+      forall row params e' a.
+      (PSQL.ToRow params) =>
+      PSQL.RowParser row ->
+      PSQL.Query ->
+      params ->
+      a ->
+      (a -> row -> Eff e' a) ->
+      Eff (e' :& es) a
+    foldWithImpl parser q params a f =
+      unliftWithConn withConn ioe $ \conn unlift ->
+        PSQL.foldWith parser conn q params a (unlift ... (useImpl ... f))
+
+    foldWithOptionsAndParserImpl ::
+      forall row params e' a.
+      (PSQL.ToRow params) =>
+      PSQL.FoldOptions ->
+      PSQL.RowParser row ->
+      PSQL.Query ->
+      params ->
+      a ->
+      (a -> row -> Eff e' a) ->
+      Eff (e' :& es) a
+    foldWithOptionsAndParserImpl opts parser q params a f =
+      unliftWithConn withConn ioe $ \conn unlift ->
+        PSQL.foldWithOptionsAndParser opts parser conn q params a (unlift ... (useImpl ... f))
+
+    foldWith_Impl ::
+      forall row e' a.
+      PSQL.RowParser row ->
+      PSQL.Query ->
+      a ->
+      (a -> row -> Eff e' a) ->
+      Eff (e' :& es) a
+    foldWith_Impl parser q a f =
+      unliftWithConn withConn ioe $ \conn unlift ->
+        PSQL.foldWith_ parser conn q a (unlift ... (useImpl ... f))
+
+    foldWithOptionsAndParser_Impl ::
+      forall row e' a.
+      PSQL.FoldOptions ->
+      PSQL.RowParser row ->
+      PSQL.Query ->
+      a ->
+      (a -> row -> Eff e' a) ->
+      Eff (e' :& es) a
+    foldWithOptionsAndParser_Impl opts parser q a f =
+      unliftWithConn withConn ioe $ \conn unlift ->
+        PSQL.foldWithOptionsAndParser_ opts parser conn q a (unlift ... (useImpl ... f))
+
+    forEachWithImpl ::
+      forall r q e'.
+      (PSQL.ToRow q) =>
+      PSQL.RowParser r ->
+      PSQL.Query ->
+      q ->
+      (r -> Eff e' ()) ->
+      Eff (e' :& es) ()
+    forEachWithImpl parser q row forR =
+      unliftWithConn withConn ioe $ \conn unlift ->
+        PSQL.forEachWith parser conn q row (unlift . useImpl . forR)
+
+    forEachWith_Impl ::
+      forall r e'.
+      PSQL.RowParser r ->
+      PSQL.Query ->
+      (r -> Eff e' ()) ->
+      Eff (e' :& es) ()
+    forEachWith_Impl parser q forR =
+      unliftWithConn withConn ioe $ \conn unlift ->
+        PSQL.forEachWith_ parser conn q (unlift . useImpl . forR)
+
+    returningWithImpl ::
+      forall r q.
+      (PSQL.ToRow q) =>
+      PSQL.RowParser r ->
+      PSQL.Query ->
+      [q] ->
+      Eff es [r]
+    returningWithImpl parser q rows = withConnection withConn $ \conn -> effIO ioe $ PSQL.returningWith parser conn q rows
+
+#if OTEL
+{- | An interpreter for the 'PostgreSQL' effect that runs database operations using OpenTelemetry instrumentation.
+
+Basically the same as 'runPostgreSQL' except it uses the functions from
+[OpenTelemetry.Instrumentation.PostgresqlSimple](https://hackage-content.haskell.org/package/hs-opentelemetry-instrumentation-postgresql-simple/docs/OpenTelemetry-Instrumentation-PostgresqlSimple.html).
+
+Note that the @enable-opentel@ cabal flag must be set to enable this functionality.
+-}
+runPostgreSQLOT ::
+  forall e1 e2 es b.
+  (HasCallStack, e1 :> es, e2 :> es) =>
+  WithConnection e1 ->
+  IOE e2 ->
+  (forall e. PostgreSQL e -> Eff (e :& es) b) ->
+  Eff es b
+runPostgreSQLOT withConn ioe k =
+  useImplIn k MkPostgreSQL {..}
+  where
+    queryImpl :: forall q r. (PSQL.ToRow q, PSQL.FromRow r) => PSQL.Query -> q -> Eff es [r]
+    queryImpl q row = withConnection withConn $ \conn -> effIO ioe (OT.query conn q row)
+
+    queryWithImpl :: forall q r. (PSQL.ToRow q) => PSQL.RowParser r -> PSQL.Query -> q -> Eff es [r]
+    queryWithImpl parser q row =
+      withConnection withConn $ \conn -> effIO ioe (OT.queryWith parser conn q row)
+
+    query_Impl :: forall r. (PSQL.FromRow r) => PSQL.Query -> Eff es [r]
+    query_Impl row =
+      withConnection withConn $ \conn -> effIO ioe (OT.query_ conn row)
+
+    queryWith_Impl :: forall r. PSQL.RowParser r -> PSQL.Query -> Eff es [r]
+    queryWith_Impl parser row =
+      withConnection withConn $ \conn -> effIO ioe (OT.queryWith_ parser conn row)
+
+    executeImpl :: forall q. (PSQL.ToRow q) => PSQL.Query -> q -> Eff es Int64
+    executeImpl q row = withConnection withConn $ \conn -> effIO ioe (OT.execute conn q row)
+
+    execute_Impl :: PSQL.Query -> Eff es Int64
+    execute_Impl q = withConnection withConn $ \conn -> effIO ioe (OT.execute_ conn q)
+
+    executeManyImpl :: forall q. (PSQL.ToRow q) => PSQL.Query -> [q] -> Eff es Int64
+    executeManyImpl q row = withConnection withConn $ \conn -> effIO ioe (OT.executeMany conn q row)
+
+    withTransactionImpl :: forall e' a. Eff e' a -> Eff (e' :& es) a
+    withTransactionImpl f = unliftWithConn withConn ioe $ \conn unlift -> OT.withTransaction conn (unlift $ useImpl f)
+
+    withTransactionLevelImpl :: forall e' a. PSQL.IsolationLevel -> Eff e' a -> Eff (e' :& es) a
+    withTransactionLevelImpl level f = unliftWithConn withConn ioe $ \conn unlift -> PSQL.withTransactionLevel level conn (unlift $ useImpl f)
+
+    withTransactionModeImpl :: forall e' a. PSQL.TransactionMode -> Eff e' a -> Eff (e' :& es) a
+    withTransactionModeImpl mode f = unliftWithConn withConn ioe $ \conn unlift -> PSQL.withTransactionMode mode conn (unlift $ useImpl f)
+
+    withTransactionModeRetryImpl :: forall e' a. PSQL.TransactionMode -> (PSQL.SqlError -> Bool) -> Eff e' a -> Eff (e' :& es) a
+    withTransactionModeRetryImpl mode shouldRetry f = unliftWithConn withConn ioe $ \conn unlift -> PSQL.withTransactionModeRetry mode shouldRetry conn (unlift $ useImpl f)
+
+    withTransactionModeRetry'Impl :: forall exc e' a. (E.Exception exc) => PSQL.TransactionMode -> (exc -> Bool) -> Eff e' a -> Eff (e' :& es) a
+    withTransactionModeRetry'Impl mode shouldRetry f = unliftWithConn withConn ioe $ \conn unlift -> PSQL.withTransactionModeRetry' mode shouldRetry conn (unlift $ useImpl f)
+
+    withTransactionSerializableImpl :: forall e' a. Eff e' a -> Eff (e' :& es) a
+    withTransactionSerializableImpl f = unliftWithConn withConn ioe $ \conn unlift -> PSQL.withTransactionSerializable conn (unlift $ useImpl f)
+
+    withSavepointImpl :: forall e' a. Eff e' a -> Eff (e' :& es) a
+    withSavepointImpl f = unliftWithConn withConn ioe $ \conn unlift -> OT.withSavepoint conn (unlift $ useImpl f)
+
+    beginImpl :: Eff es ()
+    beginImpl = withConnection withConn $ effIO ioe . OT.begin
+
+    commitImpl :: Eff es ()
+    commitImpl = withConnection withConn $ effIO ioe . OT.commit
+
+    rollbackImpl :: Eff es ()
+    rollbackImpl = withConnection withConn $ effIO ioe . OT.rollback
+
+    foldImpl ::
+      forall row params e' a.
+      (PSQL.FromRow row, PSQL.ToRow params) =>
+      PSQL.Query ->
+      params ->
+      a ->
+      (a -> row -> Eff e' a) ->
+      Eff (e' :& es) a
+    foldImpl q params a f =
+      unliftWithConn withConn ioe $ \conn unlift ->
+        OT.fold conn q params a (unlift ... (useImpl ... f))
+
+    fold_Impl ::
+      forall row e' a.
+      (PSQL.FromRow row) =>
+      PSQL.Query ->
+      a ->
+      (a -> row -> Eff e' a) ->
+      Eff (e' :& es) a
+    fold_Impl q a f =
+      unliftWithConn withConn ioe $ \conn unlift ->
+        OT.fold_ conn q a (unlift ... (useImpl ... f))
+
+    foldWithOptionsImpl ::
+      forall row params e' a.
+      (PSQL.FromRow row, PSQL.ToRow params) =>
+      PSQL.FoldOptions ->
+      PSQL.Query ->
+      params ->
+      a ->
+      (a -> row -> Eff e' a) ->
+      Eff (e' :& es) a
+    foldWithOptionsImpl opts q params a f =
+      unliftWithConn withConn ioe $ \conn unlift ->
+        OT.foldWithOptions opts conn q params a (unlift ... (useImpl ... f))
+
+    foldWithOptions_Impl ::
+      forall row e' a.
+      (PSQL.FromRow row) =>
+      PSQL.FoldOptions ->
+      PSQL.Query ->
+      a ->
+      (a -> row -> Eff e' a) ->
+      Eff (e' :& es) a
+    foldWithOptions_Impl opts q a f =
+      unliftWithConn withConn ioe $ \conn unlift ->
+        OT.foldWithOptions_ opts conn q a (unlift ... (useImpl ... f))
+
+    forEachImpl ::
+      forall r q e'.
+      (PSQL.FromRow r, PSQL.ToRow q) =>
+      PSQL.Query ->
+      q ->
+      (r -> Eff e' ()) ->
+      Eff (e' :& es) ()
+    forEachImpl q row forR =
+      unliftWithConn withConn ioe $ \conn unlift ->
+        OT.forEachWith PSQL.fromRow conn q row (unlift . useImpl . forR)
+
+    forEach_Impl ::
+      forall r e'.
+      (PSQL.FromRow r) =>
+      PSQL.Query ->
+      (r -> Eff e' ()) ->
+      Eff (e' :& es) ()
+    forEach_Impl q forR =
+      unliftWithConn withConn ioe $ \conn unlift ->
+        OT.forEach_ conn q (unlift . useImpl . forR)
+
+    returningImpl ::
+      forall r q.
+      (PSQL.ToRow q, PSQL.FromRow r) =>
+      PSQL.Query ->
+      [q] ->
+      Eff es [r]
+    returningImpl q rows = withConnection withConn $ \conn -> effIO ioe $ OT.returning conn q rows
+
+    foldWithImpl ::
+      forall row params e' a.
+      (PSQL.ToRow params) =>
+      PSQL.RowParser row ->
+      PSQL.Query ->
+      params ->
+      a ->
+      (a -> row -> Eff e' a) ->
+      Eff (e' :& es) a
+    foldWithImpl parser q params a f =
+      unliftWithConn withConn ioe $ \conn unlift ->
+        OT.foldWith parser conn q params a (unlift ... (useImpl ... f))
+
+    foldWithOptionsAndParserImpl ::
+      forall row params e' a.
+      (PSQL.ToRow params) =>
+      PSQL.FoldOptions ->
+      PSQL.RowParser row ->
+      PSQL.Query ->
+      params ->
+      a ->
+      (a -> row -> Eff e' a) ->
+      Eff (e' :& es) a
+    foldWithOptionsAndParserImpl opts parser q params a f =
+      unliftWithConn withConn ioe $ \conn unlift ->
+        OT.foldWithOptionsAndParser opts parser conn q params a (unlift ... (useImpl ... f))
+
+    foldWith_Impl ::
+      forall row e' a.
+      PSQL.RowParser row ->
+      PSQL.Query ->
+      a ->
+      (a -> row -> Eff e' a) ->
+      Eff (e' :& es) a
+    foldWith_Impl parser q a f =
+      unliftWithConn withConn ioe $ \conn unlift ->
+        OT.foldWith_ parser conn q a (unlift ... (useImpl ... f))
+
+    foldWithOptionsAndParser_Impl ::
+      forall row e' a.
+      PSQL.FoldOptions ->
+      PSQL.RowParser row ->
+      PSQL.Query ->
+      a ->
+      (a -> row -> Eff e' a) ->
+      Eff (e' :& es) a
+    foldWithOptionsAndParser_Impl opts parser q a f =
+      unliftWithConn withConn ioe $ \conn unlift ->
+        OT.foldWithOptionsAndParser_ opts parser conn q a (unlift ... (useImpl ... f))
+
+    forEachWithImpl ::
+      forall r q e'.
+      (PSQL.ToRow q) =>
+      PSQL.RowParser r ->
+      PSQL.Query ->
+      q ->
+      (r -> Eff e' ()) ->
+      Eff (e' :& es) ()
+    forEachWithImpl parser q row forR =
+      unliftWithConn withConn ioe $ \conn unlift ->
+        OT.forEachWith parser conn q row (unlift . useImpl . forR)
+
+    forEachWith_Impl ::
+      forall r e'.
+      PSQL.RowParser r ->
+      PSQL.Query ->
+      (r -> Eff e' ()) ->
+      Eff (e' :& es) ()
+    forEachWith_Impl parser q forR =
+      unliftWithConn withConn ioe $ \conn unlift ->
+        OT.forEachWith_ parser conn q (unlift . useImpl . forR)
+
+    returningWithImpl ::
+      forall r q.
+      (PSQL.ToRow q) =>
+      PSQL.RowParser r ->
+      PSQL.Query ->
+      [q] ->
+      Eff es [r]
+    returningWithImpl parser q rows = withConnection withConn $ \conn -> effIO ioe $ OT.returningWith parser conn q rows
+#endif
