    {-# LANGUAGE CPP #-}
    {-# LANGUAGE DeriveDataTypeable #-}
    {-# LANGUAGE FlexibleContexts #-}
    {-# LANGUAGE FlexibleInstances #-}
    {-# LANGUAGE GADTs #-}
    {-# LANGUAGE GeneralizedNewtypeDeriving #-}
    {-# LANGUAGE LambdaCase #-}
    {-# LANGUAGE MultiParamTypeClasses #-}
    {-# LANGUAGE NamedFieldPuns #-}
    {-# LANGUAGE OverloadedStrings #-}
    {-# LANGUAGE RecordWildCards #-}
    {-# LANGUAGE ScopedTypeVariables #-}
    {-# LANGUAGE StandaloneDeriving #-}
    {-# LANGUAGE TupleSections #-}
    {-# LANGUAGE TypeFamilies #-}
    {-# LANGUAGE TypeOperators #-}
    {-# LANGUAGE ViewPatterns #-}

    #if MIN_VERSION_base(4,12,0)
    {-# LANGUAGE DerivingVia #-}
    {-# LANGUAGE QuasiQuotes #-}
    {-# LANGUAGE TemplateHaskell #-}
    {-# LANGUAGE UndecidableInstances #-}
    #endif

    -- | A postgresql backend for persistent.
    module Database.Persist.Postgresql
        ( withPostgresqlPool
        , withPostgresqlPoolWithVersion
        , withPostgresqlPoolWithConf
        , withPostgresqlPoolModified
        , withPostgresqlPoolModifiedWithVersion
        , withPostgresqlConn
        , withPostgresqlConnWithVersion
        , createPostgresqlPool
        , createPostgresqlPoolModified
        , createPostgresqlPoolModifiedWithVersion
        , createPostgresqlPoolTailored
        , createPostgresqlPoolWithConf
        , module Database.Persist.Sql
        , ConnectionString
        , HandleUpdateCollision
        , copyField
        , copyUnlessNull
        , copyUnlessEmpty
        , copyUnlessEq
        , excludeNotEqualToOriginal
        , PostgresConf (..)
        , PgInterval (..)
        , upsertWhere
        , upsertManyWhere
        , openSimpleConn
        , openSimpleConnWithVersion
        , getServerVersion
        , getSimpleConn
        , tableName
        , fieldName
        , mockMigration
        , migrateEnableExtension
        , PostgresConfHooks (..)
        , defaultPostgresConfHooks
        , RawPostgresql (..)
        , createRawPostgresqlPool
        , createRawPostgresqlPoolModified
        , createRawPostgresqlPoolModifiedWithVersion
        , createRawPostgresqlPoolWithConf
        , createBackend
        ) where

    import qualified Database.PostgreSQL.LibPQ as LibPQ

    import qualified Database.PostgreSQL.Simple as PG
    import qualified Database.PostgreSQL.Simple.FromField as PGFF
    import qualified Database.PostgreSQL.Simple.Internal as PG
    import Database.PostgreSQL.Simple.Ok (Ok (..))
    import qualified Database.PostgreSQL.Simple.Transaction as PG
    import qualified Database.PostgreSQL.Simple.Types as PG

    import Control.Exception (Exception, throw, throwIO)
    import Control.Monad
    import Control.Monad.Except
    import Control.Monad.IO.Unlift (MonadIO (..), MonadUnliftIO)
    import Control.Monad.Logger (MonadLoggerIO, runNoLoggingT)
    import Control.Monad.Trans.Reader (ReaderT (..), asks, runReaderT)
    #if !MIN_VERSION_base(4,12,0)
    import Control.Monad.Trans.Reader (withReaderT)
    #endif
    import Control.Monad.Trans.Writer (WriterT (..), runWriterT)
    import qualified Data.List.NonEmpty as NEL
    import Data.Proxy (Proxy (..))

    import Data.Acquire (Acquire, mkAcquire)
    import Data.Aeson
    import Data.Aeson.Types (modifyFailure)
    import qualified Data.Attoparsec.Text as AT
    import Data.ByteString (ByteString)
    import qualified Data.ByteString.Char8 as B8
    import Data.Conduit
    import Data.Data (Data)
    import Data.Either (partitionEithers)
    import Data.IORef
    import Data.Int (Int64)
    import Data.List.NonEmpty (NonEmpty)
    import qualified Data.Map as Map
    import qualified Data.Monoid as Monoid
    import Data.Pool (Pool)
    import Data.Text (Text)
    import qualified Data.Text as T
    import qualified Data.Text.Encoding as T
    import qualified Data.Text.IO as T
    import Data.Text.Read (rational)
    import System.Environment (getEnvironment)

    #if MIN_VERSION_base(4,12,0)
    import Database.Persist.Compatible
    #endif
    import qualified Data.Vault.Strict as Vault
    import Database.Persist.Postgresql.Internal
    import Database.Persist.Sql
    import qualified Database.Persist.Sql.Util as Util
    import Database.Persist.SqlBackend
    import System.IO.Unsafe (unsafePerformIO)

    -- | A @libpq@ connection string.  A simple example of connection
    -- string would be @\"host=localhost port=5432 user=test
    -- dbname=test password=test\"@.  Please read libpq's
    -- documentation at
    -- <https://www.postgresql.org/docs/current/static/libpq-connect.html>
    -- for more details on how to create such strings.
    type ConnectionString = ByteString

    -- | PostgresServerVersionError exception. This is thrown when persistent
    -- is unable to find the version of the postgreSQL server.
    data PostgresServerVersionError = PostgresServerVersionError String

    instance Show PostgresServerVersionError where
        show :: PostgresServerVersionError -> String
    show (PostgresServerVersionError String
    uniqueMsg) =
            String
    "Unexpected PostgreSQL server version, got " String -> ShowS
    forall a. Semigroup a => a -> a -> a
    <> String
    uniqueMsg
    instance Exception PostgresServerVersionError

    -- | Create a PostgreSQL connection pool and run the given action. The pool is
    -- properly released after the action finishes using it.  Note that you should
    -- not use the given 'ConnectionPool' outside the action since it may already
    -- have been released.
    -- The provided action should use 'runSqlConn' and *not* 'runReaderT' because
    -- the former brackets the database action with transaction begin/commit.
    withPostgresqlPool
        :: (MonadLoggerIO m, MonadUnliftIO m)
        => ConnectionString
        -- ^ Connection string to the database.
        -> Int
        -- ^ Number of connections to be kept open in
        -- the pool.
        -> (Pool SqlBackend -> m a)
        -- ^ Action to be executed that uses the
        -- connection pool.
        -> m a
    withPostgresqlPool :: forall (m :: * -> *) a.
    (MonadLoggerIO m, MonadUnliftIO m) =>
    ConnectionString -> Int -> (Pool SqlBackend -> m a) -> m a
    withPostgresqlPool ConnectionString
    ci = (Connection -> IO (Maybe Double))
    -> ConnectionString -> Int -> (Pool SqlBackend -> m a) -> m a
    forall (m :: * -> *) a.
    (MonadUnliftIO m, MonadLoggerIO m) =>
    (Connection -> IO (Maybe Double))
    -> ConnectionString -> Int -> (Pool SqlBackend -> m a) -> m a
    withPostgresqlPoolWithVersion Connection -> IO (Maybe Double)
    getServerVersion ConnectionString
    ci

    -- | Same as 'withPostgresPool', but takes a callback for obtaining
    -- the server version (to work around an Amazon Redshift bug).
    --
    -- @since 2.6.2
    withPostgresqlPoolWithVersion
        :: (MonadUnliftIO m, MonadLoggerIO m)
        => (PG.Connection -> IO (Maybe Double))
        -- ^ Action to perform to get the server version.
        -> ConnectionString
        -- ^ Connection string to the database.
        -> Int
        -- ^ Number of connections to be kept open in
        -- the pool.
        -> (Pool SqlBackend -> m a)
        -- ^ Action to be executed that uses the
        -- connection pool.
        -> m a
    withPostgresqlPoolWithVersion :: forall (m :: * -> *) a.
    (MonadUnliftIO m, MonadLoggerIO m) =>
    (Connection -> IO (Maybe Double))
    -> ConnectionString -> Int -> (Pool SqlBackend -> m a) -> m a
    withPostgresqlPoolWithVersion Connection -> IO (Maybe Double)
    getVerDouble ConnectionString
    ci = do
        let
            getVer :: Connection -> IO (NonEmpty Word)
    getVer = (Connection -> IO (Maybe Double))
    -> Connection -> IO (NonEmpty Word)
    oldGetVersionToNew Connection -> IO (Maybe Double)
    getVerDouble
        (LogFunc -> IO SqlBackend)
    -> Int -> (Pool SqlBackend -> m a) -> m a
    forall backend (m :: * -> *) a.
    (MonadLoggerIO m, MonadUnliftIO m,
     BackendCompatible SqlBackend backend) =>
    (LogFunc -> IO backend) -> Int -> (Pool backend -> m a) -> m a
    withSqlPool ((LogFunc -> IO SqlBackend)
     -> Int -> (Pool SqlBackend -> m a) -> m a)
    -> (LogFunc -> IO SqlBackend)
    -> Int
    -> (Pool SqlBackend -> m a)
    -> m a
    forall a b. (a -> b) -> a -> b
    $ (Connection -> IO ())
    -> (Connection -> IO (NonEmpty Word))
    -> ((Connection -> SqlBackend) -> Connection -> SqlBackend)
    -> ConnectionString
    -> LogFunc
    -> IO SqlBackend
    forall backend.
    (Connection -> IO ())
    -> (Connection -> IO (NonEmpty Word))
    -> ((Connection -> SqlBackend) -> Connection -> backend)
    -> ConnectionString
    -> LogFunc
    -> IO backend
    open' (IO () -> Connection -> IO ()
    forall a b. a -> b -> a
    const (IO () -> Connection -> IO ()) -> IO () -> Connection -> IO ()
    forall a b. (a -> b) -> a -> b
    $ () -> IO ()
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()) Connection -> IO (NonEmpty Word)
    getVer (Connection -> SqlBackend) -> Connection -> SqlBackend
    forall a. a -> a
    id ConnectionString
    ci

    -- | Same as 'withPostgresqlPool', but can be configured with 'PostgresConf' and 'PostgresConfHooks'.
    --
    -- @since 2.11.0.0
    withPostgresqlPoolWithConf
        :: (MonadUnliftIO m, MonadLoggerIO m)
        => PostgresConf
        -- ^ Configuration for connecting to Postgres
        -> PostgresConfHooks
        -- ^ Record of callback functions
        -> (Pool SqlBackend -> m a)
        -- ^ Action to be executed that uses the
        -- connection pool.
        -> m a
    withPostgresqlPoolWithConf :: forall (m :: * -> *) a.
    (MonadUnliftIO m, MonadLoggerIO m) =>
    PostgresConf
    -> PostgresConfHooks -> (Pool SqlBackend -> m a) -> m a
    withPostgresqlPoolWithConf PostgresConf
    conf PostgresConfHooks
    hooks = do
        let
            getVer :: Connection -> IO (NonEmpty Word)
    getVer = PostgresConfHooks -> Connection -> IO (NonEmpty Word)
    pgConfHooksGetServerVersion PostgresConfHooks
    hooks
            modConn :: Connection -> IO ()
    modConn = PostgresConfHooks -> Connection -> IO ()
    pgConfHooksAfterCreate PostgresConfHooks
    hooks
        let
            logFuncToBackend :: LogFunc -> IO SqlBackend
    logFuncToBackend = (Connection -> IO ())
    -> (Connection -> IO (NonEmpty Word))
    -> ((Connection -> SqlBackend) -> Connection -> SqlBackend)
    -> ConnectionString
    -> LogFunc
    -> IO SqlBackend
    forall backend.
    (Connection -> IO ())
    -> (Connection -> IO (NonEmpty Word))
    -> ((Connection -> SqlBackend) -> Connection -> backend)
    -> ConnectionString
    -> LogFunc
    -> IO backend
    open' Connection -> IO ()
    modConn Connection -> IO (NonEmpty Word)
    getVer (Connection -> SqlBackend) -> Connection -> SqlBackend
    forall a. a -> a
    id (PostgresConf -> ConnectionString
    pgConnStr PostgresConf
    conf)
        (LogFunc -> IO SqlBackend)
    -> ConnectionPoolConfig -> (Pool SqlBackend -> m a) -> m a
    forall backend (m :: * -> *) a.
    (MonadLoggerIO m, MonadUnliftIO m,
     BackendCompatible SqlBackend backend) =>
    (LogFunc -> IO backend)
    -> ConnectionPoolConfig -> (Pool backend -> m a) -> m a
    withSqlPoolWithConfig LogFunc -> IO SqlBackend
    logFuncToBackend (PostgresConf -> ConnectionPoolConfig
    postgresConfToConnectionPoolConfig PostgresConf
    conf)

    -- | Same as 'withPostgresqlPool', but with the 'createPostgresqlPoolModified'
    -- feature.
    --
    -- @since 2.13.5.0
    withPostgresqlPoolModified
        :: (MonadUnliftIO m, MonadLoggerIO m)
        => (PG.Connection -> IO ())
        -- ^ Action to perform after connection is created.
        -> ConnectionString
        -- ^ Connection string to the database.
        -> Int
        -- ^ Number of connections to be kept open in the pool.
        -> (Pool SqlBackend -> m t)
        -> m t
    withPostgresqlPoolModified :: forall (m :: * -> *) t.
    (MonadUnliftIO m, MonadLoggerIO m) =>
    (Connection -> IO ())
    -> ConnectionString -> Int -> (Pool SqlBackend -> m t) -> m t
    withPostgresqlPoolModified = (Connection -> IO (Maybe Double))
    -> (Connection -> IO ())
    -> ConnectionString
    -> Int
    -> (Pool SqlBackend -> m t)
    -> m t
    forall (m :: * -> *) t.
    (MonadUnliftIO m, MonadLoggerIO m) =>
    (Connection -> IO (Maybe Double))
    -> (Connection -> IO ())
    -> ConnectionString
    -> Int
    -> (Pool SqlBackend -> m t)
    -> m t
    withPostgresqlPoolModifiedWithVersion Connection -> IO (Maybe Double)
    getServerVersion

    -- | Same as 'withPostgresqlPool', but with the
    -- 'createPostgresqlPoolModifiedWithVersion' feature.
    --
    -- @since 2.13.5.0
    withPostgresqlPoolModifiedWithVersion
        :: (MonadUnliftIO m, MonadLoggerIO m)
        => (PG.Connection -> IO (Maybe Double))
        -- ^ Action to perform to get the server version.
        -> (PG.Connection -> IO ())
        -- ^ Action to perform after connection is created.
        -> ConnectionString
        -- ^ Connection string to the database.
        -> Int
        -- ^ Number of connections to be kept open in the pool.
        -> (Pool SqlBackend -> m t)
        -> m t
    withPostgresqlPoolModifiedWithVersion :: forall (m :: * -> *) t.
    (MonadUnliftIO m, MonadLoggerIO m) =>
    (Connection -> IO (Maybe Double))
    -> (Connection -> IO ())
    -> ConnectionString
    -> Int
    -> (Pool SqlBackend -> m t)
    -> m t
    withPostgresqlPoolModifiedWithVersion Connection -> IO (Maybe Double)
    getVerDouble Connection -> IO ()
    modConn ConnectionString
    ci = do
        (LogFunc -> IO SqlBackend)
    -> Int -> (Pool SqlBackend -> m t) -> m t
    forall backend (m :: * -> *) a.
    (MonadLoggerIO m, MonadUnliftIO m,
     BackendCompatible SqlBackend backend) =>
    (LogFunc -> IO backend) -> Int -> (Pool backend -> m a) -> m a
    withSqlPool ((Connection -> IO ())
    -> (Connection -> IO (NonEmpty Word))
    -> ((Connection -> SqlBackend) -> Connection -> SqlBackend)
    -> ConnectionString
    -> LogFunc
    -> IO SqlBackend
    forall backend.
    (Connection -> IO ())
    -> (Connection -> IO (NonEmpty Word))
    -> ((Connection -> SqlBackend) -> Connection -> backend)
    -> ConnectionString
    -> LogFunc
    -> IO backend
    open' Connection -> IO ()
    modConn ((Connection -> IO (Maybe Double))
    -> Connection -> IO (NonEmpty Word)
    oldGetVersionToNew Connection -> IO (Maybe Double)
    getVerDouble) (Connection -> SqlBackend) -> Connection -> SqlBackend
    forall a. a -> a
    id ConnectionString
    ci)

    -- | Create a PostgreSQL connection pool.  Note that it's your
    -- responsibility to properly close the connection pool when
    -- unneeded.  Use 'withPostgresqlPool' for an automatic resource
    -- control.
    createPostgresqlPool
        :: (MonadUnliftIO m, MonadLoggerIO m)
        => ConnectionString
        -- ^ Connection string to the database.
        -> Int
        -- ^ Number of connections to be kept open
        -- in the pool.
        -> m (Pool SqlBackend)
    createPostgresqlPool :: forall (m :: * -> *).
    (MonadUnliftIO m, MonadLoggerIO m) =>
    ConnectionString -> Int -> m (Pool SqlBackend)
    createPostgresqlPool = (Connection -> IO ())
    -> ConnectionString -> Int -> m (Pool SqlBackend)
    forall (m :: * -> *).
    (MonadUnliftIO m, MonadLoggerIO m) =>
    (Connection -> IO ())
    -> ConnectionString -> Int -> m (Pool SqlBackend)
    createPostgresqlPoolModified (IO () -> Connection -> IO ()
    forall a b. a -> b -> a
    const (IO () -> Connection -> IO ()) -> IO () -> Connection -> IO ()
    forall a b. (a -> b) -> a -> b
    $ () -> IO ()
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ())

    -- | Same as 'createPostgresqlPool', but additionally takes a callback function
    -- for some connection-specific tweaking to be performed after connection
    -- creation. This could be used, for example, to change the schema. For more
    -- information, see:
    --
    -- <https://groups.google.com/d/msg/yesodweb/qUXrEN_swEo/O0pFwqwQIdcJ>
    --
    -- @since 2.1.3
    createPostgresqlPoolModified
        :: (MonadUnliftIO m, MonadLoggerIO m)
        => (PG.Connection -> IO ())
        -- ^ Action to perform after connection is created.
        -> ConnectionString
        -- ^ Connection string to the database.
        -> Int
        -- ^ Number of connections to be kept open in the pool.
        -> m (Pool SqlBackend)
    createPostgresqlPoolModified :: forall (m :: * -> *).
    (MonadUnliftIO m, MonadLoggerIO m) =>
    (Connection -> IO ())
    -> ConnectionString -> Int -> m (Pool SqlBackend)
    createPostgresqlPoolModified = (Connection -> IO (Maybe Double))
    -> (Connection -> IO ())
    -> ConnectionString
    -> Int
    -> m (Pool SqlBackend)
    forall (m :: * -> *).
    (MonadUnliftIO m, MonadLoggerIO m) =>
    (Connection -> IO (Maybe Double))
    -> (Connection -> IO ())
    -> ConnectionString
    -> Int
    -> m (Pool SqlBackend)
    createPostgresqlPoolModifiedWithVersion Connection -> IO (Maybe Double)
    getServerVersion

    -- | Same as other similarly-named functions in this module, but takes callbacks for obtaining
    -- the server version (to work around an Amazon Redshift bug) and connection-specific tweaking
    -- (to change the schema).
    --
    -- @since 2.6.2
    createPostgresqlPoolModifiedWithVersion
        :: (MonadUnliftIO m, MonadLoggerIO m)
        => (PG.Connection -> IO (Maybe Double))
        -- ^ Action to perform to get the server version.
        -> (PG.Connection -> IO ())
        -- ^ Action to perform after connection is created.
        -> ConnectionString
        -- ^ Connection string to the database.
        -> Int
        -- ^ Number of connections to be kept open in the pool.
        -> m (Pool SqlBackend)
    createPostgresqlPoolModifiedWithVersion :: forall (m :: * -> *).
    (MonadUnliftIO m, MonadLoggerIO m) =>
    (Connection -> IO (Maybe Double))
    -> (Connection -> IO ())
    -> ConnectionString
    -> Int
    -> m (Pool SqlBackend)
    createPostgresqlPoolModifiedWithVersion = ((Connection -> IO ())
     -> (Connection -> IO (NonEmpty Word))
     -> ((Connection -> SqlBackend) -> Connection -> SqlBackend)
     -> ConnectionString
     -> LogFunc
     -> IO SqlBackend)
    -> (Connection -> IO (Maybe Double))
    -> (Connection -> IO ())
    -> ConnectionString
    -> Int
    -> m (Pool SqlBackend)
    forall (m :: * -> *).
    (MonadUnliftIO m, MonadLoggerIO m) =>
    ((Connection -> IO ())
     -> (Connection -> IO (NonEmpty Word))
     -> ((Connection -> SqlBackend) -> Connection -> SqlBackend)
     -> ConnectionString
     -> LogFunc
     -> IO SqlBackend)
    -> (Connection -> IO (Maybe Double))
    -> (Connection -> IO ())
    -> ConnectionString
    -> Int
    -> m (Pool SqlBackend)
    createPostgresqlPoolTailored (Connection -> IO ())
    -> (Connection -> IO (NonEmpty Word))
    -> ((Connection -> SqlBackend) -> Connection -> SqlBackend)
    -> ConnectionString
    -> LogFunc
    -> IO SqlBackend
    forall backend.
    (Connection -> IO ())
    -> (Connection -> IO (NonEmpty Word))
    -> ((Connection -> SqlBackend) -> Connection -> backend)
    -> ConnectionString
    -> LogFunc
    -> IO backend
    open'

    -- | Same as 'createPostgresqlPoolModifiedWithVersion', but takes a custom connection-creation
    -- function.
    --
    -- The only time you should reach for this function is if you need to write custom logic for creating
    -- a connection to the database.
    --
    -- @since 2.13.6
    createPostgresqlPoolTailored
        :: (MonadUnliftIO m, MonadLoggerIO m)
        => ( (PG.Connection -> IO ())
             -> (PG.Connection -> IO (NonEmpty Word))
             -> ((PG.Connection -> SqlBackend) -> PG.Connection -> SqlBackend)
             -> ConnectionString
             -> LogFunc
             -> IO SqlBackend
           )
        -- ^ Action that creates a postgresql connection (please see documentation on the un-exported @open'@ function in this same module.
        -> (PG.Connection -> IO (Maybe Double))
        -- ^ Action to perform to get the server version.
        -> (PG.Connection -> IO ())
        -- ^ Action to perform after connection is created.
        -> ConnectionString
        -- ^ Connection string to the database.
        -> Int
        -- ^ Number of connections to be kept open in the pool.
        -> m (Pool SqlBackend)
    createPostgresqlPoolTailored :: forall (m :: * -> *).
    (MonadUnliftIO m, MonadLoggerIO m) =>
    ((Connection -> IO ())
     -> (Connection -> IO (NonEmpty Word))
     -> ((Connection -> SqlBackend) -> Connection -> SqlBackend)
     -> ConnectionString
     -> LogFunc
     -> IO SqlBackend)
    -> (Connection -> IO (Maybe Double))
    -> (Connection -> IO ())
    -> ConnectionString
    -> Int
    -> m (Pool SqlBackend)
    createPostgresqlPoolTailored (Connection -> IO ())
    -> (Connection -> IO (NonEmpty Word))
    -> ((Connection -> SqlBackend) -> Connection -> SqlBackend)
    -> ConnectionString
    -> LogFunc
    -> IO SqlBackend
    createConnection Connection -> IO (Maybe Double)
    getVerDouble Connection -> IO ()
    modConn ConnectionString
    ci = do
        let
            getVer :: Connection -> IO (NonEmpty Word)
    getVer = (Connection -> IO (Maybe Double))
    -> Connection -> IO (NonEmpty Word)
    oldGetVersionToNew Connection -> IO (Maybe Double)
    getVerDouble
        (LogFunc -> IO SqlBackend) -> Int -> m (Pool SqlBackend)
    forall backend (m :: * -> *).
    (MonadLoggerIO m, MonadUnliftIO m,
     BackendCompatible SqlBackend backend) =>
    (LogFunc -> IO backend) -> Int -> m (Pool backend)
    createSqlPool ((LogFunc -> IO SqlBackend) -> Int -> m (Pool SqlBackend))
    -> (LogFunc -> IO SqlBackend) -> Int -> m (Pool SqlBackend)
    forall a b. (a -> b) -> a -> b
    $ (Connection -> IO ())
    -> (Connection -> IO (NonEmpty Word))
    -> ((Connection -> SqlBackend) -> Connection -> SqlBackend)
    -> ConnectionString
    -> LogFunc
    -> IO SqlBackend
    createConnection Connection -> IO ()
    modConn Connection -> IO (NonEmpty Word)
    getVer (Connection -> SqlBackend) -> Connection -> SqlBackend
    forall a. a -> a
    id ConnectionString
    ci

    -- | Same as 'createPostgresqlPool', but can be configured with 'PostgresConf' and 'PostgresConfHooks'.
    --
    -- @since 2.11.0.0
    createPostgresqlPoolWithConf
        :: (MonadUnliftIO m, MonadLoggerIO m)
        => PostgresConf
        -- ^ Configuration for connecting to Postgres
        -> PostgresConfHooks
        -- ^ Record of callback functions
        -> m (Pool SqlBackend)
    createPostgresqlPoolWithConf :: forall (m :: * -> *).
    (MonadUnliftIO m, MonadLoggerIO m) =>
    PostgresConf -> PostgresConfHooks -> m (Pool SqlBackend)
    createPostgresqlPoolWithConf PostgresConf
    conf PostgresConfHooks
    hooks = do
        let
            getVer :: Connection -> IO (NonEmpty Word)
    getVer = PostgresConfHooks -> Connection -> IO (NonEmpty Word)
    pgConfHooksGetServerVersion PostgresConfHooks
    hooks
            modConn :: Connection -> IO ()
    modConn = PostgresConfHooks -> Connection -> IO ()
    pgConfHooksAfterCreate PostgresConfHooks
    hooks
        (LogFunc -> IO SqlBackend)
    -> ConnectionPoolConfig -> m (Pool SqlBackend)
    forall (m :: * -> *) backend.
    (MonadLoggerIO m, MonadUnliftIO m,
     BackendCompatible SqlBackend backend) =>
    (LogFunc -> IO backend) -> ConnectionPoolConfig -> m (Pool backend)
    createSqlPoolWithConfig
            ((Connection -> IO ())
    -> (Connection -> IO (NonEmpty Word))
    -> ((Connection -> SqlBackend) -> Connection -> SqlBackend)
    -> ConnectionString
    -> LogFunc
    -> IO SqlBackend
    forall backend.
    (Connection -> IO ())
    -> (Connection -> IO (NonEmpty Word))
    -> ((Connection -> SqlBackend) -> Connection -> backend)
    -> ConnectionString
    -> LogFunc
    -> IO backend
    open' Connection -> IO ()
    modConn Connection -> IO (NonEmpty Word)
    getVer (Connection -> SqlBackend) -> Connection -> SqlBackend
    forall a. a -> a
    id (PostgresConf -> ConnectionString
    pgConnStr PostgresConf
    conf))
            (PostgresConf -> ConnectionPoolConfig
    postgresConfToConnectionPoolConfig PostgresConf
    conf)

    postgresConfToConnectionPoolConfig :: PostgresConf -> ConnectionPoolConfig
    postgresConfToConnectionPoolConfig :: PostgresConf -> ConnectionPoolConfig
    postgresConfToConnectionPoolConfig PostgresConf
    conf =
        ConnectionPoolConfig
            { connectionPoolConfigStripes :: Int
    connectionPoolConfigStripes = PostgresConf -> Int
    pgPoolStripes PostgresConf
    conf
            , connectionPoolConfigIdleTimeout :: NominalDiffTime
    connectionPoolConfigIdleTimeout = Integer -> NominalDiffTime
    forall a. Num a => Integer -> a
    fromInteger (Integer -> NominalDiffTime) -> Integer -> NominalDiffTime
    forall a b. (a -> b) -> a -> b
    $ PostgresConf -> Integer
    pgPoolIdleTimeout PostgresConf
    conf
            , connectionPoolConfigSize :: Int
    connectionPoolConfigSize = PostgresConf -> Int
    pgPoolSize PostgresConf
    conf
            }

    -- | Same as 'withPostgresqlPool', but instead of opening a pool
    -- of connections, only one connection is opened.
    -- The provided action should use 'runSqlConn' and *not* 'runReaderT' because
    -- the former brackets the database action with transaction begin/commit.
    withPostgresqlConn
        :: (MonadUnliftIO m, MonadLoggerIO m)
        => ConnectionString
        -> (SqlBackend -> m a)
        -> m a
    withPostgresqlConn :: forall (m :: * -> *) a.
    (MonadUnliftIO m, MonadLoggerIO m) =>
    ConnectionString -> (SqlBackend -> m a) -> m a
    withPostgresqlConn = (Connection -> IO (Maybe Double))
    -> ConnectionString -> (SqlBackend -> m a) -> m a
    forall (m :: * -> *) a.
    (MonadUnliftIO m, MonadLoggerIO m) =>
    (Connection -> IO (Maybe Double))
    -> ConnectionString -> (SqlBackend -> m a) -> m a
    withPostgresqlConnWithVersion Connection -> IO (Maybe Double)
    getServerVersion

    -- | Same as 'withPostgresqlConn', but takes a callback for obtaining
    -- the server version (to work around an Amazon Redshift bug).
    --
    -- @since 2.6.2
    withPostgresqlConnWithVersion
        :: (MonadUnliftIO m, MonadLoggerIO m)
        => (PG.Connection -> IO (Maybe Double))
        -> ConnectionString
        -> (SqlBackend -> m a)
        -> m a
    withPostgresqlConnWithVersion :: forall (m :: * -> *) a.
    (MonadUnliftIO m, MonadLoggerIO m) =>
    (Connection -> IO (Maybe Double))
    -> ConnectionString -> (SqlBackend -> m a) -> m a
    withPostgresqlConnWithVersion Connection -> IO (Maybe Double)
    getVerDouble = do
        let
            getVer :: Connection -> IO (NonEmpty Word)
    getVer = (Connection -> IO (Maybe Double))
    -> Connection -> IO (NonEmpty Word)
    oldGetVersionToNew Connection -> IO (Maybe Double)
    getVerDouble
        (LogFunc -> IO SqlBackend) -> (SqlBackend -> m a) -> m a
    forall backend (m :: * -> *) a.
    (MonadUnliftIO m, MonadLoggerIO m,
     BackendCompatible SqlBackend backend) =>
    (LogFunc -> IO backend) -> (backend -> m a) -> m a
    withSqlConn ((LogFunc -> IO SqlBackend) -> (SqlBackend -> m a) -> m a)
    -> (ConnectionString -> LogFunc -> IO SqlBackend)
    -> ConnectionString
    -> (SqlBackend -> m a)
    -> m a
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (Connection -> IO ())
    -> (Connection -> IO (NonEmpty Word))
    -> ((Connection -> SqlBackend) -> Connection -> SqlBackend)
    -> ConnectionString
    -> LogFunc
    -> IO SqlBackend
    forall backend.
    (Connection -> IO ())
    -> (Connection -> IO (NonEmpty Word))
    -> ((Connection -> SqlBackend) -> Connection -> backend)
    -> ConnectionString
    -> LogFunc
    -> IO backend
    open' (IO () -> Connection -> IO ()
    forall a b. a -> b -> a
    const (IO () -> Connection -> IO ()) -> IO () -> Connection -> IO ()
    forall a b. (a -> b) -> a -> b
    $ () -> IO ()
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()) Connection -> IO (NonEmpty Word)
    getVer (Connection -> SqlBackend) -> Connection -> SqlBackend
    forall a. a -> a
    id

    open'
        :: (PG.Connection -> IO ())
        -> (PG.Connection -> IO (NonEmpty Word))
        -> ((PG.Connection -> SqlBackend) -> PG.Connection -> backend)
        -- ^ How to construct the actual backend type desired. For most uses,
        -- this is just 'id', since the desired backend type is 'SqlBackend'.
        -- But some callers want a @'RawPostgresql' 'SqlBackend'@, and will
        -- pass in 'withRawConnection'.
        -> ConnectionString
        -> LogFunc
        -> IO backend
    open' :: forall backend.
    (Connection -> IO ())
    -> (Connection -> IO (NonEmpty Word))
    -> ((Connection -> SqlBackend) -> Connection -> backend)
    -> ConnectionString
    -> LogFunc
    -> IO backend
    open' Connection -> IO ()
    modConn Connection -> IO (NonEmpty Word)
    getVer (Connection -> SqlBackend) -> Connection -> backend
    constructor ConnectionString
    cstr LogFunc
    logFunc = do
        conn <- ConnectionString -> IO Connection
    PG.connectPostgreSQL ConnectionString
    cstr
        modConn conn
        ver <- getVer conn
        smap <- newIORef mempty
        return $ constructor (createBackend logFunc ver smap) conn

    -- | Gets the PostgreSQL server version
    --
    -- @since 2.13.6
    getServerVersion :: PG.Connection -> IO (Maybe Double)
    getServerVersion :: Connection -> IO (Maybe Double)
    getServerVersion Connection
    conn = do
        [PG.Only version] <- Connection -> Query -> IO [Only Text]
    forall r. FromRow r => Connection -> Query -> IO [r]
    PG.query_ Connection
    conn Query
    "show server_version"
        let
            version' = Reader Double
    forall a. Fractional a => Reader a
    rational Text
    version
        --- λ> rational "9.8.3"
        --- Right (9.8,".3")
        --- λ> rational "9.8.3.5"
        --- Right (9.8,".3.5")
        case version' of
            Right (Double
    a, Text
    _) -> Maybe Double -> IO (Maybe Double)
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Maybe Double -> IO (Maybe Double))
    -> Maybe Double -> IO (Maybe Double)
    forall a b. (a -> b) -> a -> b
    $ Double -> Maybe Double
    forall a. a -> Maybe a
    Just Double
    a
            Left String
    err -> PostgresServerVersionError -> IO (Maybe Double)
    forall e a. (HasCallStack, Exception e) => e -> IO a
    throwIO (PostgresServerVersionError -> IO (Maybe Double))
    -> PostgresServerVersionError -> IO (Maybe Double)
    forall a b. (a -> b) -> a -> b
    $ String -> PostgresServerVersionError
    PostgresServerVersionError String
    err

    getServerVersionNonEmpty :: PG.Connection -> IO (NonEmpty Word)
    getServerVersionNonEmpty :: Connection -> IO (NonEmpty Word)
    getServerVersionNonEmpty Connection
    conn = do
        [PG.Only version] <- Connection -> Query -> IO [Only String]
    forall r. FromRow r => Connection -> Query -> IO [r]
    PG.query_ Connection
    conn Query
    "show server_version"
        case AT.parseOnly parseVersion (T.pack version) of
            Left String
    err ->
                PostgresServerVersionError -> IO (NonEmpty Word)
    forall e a. (HasCallStack, Exception e) => e -> IO a
    throwIO (PostgresServerVersionError -> IO (NonEmpty Word))
    -> PostgresServerVersionError -> IO (NonEmpty Word)
    forall a b. (a -> b) -> a -> b
    $
                    String -> PostgresServerVersionError
    PostgresServerVersionError (String -> PostgresServerVersionError)
    -> String -> PostgresServerVersionError
    forall a b. (a -> b) -> a -> b
    $
                        String
    "Parse failure on: " String -> ShowS
    forall a. Semigroup a => a -> a -> a
    <> String
    version String -> ShowS
    forall a. Semigroup a => a -> a -> a
    <> String
    ". Error: " String -> ShowS
    forall a. Semigroup a => a -> a -> a
    <> String
    err
            Right [Word]
    versionComponents -> case [Word] -> Maybe (NonEmpty Word)
    forall a. [a] -> Maybe (NonEmpty a)
    NEL.nonEmpty [Word]
    versionComponents of
                Maybe (NonEmpty Word)
    Nothing ->
                    PostgresServerVersionError -> IO (NonEmpty Word)
    forall e a. (HasCallStack, Exception e) => e -> IO a
    throwIO (PostgresServerVersionError -> IO (NonEmpty Word))
    -> PostgresServerVersionError -> IO (NonEmpty Word)
    forall a b. (a -> b) -> a -> b
    $
                        String -> PostgresServerVersionError
    PostgresServerVersionError (String -> PostgresServerVersionError)
    -> String -> PostgresServerVersionError
    forall a b. (a -> b) -> a -> b
    $
                            String
    "Empty Postgres version string: " String -> ShowS
    forall a. Semigroup a => a -> a -> a
    <> String
    version
                Just NonEmpty Word
    neVersion -> NonEmpty Word -> IO (NonEmpty Word)
    forall a. a -> IO a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure NonEmpty Word
    neVersion
      where
        -- Partially copied from the `versions` package
        -- Typically server_version gives e.g. 12.3
        -- In Persistent's CI, we get "12.4 (Debian 12.4-1.pgdg100+1)", so we ignore the trailing data.
        parseVersion :: Parser [Word]
    parseVersion = Parser Word
    forall a. Integral a => Parser a
    AT.decimal Parser Word -> Parser Text Char -> Parser [Word]
    forall (f :: * -> *) a s. Alternative f => f a -> f s -> f [a]
    `AT.sepBy` Char -> Parser Text Char
    AT.char Char
    '.'

    -- | Choose upsert sql generation function based on postgresql version.
    -- PostgreSQL version >= 9.5 supports native upsert feature,
    -- so depending upon that we have to choose how the sql query is generated.
    -- upsertFunction :: Double -> Maybe (EntityDef -> Text -> Text)
    upsertFunction :: a -> NonEmpty Word -> Maybe a
    upsertFunction :: forall a. a -> NonEmpty Word -> Maybe a
    upsertFunction a
    f NonEmpty Word
    version =
        if (NonEmpty Word
    version NonEmpty Word -> NonEmpty Word -> Bool
    forall a. Ord a => a -> a -> Bool
    >= NonEmpty Word
    postgres9dot5)
            then a -> Maybe a
    forall a. a -> Maybe a
    Just a
    f
            else Maybe a
    forall a. Maybe a
    Nothing
      where

    postgres9dot5 :: NonEmpty Word
    postgres9dot5 :: NonEmpty Word
    postgres9dot5 = Word
    9 Word -> [Word] -> NonEmpty Word
    forall a. a -> [a] -> NonEmpty a
    NEL.:| [Word
    5]

    -- | If the user doesn't supply a Postgres version, we assume this version.
    --
    -- This is currently below any version-specific features Persistent uses.
    minimumPostgresVersion :: NonEmpty Word
    minimumPostgresVersion :: NonEmpty Word
    minimumPostgresVersion = Word
    9 Word -> [Word] -> NonEmpty Word
    forall a. a -> [a] -> NonEmpty a
    NEL.:| [Word
    4]

    oldGetVersionToNew
        :: (PG.Connection -> IO (Maybe Double)) -> (PG.Connection -> IO (NonEmpty Word))
    oldGetVersionToNew :: (Connection -> IO (Maybe Double))
    -> Connection -> IO (NonEmpty Word)
    oldGetVersionToNew Connection -> IO (Maybe Double)
    oldFn = \Connection
    conn -> do
        mDouble <- Connection -> IO (Maybe Double)
    oldFn Connection
    conn
        case mDouble of
            Maybe Double
    Nothing -> NonEmpty Word -> IO (NonEmpty Word)
    forall a. a -> IO a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure NonEmpty Word
    minimumPostgresVersion
            Just Double
    double -> do
                let
                    (Word
    major, Double
    minor) = Double -> (Word, Double)
    forall b. Integral b => Double -> (b, Double)
    forall a b. (RealFrac a, Integral b) => a -> (b, a)
    properFraction Double
    double
                NonEmpty Word -> IO (NonEmpty Word)
    forall a. a -> IO a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure (NonEmpty Word -> IO (NonEmpty Word))
    -> NonEmpty Word -> IO (NonEmpty Word)
    forall a b. (a -> b) -> a -> b
    $ Word
    major Word -> [Word] -> NonEmpty Word
    forall a. a -> [a] -> NonEmpty a
    NEL.:| [Double -> Word
    forall b. Integral b => Double -> b
    forall a b. (RealFrac a, Integral b) => a -> b
    floor Double
    minor]

    -- | Generate a 'SqlBackend' from a 'PG.Connection'.
    openSimpleConn :: LogFunc -> PG.Connection -> IO SqlBackend
    openSimpleConn :: LogFunc -> Connection -> IO SqlBackend
    openSimpleConn = (Connection -> IO (Maybe Double))
    -> LogFunc -> Connection -> IO SqlBackend
    openSimpleConnWithVersion Connection -> IO (Maybe Double)
    getServerVersion

    -- | Generate a 'SqlBackend' from a 'PG.Connection', but takes a callback for
    -- obtaining the server version.
    --
    -- @since 2.9.1
    openSimpleConnWithVersion
        :: (PG.Connection -> IO (Maybe Double))
        -> LogFunc
        -> PG.Connection
        -> IO SqlBackend
    openSimpleConnWithVersion :: (Connection -> IO (Maybe Double))
    -> LogFunc -> Connection -> IO SqlBackend
    openSimpleConnWithVersion Connection -> IO (Maybe Double)
    getVerDouble LogFunc
    logFunc Connection
    conn = do
        smap <- Map Text Statement -> IO (IORef (Map Text Statement))
    forall a. a -> IO (IORef a)
    newIORef Map Text Statement
    forall a. Monoid a => a
    mempty
        serverVersion <- oldGetVersionToNew getVerDouble conn
        return $ createBackend logFunc serverVersion smap conn

    underlyingConnectionKey :: Vault.Key PG.Connection
    underlyingConnectionKey :: Key Connection
    underlyingConnectionKey = IO (Key Connection) -> Key Connection
    forall a. IO a -> a
    unsafePerformIO IO (Key Connection)
    forall a. IO (Key a)
    Vault.newKey
    {-# NOINLINE underlyingConnectionKey #-}

    -- | Access underlying connection, returning 'Nothing' if the 'SqlBackend'
    -- provided isn't backed by postgresql-simple.
    --
    -- @since 2.13.0
    getSimpleConn
        :: (BackendCompatible SqlBackend backend) => backend -> Maybe PG.Connection
    getSimpleConn :: forall backend.
    BackendCompatible SqlBackend backend =>
    backend -> Maybe Connection
    getSimpleConn = Key Connection -> Vault -> Maybe Connection
    forall a. Key a -> Vault -> Maybe a
    Vault.lookup Key Connection
    underlyingConnectionKey (Vault -> Maybe Connection)
    -> (backend -> Vault) -> backend -> Maybe Connection
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> backend -> Vault
    forall backend (m :: * -> *).
    (BackendCompatible SqlBackend backend, MonadReader backend m) =>
    m Vault
    getConnVault

    -- | Create the backend given a logging function, server version, mutable statement cell,
    -- and connection.
    --
    -- @since 2.13.6
    createBackend
        :: LogFunc
        -> NonEmpty Word
        -> IORef (Map.Map Text Statement)
        -> PG.Connection
        -> SqlBackend
    createBackend :: LogFunc
    -> NonEmpty Word
    -> IORef (Map Text Statement)
    -> Connection
    -> SqlBackend
    createBackend LogFunc
    logFunc NonEmpty Word
    serverVersion IORef (Map Text Statement)
    smap Connection
    conn =
        (SqlBackend -> SqlBackend)
    -> ((EntityDef -> Int -> Text) -> SqlBackend -> SqlBackend)
    -> Maybe (EntityDef -> Int -> Text)
    -> SqlBackend
    -> SqlBackend
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe SqlBackend -> SqlBackend
    forall a. a -> a
    id (EntityDef -> Int -> Text) -> SqlBackend -> SqlBackend
    setConnPutManySql ((EntityDef -> Int -> Text)
    -> NonEmpty Word -> Maybe (EntityDef -> Int -> Text)
    forall a. a -> NonEmpty Word -> Maybe a
    upsertFunction EntityDef -> Int -> Text
    putManySql NonEmpty Word
    serverVersion) (SqlBackend -> SqlBackend) -> SqlBackend -> SqlBackend
    forall a b. (a -> b) -> a -> b
    $
            (SqlBackend -> SqlBackend)
    -> ((EntityDef
         -> NonEmpty (FieldNameHS, FieldNameDB) -> Text -> Text)
        -> SqlBackend -> SqlBackend)
    -> Maybe
         (EntityDef -> NonEmpty (FieldNameHS, FieldNameDB) -> Text -> Text)
    -> SqlBackend
    -> SqlBackend
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe SqlBackend -> SqlBackend
    forall a. a -> a
    id (EntityDef -> NonEmpty (FieldNameHS, FieldNameDB) -> Text -> Text)
    -> SqlBackend -> SqlBackend
    setConnUpsertSql ((EntityDef -> NonEmpty (FieldNameHS, FieldNameDB) -> Text -> Text)
    -> NonEmpty Word
    -> Maybe
         (EntityDef -> NonEmpty (FieldNameHS, FieldNameDB) -> Text -> Text)
    forall a. a -> NonEmpty Word -> Maybe a
    upsertFunction EntityDef -> NonEmpty (FieldNameHS, FieldNameDB) -> Text -> Text
    upsertSql' NonEmpty Word
    serverVersion) (SqlBackend -> SqlBackend) -> SqlBackend -> SqlBackend
    forall a b. (a -> b) -> a -> b
    $
                (EntityDef -> [[PersistValue]] -> InsertSqlResult)
    -> SqlBackend -> SqlBackend
    setConnInsertManySql EntityDef -> [[PersistValue]] -> InsertSqlResult
    insertManySql' (SqlBackend -> SqlBackend) -> SqlBackend -> SqlBackend
    forall a b. (a -> b) -> a -> b
    $
                    (SqlBackend -> SqlBackend)
    -> ((EntityDef -> Int -> Text) -> SqlBackend -> SqlBackend)
    -> Maybe (EntityDef -> Int -> Text)
    -> SqlBackend
    -> SqlBackend
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe SqlBackend -> SqlBackend
    forall a. a -> a
    id (EntityDef -> Int -> Text) -> SqlBackend -> SqlBackend
    setConnRepsertManySql ((EntityDef -> Int -> Text)
    -> NonEmpty Word -> Maybe (EntityDef -> Int -> Text)
    forall a. a -> NonEmpty Word -> Maybe a
    upsertFunction EntityDef -> Int -> Text
    repsertManySql NonEmpty Word
    serverVersion) (SqlBackend -> SqlBackend) -> SqlBackend -> SqlBackend
    forall a b. (a -> b) -> a -> b
    $
                        (Vault -> Vault) -> SqlBackend -> SqlBackend
    modifyConnVault (Key Connection -> Connection -> Vault -> Vault
    forall a. Key a -> a -> Vault -> Vault
    Vault.insert Key Connection
    underlyingConnectionKey Connection
    conn) (SqlBackend -> SqlBackend) -> SqlBackend -> SqlBackend
    forall a b. (a -> b) -> a -> b
    $
                            MkSqlBackendArgs -> SqlBackend
    mkSqlBackend
                                MkSqlBackendArgs
                                    { connPrepare :: Text -> IO Statement
    connPrepare = Connection -> Text -> IO Statement
    prepare' Connection
    conn
                                    , connStmtMap :: IORef (Map Text Statement)
    connStmtMap = IORef (Map Text Statement)
    smap
                                    , connInsertSql :: EntityDef -> [PersistValue] -> InsertSqlResult
    connInsertSql = EntityDef -> [PersistValue] -> InsertSqlResult
    insertSql'
                                    , connClose :: IO ()
    connClose = Connection -> IO ()
    PG.close Connection
    conn
                                    , connMigrateSql :: [EntityDef]
    -> (Text -> IO Statement)
    -> EntityDef
    -> IO (Either [Text] [(Bool, Text)])
    connMigrateSql = [EntityDef]
    -> (Text -> IO Statement)
    -> EntityDef
    -> IO (Either [Text] [(Bool, Text)])
    migrate'
                                    , connBegin :: (Text -> IO Statement) -> Maybe IsolationLevel -> IO ()
    connBegin = \Text -> IO Statement
    _ Maybe IsolationLevel
    mIsolation -> case Maybe IsolationLevel
    mIsolation of
                                        Maybe IsolationLevel
    Nothing -> Connection -> IO ()
    PG.begin Connection
    conn
                                        Just IsolationLevel
    iso ->
                                            IsolationLevel -> Connection -> IO ()
    PG.beginLevel
                                                ( case IsolationLevel
    iso of
                                                    IsolationLevel
    ReadUncommitted -> IsolationLevel
    PG.ReadCommitted -- PG Upgrades uncommitted reads to committed anyways
                                                    IsolationLevel
    ReadCommitted -> IsolationLevel
    PG.ReadCommitted
                                                    IsolationLevel
    RepeatableRead -> IsolationLevel
    PG.RepeatableRead
                                                    IsolationLevel
    Serializable -> IsolationLevel
    PG.Serializable
                                                )
                                                Connection
    conn
                                    , connCommit :: (Text -> IO Statement) -> IO ()
    connCommit = IO () -> (Text -> IO Statement) -> IO ()
    forall a b. a -> b -> a
    const (IO () -> (Text -> IO Statement) -> IO ())
    -> IO () -> (Text -> IO Statement) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ Connection -> IO ()
    PG.commit Connection
    conn
                                    , connRollback :: (Text -> IO Statement) -> IO ()
    connRollback = IO () -> (Text -> IO Statement) -> IO ()
    forall a b. a -> b -> a
    const (IO () -> (Text -> IO Statement) -> IO ())
    -> IO () -> (Text -> IO Statement) -> IO ()
    forall a b. (a -> b) -> a -> b
    $ Connection -> IO ()
    PG.rollback Connection
    conn
                                    , connEscapeFieldName :: FieldNameDB -> Text
    connEscapeFieldName = FieldNameDB -> Text
    escapeF
                                    , connEscapeTableName :: EntityDef -> Text
    connEscapeTableName = EntityNameDB -> Text
    escapeE (EntityNameDB -> Text)
    -> (EntityDef -> EntityNameDB) -> EntityDef -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . EntityDef -> EntityNameDB
    getEntityDBName
                                    , connEscapeRawName :: Text -> Text
    connEscapeRawName = Text -> Text
    escape
                                    , connNoLimit :: Text
    connNoLimit = Text
    "LIMIT ALL"
                                    , connRDBMS :: Text
    connRDBMS = Text
    "postgresql"
                                    , connLimitOffset :: (Int, Int) -> Text -> Text
    connLimitOffset = Text -> (Int, Int) -> Text -> Text
    decorateSQLWithLimitOffset Text
    "LIMIT ALL"
                                    , connLogFunc :: LogFunc
    connLogFunc = LogFunc
    logFunc
                                    }

    prepare' :: PG.Connection -> Text -> IO Statement
    prepare' :: Connection -> Text -> IO Statement
    prepare' Connection
    conn Text
    sql = do
        let
            query :: Query
    query = ConnectionString -> Query
    PG.Query (Text -> ConnectionString
    T.encodeUtf8 Text
    sql)
        Statement -> IO Statement
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return
            Statement
                { stmtFinalize :: IO ()
    stmtFinalize = () -> IO ()
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
                , stmtReset :: IO ()
    stmtReset = () -> IO ()
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
                , stmtExecute :: [PersistValue] -> IO Int64
    stmtExecute = Connection -> Query -> [PersistValue] -> IO Int64
    execute' Connection
    conn Query
    query
                , stmtQuery :: forall (m :: * -> *).
    MonadIO m =>
    [PersistValue] -> Acquire (ConduitM () [PersistValue] m ())
    stmtQuery = Connection
    -> Query
    -> [PersistValue]
    -> Acquire (ConduitM () [PersistValue] m ())
    forall (m :: * -> *).
    MonadIO m =>
    Connection
    -> Query
    -> [PersistValue]
    -> Acquire (ConduitM () [PersistValue] m ())
    withStmt' Connection
    conn Query
    query
                }

    insertSql' :: EntityDef -> [PersistValue] -> InsertSqlResult
    insertSql' :: EntityDef -> [PersistValue] -> InsertSqlResult
    insertSql' EntityDef
    ent [PersistValue]
    vals =
        case EntityDef -> EntityIdDef
    getEntityId EntityDef
    ent of
            EntityIdNaturalKey CompositeDef
    _pdef ->
                Text -> [PersistValue] -> InsertSqlResult
    ISRManyKeys Text
    sql [PersistValue]
    vals
            EntityIdField FieldDef
    field ->
                Text -> InsertSqlResult
    ISRSingle (Text
    sql Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    " RETURNING " Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> FieldNameDB -> Text
    escapeF (FieldDef -> FieldNameDB
    fieldDB FieldDef
    field))
      where
        ([Text]
    fieldNames, [Text]
    placeholders) = [(Text, Text)] -> ([Text], [Text])
    forall a b. [(a, b)] -> ([a], [b])
    unzip (EntityDef -> (FieldNameDB -> Text) -> [(Text, Text)]
    Util.mkInsertPlaceholders EntityDef
    ent FieldNameDB -> Text
    escapeF)
        sql :: Text
    sql =
            [Text] -> Text
    T.concat
                [ Text
    "INSERT INTO "
                , EntityNameDB -> Text
    escapeE (EntityNameDB -> Text) -> EntityNameDB -> Text
    forall a b. (a -> b) -> a -> b
    $ EntityDef -> EntityNameDB
    getEntityDBName EntityDef
    ent
                , if [FieldDef] -> Bool
    forall a. [a] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null (EntityDef -> [FieldDef]
    getEntityFields EntityDef
    ent)
                    then Text
    " DEFAULT VALUES"
                    else
                        [Text] -> Text
    T.concat
                            [ Text
    "("
                            , Text -> [Text] -> Text
    T.intercalate Text
    "," [Text]
    fieldNames
                            , Text
    ") VALUES("
                            , Text -> [Text] -> Text
    T.intercalate Text
    "," [Text]
    placeholders
                            , Text
    ")"
                            ]
                ]

    upsertSql' :: EntityDef -> NonEmpty (FieldNameHS, FieldNameDB) -> Text -> Text
    upsertSql' :: EntityDef -> NonEmpty (FieldNameHS, FieldNameDB) -> Text -> Text
    upsertSql' EntityDef
    ent NonEmpty (FieldNameHS, FieldNameDB)
    uniqs Text
    updateVal =
        [Text] -> Text
    T.concat
            [ Text
    "INSERT INTO "
            , EntityNameDB -> Text
    escapeE (EntityDef -> EntityNameDB
    getEntityDBName EntityDef
    ent)
            , Text
    "("
            , Text -> [Text] -> Text
    T.intercalate Text
    "," [Text]
    fieldNames
            , Text
    ") VALUES ("
            , Text -> [Text] -> Text
    T.intercalate Text
    "," [Text]
    placeholders
            , Text
    ") ON CONFLICT ("
            , Text -> [Text] -> Text
    T.intercalate Text
    "," ([Text] -> Text) -> [Text] -> Text
    forall a b. (a -> b) -> a -> b
    $ ((FieldNameHS, FieldNameDB) -> Text)
    -> [(FieldNameHS, FieldNameDB)] -> [Text]
    forall a b. (a -> b) -> [a] -> [b]
    map (FieldNameDB -> Text
    escapeF (FieldNameDB -> Text)
    -> ((FieldNameHS, FieldNameDB) -> FieldNameDB)
    -> (FieldNameHS, FieldNameDB)
    -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (FieldNameHS, FieldNameDB) -> FieldNameDB
    forall a b. (a, b) -> b
    snd) (NonEmpty (FieldNameHS, FieldNameDB) -> [(FieldNameHS, FieldNameDB)]
    forall a. NonEmpty a -> [a]
    NEL.toList NonEmpty (FieldNameHS, FieldNameDB)
    uniqs)
            , Text
    ") DO UPDATE SET "
            , Text
    updateVal
            , Text
    " WHERE "
            , Text
    wher
            , Text
    " RETURNING ??"
            ]
      where
        ([Text]
    fieldNames, [Text]
    placeholders) = [(Text, Text)] -> ([Text], [Text])
    forall a b. [(a, b)] -> ([a], [b])
    unzip (EntityDef -> (FieldNameDB -> Text) -> [(Text, Text)]
    Util.mkInsertPlaceholders EntityDef
    ent FieldNameDB -> Text
    escapeF)

        wher :: Text
    wher = Text -> [Text] -> Text
    T.intercalate Text
    " AND " ([Text] -> Text) -> [Text] -> Text
    forall a b. (a -> b) -> a -> b
    $ ((FieldNameHS, FieldNameDB) -> Text)
    -> [(FieldNameHS, FieldNameDB)] -> [Text]
    forall a b. (a -> b) -> [a] -> [b]
    map (FieldNameDB -> Text
    singleClause (FieldNameDB -> Text)
    -> ((FieldNameHS, FieldNameDB) -> FieldNameDB)
    -> (FieldNameHS, FieldNameDB)
    -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (FieldNameHS, FieldNameDB) -> FieldNameDB
    forall a b. (a, b) -> b
    snd) ([(FieldNameHS, FieldNameDB)] -> [Text])
    -> [(FieldNameHS, FieldNameDB)] -> [Text]
    forall a b. (a -> b) -> a -> b
    $ NonEmpty (FieldNameHS, FieldNameDB) -> [(FieldNameHS, FieldNameDB)]
    forall a. NonEmpty a -> [a]
    NEL.toList NonEmpty (FieldNameHS, FieldNameDB)
    uniqs

        singleClause :: FieldNameDB -> Text
        singleClause :: FieldNameDB -> Text
    singleClause FieldNameDB
    field = EntityNameDB -> Text
    escapeE (EntityDef -> EntityNameDB
    getEntityDBName EntityDef
    ent) Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    "." Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> (FieldNameDB -> Text
    escapeF FieldNameDB
    field) Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> Text
    " =?"

    -- | SQL for inserting multiple rows at once and returning their primary keys.
    insertManySql' :: EntityDef -> [[PersistValue]] -> InsertSqlResult
    insertManySql' :: EntityDef -> [[PersistValue]] -> InsertSqlResult
    insertManySql' EntityDef
    ent [[PersistValue]]
    valss =
        Text -> InsertSqlResult
    ISRSingle Text
    sql
      where
        ([Text]
    fieldNames, [Text]
    placeholders) = [(Text, Text)] -> ([Text], [Text])
    forall a b. [(a, b)] -> ([a], [b])
    unzip (EntityDef -> (FieldNameDB -> Text) -> [(Text, Text)]
    Util.mkInsertPlaceholders EntityDef
    ent FieldNameDB -> Text
    escapeF)
        sql :: Text
    sql =
            [Text] -> Text
    T.concat
                [ Text
    "INSERT INTO "
                , EntityNameDB -> Text
    escapeE (EntityDef -> EntityNameDB
    getEntityDBName EntityDef
    ent)
                , Text
    "("
                , Text -> [Text] -> Text
    T.intercalate Text
    "," [Text]
    fieldNames
                , Text
    ") VALUES ("
                , Text -> [Text] -> Text
    T.intercalate Text
    "),(" ([Text] -> Text) -> [Text] -> Text
    forall a b. (a -> b) -> a -> b
    $ Int -> Text -> [Text]
    forall a. Int -> a -> [a]
    replicate ([[PersistValue]] -> Int
    forall a. [a] -> Int
    forall (t :: * -> *) a. Foldable t => t a -> Int
    length [[PersistValue]]
    valss) (Text -> [Text]) -> Text -> [Text]
    forall a b. (a -> b) -> a -> b
    $ Text -> [Text] -> Text
    T.intercalate Text
    "," [Text]
    placeholders
                , Text
    ") RETURNING "
                , [Text] -> Text
    Util.commaSeparated ([Text] -> Text) -> [Text] -> Text
    forall a b. (a -> b) -> a -> b
    $ NonEmpty Text -> [Text]
    forall a. NonEmpty a -> [a]
    NEL.toList (NonEmpty Text -> [Text]) -> NonEmpty Text -> [Text]
    forall a b. (a -> b) -> a -> b
    $ (FieldNameDB -> Text) -> EntityDef -> NonEmpty Text
    Util.dbIdColumnsEsc FieldNameDB -> Text
    escapeF EntityDef
    ent
                ]

    execute' :: PG.Connection -> PG.Query -> [PersistValue] -> IO Int64
    execute' :: Connection -> Query -> [PersistValue] -> IO Int64
    execute' Connection
    conn Query
    query [PersistValue]
    vals = Connection -> Query -> [P] -> IO Int64
    forall q. ToRow q => Connection -> Query -> q -> IO Int64
    PG.execute Connection
    conn Query
    query ((PersistValue -> P) -> [PersistValue] -> [P]
    forall a b. (a -> b) -> [a] -> [b]
    map PersistValue -> P
    P [PersistValue]
    vals)

    withStmt'
        :: (MonadIO m)
        => PG.Connection
        -> PG.Query
        -> [PersistValue]
        -> Acquire (ConduitM () [PersistValue] m ())
    withStmt' :: forall (m :: * -> *).
    MonadIO m =>
    Connection
    -> Query
    -> [PersistValue]
    -> Acquire (ConduitM () [PersistValue] m ())
    withStmt' Connection
    conn Query
    query [PersistValue]
    vals =
        (Result, IORef Row, Row,
     [Maybe ConnectionString -> Conversion PersistValue])
    -> ConduitT () [PersistValue] m ()
    pull ((Result, IORef Row, Row,
      [Maybe ConnectionString -> Conversion PersistValue])
     -> ConduitT () [PersistValue] m ())
    -> Acquire
         (Result, IORef Row, Row,
          [Maybe ConnectionString -> Conversion PersistValue])
    -> Acquire (ConduitT () [PersistValue] m ())
    forall a b. (a -> b) -> Acquire a -> Acquire b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    `fmap` IO
      (Result, IORef Row, Row,
       [Maybe ConnectionString -> Conversion PersistValue])
    -> ((Result, IORef Row, Row,
         [Maybe ConnectionString -> Conversion PersistValue])
        -> IO ())
    -> Acquire
         (Result, IORef Row, Row,
          [Maybe ConnectionString -> Conversion PersistValue])
    forall a. IO a -> (a -> IO ()) -> Acquire a
    mkAcquire IO
      (Result, IORef Row, Row,
       [Maybe ConnectionString -> Conversion PersistValue])
    openS (Result, IORef Row, Row,
     [Maybe ConnectionString -> Conversion PersistValue])
    -> IO ()
    forall {b} {c} {d}. (Result, b, c, d) -> IO ()
    closeS
      where
        openS :: IO
      (Result, IORef Row, Row,
       [Maybe ConnectionString -> Conversion PersistValue])
    openS = do
            -- Construct raw query
            rawquery <- Connection -> Query -> [P] -> IO ConnectionString
    forall q.
    ToRow q =>
    Connection -> Query -> q -> IO ConnectionString
    PG.formatQuery Connection
    conn Query
    query ((PersistValue -> P) -> [PersistValue] -> [P]
    forall a b. (a -> b) -> [a] -> [b]
    map PersistValue -> P
    P [PersistValue]
    vals)

            -- Take raw connection
            (rt, rr, rc, ids) <- PG.withConnection conn $ \Connection
    rawconn -> do
                -- Execute query
                mret <- Connection -> ConnectionString -> IO (Maybe Result)
    LibPQ.exec Connection
    rawconn ConnectionString
    rawquery
                case mret of
                    Maybe Result
    Nothing -> do
                        merr <- Connection -> IO (Maybe ConnectionString)
    LibPQ.errorMessage Connection
    rawconn
                        fail $ case merr of
                            Maybe ConnectionString
    Nothing -> String
    "Postgresql.withStmt': unknown error"
                            Just ConnectionString
    e -> String
    "Postgresql.withStmt': " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++ ConnectionString -> String
    B8.unpack ConnectionString
    e
                    Just Result
    ret -> do
                        -- Check result status
                        status <- Result -> IO ExecStatus
    LibPQ.resultStatus Result
    ret
                        case status of
                            ExecStatus
    LibPQ.TuplesOk -> () -> IO ()
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
                            ExecStatus
    _ -> ConnectionString -> Result -> ExecStatus -> IO ()
    forall a. ConnectionString -> Result -> ExecStatus -> IO a
    PG.throwResultError ConnectionString
    "Postgresql.withStmt': bad result status " Result
    ret ExecStatus
    status

                        -- Get number and type of columns
                        cols <- LibPQ.nfields ret
                        oids <- forM [0 .. cols - 1] $ \Column
    col -> (Oid -> (Column, Oid)) -> IO Oid -> IO (Column, Oid)
    forall a b. (a -> b) -> IO a -> IO b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap ((,) Column
    col) (Result -> Column -> IO Oid
    LibPQ.ftype Result
    ret Column
    col)
                        -- Ready to go!
                        rowRef <- newIORef (LibPQ.Row 0)
                        rowCount <- LibPQ.ntuples ret
                        return (ret, rowRef, rowCount, oids)
            let
                getters =
                    ((Column, Oid)
     -> Maybe ConnectionString -> Conversion PersistValue)
    -> [(Column, Oid)]
    -> [Maybe ConnectionString -> Conversion PersistValue]
    forall a b. (a -> b) -> [a] -> [b]
    map (\(Column
    col, Oid
    oid) -> Oid -> Getter PersistValue
    getGetter Oid
    oid Getter PersistValue -> Getter PersistValue
    forall a b. (a -> b) -> a -> b
    $ Result -> Column -> Oid -> Field
    PG.Field Result
    rt Column
    col Oid
    oid) [(Column, Oid)]
    ids
            return (rt, rr, rc, getters)

        closeS :: (Result, b, c, d) -> IO ()
    closeS (Result
    ret, b
    _, c
    _, d
    _) = Result -> IO ()
    LibPQ.unsafeFreeResult Result
    ret

        pull :: (Result, IORef Row, Row,
     [Maybe ConnectionString -> Conversion PersistValue])
    -> ConduitT () [PersistValue] m ()
    pull (Result, IORef Row, Row,
     [Maybe ConnectionString -> Conversion PersistValue])
    x = do
            y <- IO (Maybe [PersistValue])
    -> ConduitT () [PersistValue] m (Maybe [PersistValue])
    forall a. IO a -> ConduitT () [PersistValue] m a
    forall (m :: * -> *) a. MonadIO m => IO a -> m a
    liftIO (IO (Maybe [PersistValue])
     -> ConduitT () [PersistValue] m (Maybe [PersistValue]))
    -> IO (Maybe [PersistValue])
    -> ConduitT () [PersistValue] m (Maybe [PersistValue])
    forall a b. (a -> b) -> a -> b
    $ (Result, IORef Row, Row,
     [Maybe ConnectionString -> Conversion PersistValue])
    -> IO (Maybe [PersistValue])
    pullS (Result, IORef Row, Row,
     [Maybe ConnectionString -> Conversion PersistValue])
    x
            case y of
                Maybe [PersistValue]
    Nothing -> () -> ConduitT () [PersistValue] m ()
    forall a. a -> ConduitT () [PersistValue] m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
                Just [PersistValue]
    z -> [PersistValue] -> ConduitT () [PersistValue] m ()
    forall (m :: * -> *) o i. Monad m => o -> ConduitT i o m ()
    yield [PersistValue]
    z ConduitT () [PersistValue] m ()
    -> ConduitT () [PersistValue] m ()
    -> ConduitT () [PersistValue] m ()
    forall a b.
    ConduitT () [PersistValue] m a
    -> ConduitT () [PersistValue] m b -> ConduitT () [PersistValue] m b
    forall (m :: * -> *) a b. Monad m => m a -> m b -> m b
    >> (Result, IORef Row, Row,
     [Maybe ConnectionString -> Conversion PersistValue])
    -> ConduitT () [PersistValue] m ()
    pull (Result, IORef Row, Row,
     [Maybe ConnectionString -> Conversion PersistValue])
    x

        pullS :: (Result, IORef Row, Row,
     [Maybe ConnectionString -> Conversion PersistValue])
    -> IO (Maybe [PersistValue])
    pullS (Result
    ret, IORef Row
    rowRef, Row
    rowCount, [Maybe ConnectionString -> Conversion PersistValue]
    getters) = do
            row <- IORef Row -> (Row -> (Row, Row)) -> IO Row
    forall a b. IORef a -> (a -> (a, b)) -> IO b
    atomicModifyIORef IORef Row
    rowRef (\Row
    r -> (Row
    r Row -> Row -> Row
    forall a. Num a => a -> a -> a
    + Row
    1, Row
    r))
            if row == rowCount
                then return Nothing
                else fmap Just $ forM (zip getters [0 ..]) $ \(Maybe ConnectionString -> Conversion PersistValue
    getter, Column
    col) -> do
                    mbs <- Result -> Row -> Column -> IO (Maybe ConnectionString)
    LibPQ.getvalue' Result
    ret Row
    row Column
    col
                    case mbs of
                        Maybe ConnectionString
    Nothing ->
                            -- getvalue' verified that the value is NULL.
                            -- However, that does not mean that there are
                            -- no NULL values inside the value (e.g., if
                            -- we're dealing with an array of optional values).
                            PersistValue -> IO PersistValue
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return PersistValue
    PersistNull
                        Just ConnectionString
    bs -> do
                            ok <- Conversion PersistValue -> Connection -> IO (Ok PersistValue)
    forall a. Conversion a -> Connection -> IO (Ok a)
    PGFF.runConversion (Maybe ConnectionString -> Conversion PersistValue
    getter Maybe ConnectionString
    mbs) Connection
    conn
                            bs `seq` case ok of
                                Errors (SomeException
    exc : [SomeException]
    _) -> SomeException -> IO PersistValue
    forall a e. (HasCallStack, Exception e) => e -> a
    throw SomeException
    exc
                                Errors [] -> String -> IO PersistValue
    forall a. HasCallStack => String -> a
    error String
    "Got an Errors, but no exceptions"
                                Ok PersistValue
    v -> PersistValue -> IO PersistValue
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return PersistValue
    v

    migrate'
        :: [EntityDef]
        -> (Text -> IO Statement)
        -> EntityDef
        -> IO (Either [Text] CautiousMigration)
    migrate' :: [EntityDef]
    -> (Text -> IO Statement)
    -> EntityDef
    -> IO (Either [Text] [(Bool, Text)])
    migrate' [EntityDef]
    allDefs Text -> IO Statement
    getter EntityDef
    entity = (Either [Text] [AlterDB] -> Either [Text] [(Bool, Text)])
    -> IO (Either [Text] [AlterDB])
    -> IO (Either [Text] [(Bool, Text)])
    forall a b. (a -> b) -> IO a -> IO b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (([AlterDB] -> [(Bool, Text)])
    -> Either [Text] [AlterDB] -> Either [Text] [(Bool, Text)]
    forall a b. (a -> b) -> Either [Text] a -> Either [Text] b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (([AlterDB] -> [(Bool, Text)])
     -> Either [Text] [AlterDB] -> Either [Text] [(Bool, Text)])
    -> ([AlterDB] -> [(Bool, Text)])
    -> Either [Text] [AlterDB]
    -> Either [Text] [(Bool, Text)]
    forall a b. (a -> b) -> a -> b
    $ (AlterDB -> (Bool, Text)) -> [AlterDB] -> [(Bool, Text)]
    forall a b. (a -> b) -> [a] -> [b]
    map AlterDB -> (Bool, Text)
    showAlterDb) (IO (Either [Text] [AlterDB]) -> IO (Either [Text] [(Bool, Text)]))
    -> IO (Either [Text] [AlterDB])
    -> IO (Either [Text] [(Bool, Text)])
    forall a b. (a -> b) -> a -> b
    $ [EntityDef]
    -> (Text -> IO Statement)
    -> EntityDef
    -> IO (Either [Text] [AlterDB])
    migrateStructured [EntityDef]
    allDefs Text -> IO Statement
    getter EntityDef
    entity

    -- | Get the SQL string for the table that a PersistEntity represents.
    -- Useful for raw SQL queries.
    tableName :: (PersistEntity record) => record -> Text
    tableName :: forall record. PersistEntity record => record -> Text
    tableName = EntityNameDB -> Text
    escapeE (EntityNameDB -> Text)
    -> (record -> EntityNameDB) -> record -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . record -> EntityNameDB
    forall record. PersistEntity record => record -> EntityNameDB
    tableDBName

    -- | Get the SQL string for the field that an EntityField represents.
    -- Useful for raw SQL queries.
    fieldName :: (PersistEntity record) => EntityField record typ -> Text
    fieldName :: forall record typ.
    PersistEntity record =>
    EntityField record typ -> Text
    fieldName = FieldNameDB -> Text
    escapeF (FieldNameDB -> Text)
    -> (EntityField record typ -> FieldNameDB)
    -> EntityField record typ
    -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . EntityField record typ -> FieldNameDB
    forall record typ.
    PersistEntity record =>
    EntityField record typ -> FieldNameDB
    fieldDBName

    -- | Information required to connect to a PostgreSQL database
    -- using @persistent@'s generic facilities.  These values are the
    -- same that are given to 'withPostgresqlPool'.
    data PostgresConf = PostgresConf
        { PostgresConf -> ConnectionString
    pgConnStr :: ConnectionString
        -- ^ The connection string.
        , -- TODO: Currently stripes, idle timeout, and pool size are all separate fields
          -- When Persistent next does a large breaking release (3.0?), we should consider making these just a single ConnectionPoolConfig value
          --
          -- Currently there the idle timeout is an Integer, rather than resource-pool's NominalDiffTime type.
          -- This is because the time package only recently added the Read instance for NominalDiffTime.
          -- Future TODO: Consider removing the Read instance, and/or making the idle timeout a NominalDiffTime.

          PostgresConf -> Int
    pgPoolStripes :: Int
        -- ^ How many stripes to divide the pool into. See "Data.Pool" for details.
        -- @since 2.11.0.0
        , PostgresConf -> Integer
    pgPoolIdleTimeout :: Integer -- Ideally this would be a NominalDiffTime, but that type lacks a Read instance https://github.com/haskell/time/issues/130

        -- ^ How long connections can remain idle before being disposed of, in seconds.
        -- @since 2.11.0.0
        , PostgresConf -> Int
    pgPoolSize :: Int
        -- ^ How many connections should be held in the connection pool.
        }
        deriving (Int -> PostgresConf -> ShowS
    [PostgresConf] -> ShowS
    PostgresConf -> String
    (Int -> PostgresConf -> ShowS)
    -> (PostgresConf -> String)
    -> ([PostgresConf] -> ShowS)
    -> Show PostgresConf
    forall a.
    (Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
    $cshowsPrec :: Int -> PostgresConf -> ShowS
    showsPrec :: Int -> PostgresConf -> ShowS
    $cshow :: PostgresConf -> String
    show :: PostgresConf -> String
    $cshowList :: [PostgresConf] -> ShowS
    showList :: [PostgresConf] -> ShowS
    Show, ReadPrec [PostgresConf]
    ReadPrec PostgresConf
    Int -> ReadS PostgresConf
    ReadS [PostgresConf]
    (Int -> ReadS PostgresConf)
    -> ReadS [PostgresConf]
    -> ReadPrec PostgresConf
    -> ReadPrec [PostgresConf]
    -> Read PostgresConf
    forall a.
    (Int -> ReadS a)
    -> ReadS [a] -> ReadPrec a -> ReadPrec [a] -> Read a
    $creadsPrec :: Int -> ReadS PostgresConf
    readsPrec :: Int -> ReadS PostgresConf
    $creadList :: ReadS [PostgresConf]
    readList :: ReadS [PostgresConf]
    $creadPrec :: ReadPrec PostgresConf
    readPrec :: ReadPrec PostgresConf
    $creadListPrec :: ReadPrec [PostgresConf]
    readListPrec :: ReadPrec [PostgresConf]
    Read, Typeable PostgresConf
    Typeable PostgresConf =>
    (forall (c :: * -> *).
     (forall d b. Data d => c (d -> b) -> d -> c b)
     -> (forall g. g -> c g) -> PostgresConf -> c PostgresConf)
    -> (forall (c :: * -> *).
        (forall b r. Data b => c (b -> r) -> c r)
        -> (forall r. r -> c r) -> Constr -> c PostgresConf)
    -> (PostgresConf -> Constr)
    -> (PostgresConf -> DataType)
    -> (forall (t :: * -> *) (c :: * -> *).
        Typeable t =>
        (forall d. Data d => c (t d)) -> Maybe (c PostgresConf))
    -> (forall (t :: * -> * -> *) (c :: * -> *).
        Typeable t =>
        (forall d e. (Data d, Data e) => c (t d e))
        -> Maybe (c PostgresConf))
    -> ((forall b. Data b => b -> b) -> PostgresConf -> PostgresConf)
    -> (forall r r'.
        (r -> r' -> r)
        -> r -> (forall d. Data d => d -> r') -> PostgresConf -> r)
    -> (forall r r'.
        (r' -> r -> r)
        -> r -> (forall d. Data d => d -> r') -> PostgresConf -> r)
    -> (forall u. (forall d. Data d => d -> u) -> PostgresConf -> [u])
    -> (forall u.
        Int -> (forall d. Data d => d -> u) -> PostgresConf -> u)
    -> (forall (m :: * -> *).
        Monad m =>
        (forall d. Data d => d -> m d) -> PostgresConf -> m PostgresConf)
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> PostgresConf -> m PostgresConf)
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> PostgresConf -> m PostgresConf)
    -> Data PostgresConf
    PostgresConf -> Constr
    PostgresConf -> DataType
    (forall b. Data b => b -> b) -> PostgresConf -> PostgresConf
    forall a.
    Typeable a =>
    (forall (c :: * -> *).
     (forall d b. Data d => c (d -> b) -> d -> c b)
     -> (forall g. g -> c g) -> a -> c a)
    -> (forall (c :: * -> *).
        (forall b r. Data b => c (b -> r) -> c r)
        -> (forall r. r -> c r) -> Constr -> c a)
    -> (a -> Constr)
    -> (a -> DataType)
    -> (forall (t :: * -> *) (c :: * -> *).
        Typeable t =>
        (forall d. Data d => c (t d)) -> Maybe (c a))
    -> (forall (t :: * -> * -> *) (c :: * -> *).
        Typeable t =>
        (forall d e. (Data d, Data e) => c (t d e)) -> Maybe (c a))
    -> ((forall b. Data b => b -> b) -> a -> a)
    -> (forall r r'.
        (r -> r' -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
    -> (forall r r'.
        (r' -> r -> r) -> r -> (forall d. Data d => d -> r') -> a -> r)
    -> (forall u. (forall d. Data d => d -> u) -> a -> [u])
    -> (forall u. Int -> (forall d. Data d => d -> u) -> a -> u)
    -> (forall (m :: * -> *).
        Monad m =>
        (forall d. Data d => d -> m d) -> a -> m a)
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> a -> m a)
    -> (forall (m :: * -> *).
        MonadPlus m =>
        (forall d. Data d => d -> m d) -> a -> m a)
    -> Data a
    forall u. Int -> (forall d. Data d => d -> u) -> PostgresConf -> u
    forall u. (forall d. Data d => d -> u) -> PostgresConf -> [u]
    forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> PostgresConf -> r
    forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> PostgresConf -> r
    forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> PostgresConf -> m PostgresConf
    forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> PostgresConf -> m PostgresConf
    forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c PostgresConf
    forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> PostgresConf -> c PostgresConf
    forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c PostgresConf)
    forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c PostgresConf)
    $cgfoldl :: forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> PostgresConf -> c PostgresConf
    gfoldl :: forall (c :: * -> *).
    (forall d b. Data d => c (d -> b) -> d -> c b)
    -> (forall g. g -> c g) -> PostgresConf -> c PostgresConf
    $cgunfold :: forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c PostgresConf
    gunfold :: forall (c :: * -> *).
    (forall b r. Data b => c (b -> r) -> c r)
    -> (forall r. r -> c r) -> Constr -> c PostgresConf
    $ctoConstr :: PostgresConf -> Constr
    toConstr :: PostgresConf -> Constr
    $cdataTypeOf :: PostgresConf -> DataType
    dataTypeOf :: PostgresConf -> DataType
    $cdataCast1 :: forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c PostgresConf)
    dataCast1 :: forall (t :: * -> *) (c :: * -> *).
    Typeable t =>
    (forall d. Data d => c (t d)) -> Maybe (c PostgresConf)
    $cdataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c PostgresConf)
    dataCast2 :: forall (t :: * -> * -> *) (c :: * -> *).
    Typeable t =>
    (forall d e. (Data d, Data e) => c (t d e))
    -> Maybe (c PostgresConf)
    $cgmapT :: (forall b. Data b => b -> b) -> PostgresConf -> PostgresConf
    gmapT :: (forall b. Data b => b -> b) -> PostgresConf -> PostgresConf
    $cgmapQl :: forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> PostgresConf -> r
    gmapQl :: forall r r'.
    (r -> r' -> r)
    -> r -> (forall d. Data d => d -> r') -> PostgresConf -> r
    $cgmapQr :: forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> PostgresConf -> r
    gmapQr :: forall r r'.
    (r' -> r -> r)
    -> r -> (forall d. Data d => d -> r') -> PostgresConf -> r
    $cgmapQ :: forall u. (forall d. Data d => d -> u) -> PostgresConf -> [u]
    gmapQ :: forall u. (forall d. Data d => d -> u) -> PostgresConf -> [u]
    $cgmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> PostgresConf -> u
    gmapQi :: forall u. Int -> (forall d. Data d => d -> u) -> PostgresConf -> u
    $cgmapM :: forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> PostgresConf -> m PostgresConf
    gmapM :: forall (m :: * -> *).
    Monad m =>
    (forall d. Data d => d -> m d) -> PostgresConf -> m PostgresConf
    $cgmapMp :: forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> PostgresConf -> m PostgresConf
    gmapMp :: forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> PostgresConf -> m PostgresConf
    $cgmapMo :: forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> PostgresConf -> m PostgresConf
    gmapMo :: forall (m :: * -> *).
    MonadPlus m =>
    (forall d. Data d => d -> m d) -> PostgresConf -> m PostgresConf
    Data)

    instance FromJSON PostgresConf where
        parseJSON :: Value -> Parser PostgresConf
    parseJSON Value
    v = ShowS -> Parser PostgresConf -> Parser PostgresConf
    forall a. ShowS -> Parser a -> Parser a
    modifyFailure (String
    "Persistent: error loading PostgreSQL conf: " String -> ShowS
    forall a. [a] -> [a] -> [a]
    ++) (Parser PostgresConf -> Parser PostgresConf)
    -> Parser PostgresConf -> Parser PostgresConf
    forall a b. (a -> b) -> a -> b
    $
            ((Object -> Parser PostgresConf) -> Value -> Parser PostgresConf)
    -> Value -> (Object -> Parser PostgresConf) -> Parser PostgresConf
    forall a b c. (a -> b -> c) -> b -> a -> c
    flip (String
    -> (Object -> Parser PostgresConf) -> Value -> Parser PostgresConf
    forall a. String -> (Object -> Parser a) -> Value -> Parser a
    withObject String
    "PostgresConf") Value
    v ((Object -> Parser PostgresConf) -> Parser PostgresConf)
    -> (Object -> Parser PostgresConf) -> Parser PostgresConf
    forall a b. (a -> b) -> a -> b
    $ \Object
    o -> do
                let
                    defaultPoolConfig :: ConnectionPoolConfig
    defaultPoolConfig = ConnectionPoolConfig
    defaultConnectionPoolConfig
                database <- Object
    o Object -> Key -> Parser String
    forall a. FromJSON a => Object -> Key -> Parser a
    .: Key
    "database"
                host <- o .: "host"
                port <- o .:? "port" .!= 5432
                user <- o .: "user"
                password <- o .: "password"
                poolSize <- o .:? "poolsize" .!= (connectionPoolConfigSize defaultPoolConfig)
                poolStripes <-
                    o .:? "stripes" .!= (connectionPoolConfigStripes defaultPoolConfig)
                poolIdleTimeout <-
                    o
                        .:? "idleTimeout"
                        .!= (floor $ connectionPoolConfigIdleTimeout defaultPoolConfig)
                let
                    ci =
                        PG.ConnectInfo
                            { connectHost :: String
    PG.connectHost = String
    host
                            , connectPort :: Word16
    PG.connectPort = Word16
    port
                            , connectUser :: String
    PG.connectUser = String
    user
                            , connectPassword :: String
    PG.connectPassword = String
    password
                            , connectDatabase :: String
    PG.connectDatabase = String
    database
                            }
                    cstr = ConnectInfo -> ConnectionString
    PG.postgreSQLConnectionString ConnectInfo
    ci
                return $ PostgresConf cstr poolStripes poolIdleTimeout poolSize
    instance PersistConfig PostgresConf where
        type PersistConfigBackend PostgresConf = SqlPersistT
        type PersistConfigPool PostgresConf = ConnectionPool
        createPoolConfig :: PostgresConf -> IO (PersistConfigPool PostgresConf)
    createPoolConfig PostgresConf
    conf = NoLoggingT IO (PersistConfigPool PostgresConf)
    -> IO (PersistConfigPool PostgresConf)
    forall (m :: * -> *) a. NoLoggingT m a -> m a
    runNoLoggingT (NoLoggingT IO (PersistConfigPool PostgresConf)
     -> IO (PersistConfigPool PostgresConf))
    -> NoLoggingT IO (PersistConfigPool PostgresConf)
    -> IO (PersistConfigPool PostgresConf)
    forall a b. (a -> b) -> a -> b
    $ PostgresConf
    -> PostgresConfHooks -> NoLoggingT IO (Pool SqlBackend)
    forall (m :: * -> *).
    (MonadUnliftIO m, MonadLoggerIO m) =>
    PostgresConf -> PostgresConfHooks -> m (Pool SqlBackend)
    createPostgresqlPoolWithConf PostgresConf
    conf PostgresConfHooks
    defaultPostgresConfHooks
        runPool :: forall (m :: * -> *) a.
    MonadUnliftIO m =>
    PostgresConf
    -> PersistConfigBackend PostgresConf m a
    -> PersistConfigPool PostgresConf
    -> m a
    runPool PostgresConf
    _ = ReaderT SqlBackend m a -> Pool SqlBackend -> m a
    PersistConfigBackend PostgresConf m a
    -> PersistConfigPool PostgresConf -> m a
    forall backend (m :: * -> *) a.
    (MonadUnliftIO m, BackendCompatible SqlBackend backend) =>
    ReaderT backend m a -> Pool backend -> m a
    runSqlPool
        loadConfig :: Value -> Parser PostgresConf
    loadConfig = Value -> Parser PostgresConf
    forall a. FromJSON a => Value -> Parser a
    parseJSON

        applyEnv :: PostgresConf -> IO PostgresConf
    applyEnv PostgresConf
    c0 = do
            env <- IO [(String, String)]
    getEnvironment
            return $
                addUser env $
                    addPass env $
                        addDatabase env $
                            addPort env $
                                addHost env c0
          where
            addParam :: ConnectionString -> String -> PostgresConf -> PostgresConf
    addParam ConnectionString
    param String
    val PostgresConf
    c =
                PostgresConf
    c{pgConnStr = B8.concat [pgConnStr c, " ", param, "='", pgescape val, "'"]}

            pgescape :: String -> ConnectionString
    pgescape = String -> ConnectionString
    B8.pack (String -> ConnectionString) -> ShowS -> String -> ConnectionString
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . ShowS
    go
              where
                go :: ShowS
    go (Char
    '\'' : String
    rest) = Char
    '\\' Char -> ShowS
    forall a. a -> [a] -> [a]
    : Char
    '\'' Char -> ShowS
    forall a. a -> [a] -> [a]
    : ShowS
    go String
    rest
                go (Char
    '\\' : String
    rest) = Char
    '\\' Char -> ShowS
    forall a. a -> [a] -> [a]
    : Char
    '\\' Char -> ShowS
    forall a. a -> [a] -> [a]
    : ShowS
    go String
    rest
                go (Char
    x : String
    rest) = Char
    x Char -> ShowS
    forall a. a -> [a] -> [a]
    : ShowS
    go String
    rest
                go [] = []

            maybeAddParam :: ConnectionString
    -> a -> [(a, String)] -> PostgresConf -> PostgresConf
    maybeAddParam ConnectionString
    param a
    envvar [(a, String)]
    env =
                (PostgresConf -> PostgresConf)
    -> (String -> PostgresConf -> PostgresConf)
    -> Maybe String
    -> PostgresConf
    -> PostgresConf
    forall b a. b -> (a -> b) -> Maybe a -> b
    maybe PostgresConf -> PostgresConf
    forall a. a -> a
    id (ConnectionString -> String -> PostgresConf -> PostgresConf
    addParam ConnectionString
    param) (Maybe String -> PostgresConf -> PostgresConf)
    -> Maybe String -> PostgresConf -> PostgresConf
    forall a b. (a -> b) -> a -> b
    $
                    a -> [(a, String)] -> Maybe String
    forall a b. Eq a => a -> [(a, b)] -> Maybe b
    lookup a
    envvar [(a, String)]
    env

            addHost :: [(String, String)] -> PostgresConf -> PostgresConf
    addHost = ConnectionString
    -> String -> [(String, String)] -> PostgresConf -> PostgresConf
    forall {a}.
    Eq a =>
    ConnectionString
    -> a -> [(a, String)] -> PostgresConf -> PostgresConf
    maybeAddParam ConnectionString
    "host" String
    "PGHOST"
            addPort :: [(String, String)] -> PostgresConf -> PostgresConf
    addPort = ConnectionString
    -> String -> [(String, String)] -> PostgresConf -> PostgresConf
    forall {a}.
    Eq a =>
    ConnectionString
    -> a -> [(a, String)] -> PostgresConf -> PostgresConf
    maybeAddParam ConnectionString
    "port" String
    "PGPORT"
            addUser :: [(String, String)] -> PostgresConf -> PostgresConf
    addUser = ConnectionString
    -> String -> [(String, String)] -> PostgresConf -> PostgresConf
    forall {a}.
    Eq a =>
    ConnectionString
    -> a -> [(a, String)] -> PostgresConf -> PostgresConf
    maybeAddParam ConnectionString
    "user" String
    "PGUSER"
            addPass :: [(String, String)] -> PostgresConf -> PostgresConf
    addPass = ConnectionString
    -> String -> [(String, String)] -> PostgresConf -> PostgresConf
    forall {a}.
    Eq a =>
    ConnectionString
    -> a -> [(a, String)] -> PostgresConf -> PostgresConf
    maybeAddParam ConnectionString
    "password" String
    "PGPASS"
            addDatabase :: [(String, String)] -> PostgresConf -> PostgresConf
    addDatabase = ConnectionString
    -> String -> [(String, String)] -> PostgresConf -> PostgresConf
    forall {a}.
    Eq a =>
    ConnectionString
    -> a -> [(a, String)] -> PostgresConf -> PostgresConf
    maybeAddParam ConnectionString
    "dbname" String
    "PGDATABASE"

    -- | Hooks for configuring the Persistent/its connection to Postgres
    --
    -- @since 2.11.0
    data PostgresConfHooks = PostgresConfHooks
        { PostgresConfHooks -> Connection -> IO (NonEmpty Word)
    pgConfHooksGetServerVersion :: PG.Connection -> IO (NonEmpty Word)
        -- ^ Function to get the version of Postgres
        --
        -- The default implementation queries the server with "show server_version".
        -- Some variants of Postgres, such as Redshift, don't support showing the version.
        -- It's recommended you return a hardcoded version in those cases.
        --
        -- @since 2.11.0
        , PostgresConfHooks -> Connection -> IO ()
    pgConfHooksAfterCreate :: PG.Connection -> IO ()
        -- ^ Action to perform after a connection is created.
        --
        -- Typical uses of this are modifying the connection (e.g. to set the schema) or logging a connection being created.
        --
        -- The default implementation does nothing.
        --
        -- @since 2.11.0
        }

    -- | Default settings for 'PostgresConfHooks'. See the individual fields of 'PostgresConfHooks' for the default values.
    --
    -- @since 2.11.0
    defaultPostgresConfHooks :: PostgresConfHooks
    defaultPostgresConfHooks :: PostgresConfHooks
    defaultPostgresConfHooks =
        PostgresConfHooks
            { pgConfHooksGetServerVersion :: Connection -> IO (NonEmpty Word)
    pgConfHooksGetServerVersion = Connection -> IO (NonEmpty Word)
    getServerVersionNonEmpty
            , pgConfHooksAfterCreate :: Connection -> IO ()
    pgConfHooksAfterCreate = IO () -> Connection -> IO ()
    forall a b. a -> b -> a
    const (IO () -> Connection -> IO ()) -> IO () -> Connection -> IO ()
    forall a b. (a -> b) -> a -> b
    $ () -> IO ()
    forall a. a -> IO a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure ()
            }

    mockMigrate
        :: [EntityDef]
        -> (Text -> IO Statement)
        -> EntityDef
        -> IO (Either [Text] [(Bool, Text)])
    mockMigrate :: [EntityDef]
    -> (Text -> IO Statement)
    -> EntityDef
    -> IO (Either [Text] [(Bool, Text)])
    mockMigrate [EntityDef]
    allDefs Text -> IO Statement
    _ EntityDef
    entity =
        (Either [Text] [AlterDB] -> Either [Text] [(Bool, Text)])
    -> IO (Either [Text] [AlterDB])
    -> IO (Either [Text] [(Bool, Text)])
    forall a b. (a -> b) -> IO a -> IO b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (([AlterDB] -> [(Bool, Text)])
    -> Either [Text] [AlterDB] -> Either [Text] [(Bool, Text)]
    forall a b. (a -> b) -> Either [Text] a -> Either [Text] b
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    fmap (([AlterDB] -> [(Bool, Text)])
     -> Either [Text] [AlterDB] -> Either [Text] [(Bool, Text)])
    -> ([AlterDB] -> [(Bool, Text)])
    -> Either [Text] [AlterDB]
    -> Either [Text] [(Bool, Text)]
    forall a b. (a -> b) -> a -> b
    $ (AlterDB -> (Bool, Text)) -> [AlterDB] -> [(Bool, Text)]
    forall a b. (a -> b) -> [a] -> [b]
    map AlterDB -> (Bool, Text)
    showAlterDb) (IO (Either [Text] [AlterDB]) -> IO (Either [Text] [(Bool, Text)]))
    -> IO (Either [Text] [AlterDB])
    -> IO (Either [Text] [(Bool, Text)])
    forall a b. (a -> b) -> a -> b
    $
            Either [Text] [AlterDB] -> IO (Either [Text] [AlterDB])
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (Either [Text] [AlterDB] -> IO (Either [Text] [AlterDB]))
    -> Either [Text] [AlterDB] -> IO (Either [Text] [AlterDB])
    forall a b. (a -> b) -> a -> b
    $
                [AlterDB] -> Either [Text] [AlterDB]
    forall a b. b -> Either a b
    Right ([AlterDB] -> Either [Text] [AlterDB])
    -> [AlterDB] -> Either [Text] [AlterDB]
    forall a b. (a -> b) -> a -> b
    $
                    [EntityDef] -> EntityDef -> [AlterDB]
    mockMigrateStructured [EntityDef]
    allDefs EntityDef
    entity

    -- | Mock a migration even when the database is not present.
    -- This function performs the same functionality of 'printMigration'
    -- with the difference that an actual database is not needed.
    mockMigration :: Migration -> IO ()
    mockMigration :: Migration -> IO ()
    mockMigration Migration
    mig = do
        smap <- Map Text Statement -> IO (IORef (Map Text Statement))
    forall a. a -> IO (IORef a)
    newIORef Map Text Statement
    forall a. Monoid a => a
    mempty
        let
            sqlbackend =
                MkSqlBackendArgs -> SqlBackend
    mkSqlBackend
                    MkSqlBackendArgs
                        { connPrepare :: Text -> IO Statement
    connPrepare = \Text
    _ -> do
                            Statement -> IO Statement
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return
                                Statement
                                    { stmtFinalize :: IO ()
    stmtFinalize = () -> IO ()
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
                                    , stmtReset :: IO ()
    stmtReset = () -> IO ()
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
                                    , stmtExecute :: [PersistValue] -> IO Int64
    stmtExecute = [PersistValue] -> IO Int64
    forall a. HasCallStack => a
    undefined
                                    , stmtQuery :: forall (m :: * -> *).
    MonadIO m =>
    [PersistValue] -> Acquire (ConduitM () [PersistValue] m ())
    stmtQuery = \[PersistValue]
    _ -> ConduitM () [PersistValue] m ()
    -> Acquire (ConduitM () [PersistValue] m ())
    forall a. a -> Acquire a
    forall (m :: * -> *) a. Monad m => a -> m a
    return (ConduitM () [PersistValue] m ()
     -> Acquire (ConduitM () [PersistValue] m ()))
    -> ConduitM () [PersistValue] m ()
    -> Acquire (ConduitM () [PersistValue] m ())
    forall a b. (a -> b) -> a -> b
    $ () -> ConduitM () [PersistValue] m ()
    forall a. a -> ConduitT () [PersistValue] m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
                                    }
                        , connInsertSql :: EntityDef -> [PersistValue] -> InsertSqlResult
    connInsertSql = EntityDef -> [PersistValue] -> InsertSqlResult
    forall a. HasCallStack => a
    undefined
                        , connStmtMap :: IORef (Map Text Statement)
    connStmtMap = IORef (Map Text Statement)
    smap
                        , connClose :: IO ()
    connClose = IO ()
    forall a. HasCallStack => a
    undefined
                        , connMigrateSql :: [EntityDef]
    -> (Text -> IO Statement)
    -> EntityDef
    -> IO (Either [Text] [(Bool, Text)])
    connMigrateSql = [EntityDef]
    -> (Text -> IO Statement)
    -> EntityDef
    -> IO (Either [Text] [(Bool, Text)])
    mockMigrate
                        , connBegin :: (Text -> IO Statement) -> Maybe IsolationLevel -> IO ()
    connBegin = (Text -> IO Statement) -> Maybe IsolationLevel -> IO ()
    forall a. HasCallStack => a
    undefined
                        , connCommit :: (Text -> IO Statement) -> IO ()
    connCommit = (Text -> IO Statement) -> IO ()
    forall a. HasCallStack => a
    undefined
                        , connRollback :: (Text -> IO Statement) -> IO ()
    connRollback = (Text -> IO Statement) -> IO ()
    forall a. HasCallStack => a
    undefined
                        , connEscapeFieldName :: FieldNameDB -> Text
    connEscapeFieldName = FieldNameDB -> Text
    escapeF
                        , connEscapeTableName :: EntityDef -> Text
    connEscapeTableName = EntityNameDB -> Text
    escapeE (EntityNameDB -> Text)
    -> (EntityDef -> EntityNameDB) -> EntityDef -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . EntityDef -> EntityNameDB
    getEntityDBName
                        , connEscapeRawName :: Text -> Text
    connEscapeRawName = Text -> Text
    escape
                        , connNoLimit :: Text
    connNoLimit = Text
    forall a. HasCallStack => a
    undefined
                        , connRDBMS :: Text
    connRDBMS = Text
    forall a. HasCallStack => a
    undefined
                        , connLimitOffset :: (Int, Int) -> Text -> Text
    connLimitOffset = (Int, Int) -> Text -> Text
    forall a. HasCallStack => a
    undefined
                        , connLogFunc :: LogFunc
    connLogFunc = LogFunc
    forall a. HasCallStack => a
    undefined
                        }
            result = ReaderT SqlBackend IO (((), [Text]), [(Bool, Text)])
    -> SqlBackend -> IO (((), [Text]), [(Bool, Text)])
    forall r (m :: * -> *) a. ReaderT r m a -> r -> m a
    runReaderT (ReaderT SqlBackend IO (((), [Text]), [(Bool, Text)])
     -> SqlBackend -> IO (((), [Text]), [(Bool, Text)]))
    -> ReaderT SqlBackend IO (((), [Text]), [(Bool, Text)])
    -> SqlBackend
    -> IO (((), [Text]), [(Bool, Text)])
    forall a b. (a -> b) -> a -> b
    $ WriterT [(Bool, Text)] (ReaderT SqlBackend IO) ((), [Text])
    -> ReaderT SqlBackend IO (((), [Text]), [(Bool, Text)])
    forall w (m :: * -> *) a. WriterT w m a -> m (a, w)
    runWriterT (WriterT [(Bool, Text)] (ReaderT SqlBackend IO) ((), [Text])
     -> ReaderT SqlBackend IO (((), [Text]), [(Bool, Text)]))
    -> WriterT [(Bool, Text)] (ReaderT SqlBackend IO) ((), [Text])
    -> ReaderT SqlBackend IO (((), [Text]), [(Bool, Text)])
    forall a b. (a -> b) -> a -> b
    $ Migration
    -> WriterT [(Bool, Text)] (ReaderT SqlBackend IO) ((), [Text])
    forall w (m :: * -> *) a. WriterT w m a -> m (a, w)
    runWriterT Migration
    mig
        resp <- result sqlbackend
        mapM_ T.putStrLn $ map snd $ snd resp

    putManySql :: EntityDef -> Int -> Text
    putManySql :: EntityDef -> Int -> Text
    putManySql EntityDef
    ent Int
    n = [Text] -> [FieldDef] -> EntityDef -> Int -> Text
    putManySql' [Text]
    conflictColumns [FieldDef]
    fields EntityDef
    ent Int
    n
      where
        fields :: [FieldDef]
    fields = EntityDef -> [FieldDef]
    getEntityFields EntityDef
    ent
        conflictColumns :: [Text]
    conflictColumns =
            (UniqueDef -> [Text]) -> [UniqueDef] -> [Text]
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap
                (((FieldNameHS, FieldNameDB) -> Text)
    -> [(FieldNameHS, FieldNameDB)] -> [Text]
    forall a b. (a -> b) -> [a] -> [b]
    map (FieldNameDB -> Text
    escapeF (FieldNameDB -> Text)
    -> ((FieldNameHS, FieldNameDB) -> FieldNameDB)
    -> (FieldNameHS, FieldNameDB)
    -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (FieldNameHS, FieldNameDB) -> FieldNameDB
    forall a b. (a, b) -> b
    snd) ([(FieldNameHS, FieldNameDB)] -> [Text])
    -> (UniqueDef -> [(FieldNameHS, FieldNameDB)])
    -> UniqueDef
    -> [Text]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . NonEmpty (FieldNameHS, FieldNameDB) -> [(FieldNameHS, FieldNameDB)]
    forall a. NonEmpty a -> [a]
    NEL.toList (NonEmpty (FieldNameHS, FieldNameDB)
     -> [(FieldNameHS, FieldNameDB)])
    -> (UniqueDef -> NonEmpty (FieldNameHS, FieldNameDB))
    -> UniqueDef
    -> [(FieldNameHS, FieldNameDB)]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . UniqueDef -> NonEmpty (FieldNameHS, FieldNameDB)
    uniqueFields)
                (EntityDef -> [UniqueDef]
    getEntityUniques EntityDef
    ent)

    repsertManySql :: EntityDef -> Int -> Text
    repsertManySql :: EntityDef -> Int -> Text
    repsertManySql EntityDef
    ent Int
    n = [Text] -> [FieldDef] -> EntityDef -> Int -> Text
    putManySql' [Text]
    conflictColumns [FieldDef]
    fields EntityDef
    ent Int
    n
      where
        fields :: [FieldDef]
    fields = NonEmpty FieldDef -> [FieldDef]
    forall a. NonEmpty a -> [a]
    NEL.toList (NonEmpty FieldDef -> [FieldDef])
    -> NonEmpty FieldDef -> [FieldDef]
    forall a b. (a -> b) -> a -> b
    $ EntityDef -> NonEmpty FieldDef
    keyAndEntityFields EntityDef
    ent
        conflictColumns :: [Text]
    conflictColumns = NonEmpty Text -> [Text]
    forall a. NonEmpty a -> [a]
    NEL.toList (NonEmpty Text -> [Text]) -> NonEmpty Text -> [Text]
    forall a b. (a -> b) -> a -> b
    $ FieldNameDB -> Text
    escapeF (FieldNameDB -> Text)
    -> (FieldDef -> FieldNameDB) -> FieldDef -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . FieldDef -> FieldNameDB
    fieldDB (FieldDef -> Text) -> NonEmpty FieldDef -> NonEmpty Text
    forall (f :: * -> *) a b. Functor f => (a -> b) -> f a -> f b
    <$> EntityDef -> NonEmpty FieldDef
    getEntityKeyFields EntityDef
    ent

    -- | This type is used to determine how to update rows using Postgres'
    -- @INSERT ... ON CONFLICT KEY UPDATE@ functionality, exposed via
    -- 'upsertWhere' and 'upsertManyWhere' in this library.
    --
    -- @since 2.12.1.0
    data HandleUpdateCollision record where
        -- | Copy the field directly from the record.
        CopyField :: EntityField record typ -> HandleUpdateCollision record
        -- | Only copy the field if it is not equal to the provided value.
        CopyUnlessEq
            :: (PersistField typ)
            => EntityField record typ
            -> typ
            -> HandleUpdateCollision record

    -- | Copy the field into the database only if the value in the
    -- corresponding record is non-@NULL@.
    --
    -- @since  2.12.1.0
    copyUnlessNull
        :: (PersistField typ)
        => EntityField record (Maybe typ)
        -> HandleUpdateCollision record
    copyUnlessNull :: forall typ record.
    PersistField typ =>
    EntityField record (Maybe typ) -> HandleUpdateCollision record
    copyUnlessNull EntityField record (Maybe typ)
    field = EntityField record (Maybe typ)
    -> Maybe typ -> HandleUpdateCollision record
    forall typ record.
    PersistField typ =>
    EntityField record typ -> typ -> HandleUpdateCollision record
    CopyUnlessEq EntityField record (Maybe typ)
    field Maybe typ
    forall a. Maybe a
    Nothing

    -- | Copy the field into the database only if the value in the
    -- corresponding record is non-empty, where "empty" means the Monoid
    -- definition for 'mempty'. Useful for 'Text', 'String', 'ByteString', etc.
    --
    -- The resulting 'HandleUpdateCollision' type is useful for the
    -- 'upsertManyWhere' function.
    --
    -- @since  2.12.1.0
    copyUnlessEmpty
        :: (Monoid.Monoid typ, PersistField typ)
        => EntityField record typ
        -> HandleUpdateCollision record
    copyUnlessEmpty :: forall typ record.
    (Monoid typ, PersistField typ) =>
    EntityField record typ -> HandleUpdateCollision record
    copyUnlessEmpty EntityField record typ
    field = EntityField record typ -> typ -> HandleUpdateCollision record
    forall typ record.
    PersistField typ =>
    EntityField record typ -> typ -> HandleUpdateCollision record
    CopyUnlessEq EntityField record typ
    field typ
    forall a. Monoid a => a
    Monoid.mempty

    -- | Copy the field into the database only if the field is not equal to the
    -- provided value. This is useful to avoid copying weird nullary data into
    -- the database.
    --
    -- The resulting 'HandleUpdateCollision' type is useful for the
    -- 'upsertMany' function.
    --
    -- @since  2.12.1.0
    copyUnlessEq
        :: (PersistField typ)
        => EntityField record typ
        -> typ
        -> HandleUpdateCollision record
    copyUnlessEq :: forall typ record.
    PersistField typ =>
    EntityField record typ -> typ -> HandleUpdateCollision record
    copyUnlessEq = EntityField record typ -> typ -> HandleUpdateCollision record
    forall typ record.
    PersistField typ =>
    EntityField record typ -> typ -> HandleUpdateCollision record
    CopyUnlessEq

    -- | Copy the field directly from the record.
    --
    -- @since 2.12.1.0
    copyField
        :: (PersistField typ) => EntityField record typ -> HandleUpdateCollision record
    copyField :: forall typ record.
    PersistField typ =>
    EntityField record typ -> HandleUpdateCollision record
    copyField = EntityField record typ -> HandleUpdateCollision record
    forall record typ.
    EntityField record typ -> HandleUpdateCollision record
    CopyField

    -- | Postgres specific 'upsertWhere'. This method does the following:
    -- It will insert a record if no matching unique key exists.
    -- If a unique key exists, it will update the relevant field with a user-supplied value, however,
    -- it will only do this update on a user-supplied condition.
    -- For example, here's how this method could be called like such:
    --
    -- @
    -- upsertWhere record [recordField =. newValue] [recordField /= newValue]
    -- @
    --
    -- Called thusly, this method will insert a new record (if none exists) OR update a recordField with a new value
    -- assuming the condition in the last block is met.
    --
    -- @since 2.12.1.0
    upsertWhere
        :: ( backend ~ PersistEntityBackend record
           , PersistEntity record
           , PersistEntityBackend record ~ SqlBackend
           , MonadIO m
           , PersistStore backend
           , BackendCompatible SqlBackend backend
           , OnlyOneUniqueKey record
           )
        => record
        -> [Update record]
        -> [Filter record]
        -> ReaderT backend m ()
    upsertWhere :: forall backend record (m :: * -> *).
    (backend ~ PersistEntityBackend record, PersistEntity record,
     PersistEntityBackend record ~ SqlBackend, MonadIO m,
     PersistStore backend, BackendCompatible SqlBackend backend,
     OnlyOneUniqueKey record) =>
    record
    -> [Update record] -> [Filter record] -> ReaderT backend m ()
    upsertWhere record
    record [Update record]
    updates [Filter record]
    filts =
        [record]
    -> [HandleUpdateCollision record]
    -> [Update record]
    -> [Filter record]
    -> ReaderT backend m ()
    forall record backend (m :: * -> *).
    (backend ~ PersistEntityBackend record,
     BackendCompatible SqlBackend backend,
     PersistEntityBackend record ~ SqlBackend, PersistEntity record,
     OnlyOneUniqueKey record, MonadIO m) =>
    [record]
    -> [HandleUpdateCollision record]
    -> [Update record]
    -> [Filter record]
    -> ReaderT backend m ()
    upsertManyWhere [record
    record] [] [Update record]
    updates [Filter record]
    filts

    -- | Postgres specific 'upsertManyWhere'.
    --
    -- The first argument is a list of new records to insert.
    --
    -- If there's unique key collisions for some or all of the proposed insertions,
    -- you can use the second argument to specify which fields, under which
    -- conditions (using 'HandleUpdateCollision' strategies,) will be copied from
    -- each proposed, conflicting new record onto its corresponding row already present
    -- in the database. Helpers such as 'copyField', 'copyUnlessEq',
    -- 'copyUnlessNull' and 'copyUnlessEmpty' are exported from this module to help
    -- with this, as well as the constructors for 'HandleUpdateCollision'.
    -- For example, you may have a patch of updates to apply, some of which are NULL
    -- to represent "no change"; you'd use 'copyUnlessNull' for each applicable
    -- field in this case so any new values in the patch which are NULL don't
    -- accidentally overwrite existing values in the database which are non-NULL.
    --
    -- Further updates to the matching records already in the database can be
    -- specified in the third argument, these are arbitrary updates independent of
    -- the new records proposed for insertion. For example, you can use this to
    -- update a timestamp or a counter for all conflicting rows.
    --
    -- You can use the fourth argument to provide arbitrary conditions to constrain
    -- the above updates. This way, you can choose to only alter a subset of the
    -- conflicting existing rows while leaving the others alone. For example, you
    -- may want to copy fields from new records and update a timestamp only when the
    -- corresponding existing row hasn't been soft-deleted.
    --
    --
    -- For example,
    --
    -- @
    --   upsertManyWhere
    --     [record]                         -- (1)
    --     [ copyField recordField1         -- (2)
    --     , copyUnlessEq recordField2      -- (3)
    --     , copyUnlessNull recordField3    -- (4)
    --     ]
    --     [recordField4 =. arbitraryValue] -- (5)
    --     [recordField4 !=. anotherValue]  -- (6)
    -- @
    --
    -- 1. new records to insert if there's no conflicts
    -- 2. for each conflicting existing row, replace the value of recordField1 with the one present in the conflicting new record
    -- 3. only replace the existing value if it's different from the one present in the conflicting new record
    -- 4. only replace the existing value if the new value is non-NULL (i.e. don't replace existing values with NULLs.)
    --
    -- 5. update recordField4 with an arbitrary new value
    -- 6. only apply the above updates for conflicting rows that meet this condition
    --
    -- Called thusly, this method will insert a new record (if none exists) OR it
    -- will copy three fields (@recordField1@, @recordField2@, @recordField3@) from
    -- the record proposed from insertion onto the existing row in the database
    -- following three different 'HandleUpdateCollision' strategies, it will /also/
    -- update @recordField4@ with an arbitrary @arbitraryValue@. Both sets of updates
    -- will only be applied if the row already present in the database has a
    -- @recordField4@ whose value is not @arbitraryValue@. The corresponding SQL might
    -- look like this:
    --
    -- @
    --   INSERT INTO table(recordField1, recordField2, recordField3, recordField4, recordField5)
    --   VALUES
    --     (newValue1, newValue2, newValue3, newValue4, newValue5)
    --   ON CONFLICT (recordField2, recordField3) -- let's imagine these two columns define a unique constraint
    --   DO UPDATE
    --     SET
    --       recordField1 = EXCLUDED.newValue1, -- EXCLUDED points to the new, conflicting, record; so we're always replacing the old value.
    --       recordField2 = COALESCE(NULLIF(EXCLUDED.newValue2, table.recordField2), table.recordField2), -- if the values are the same, the NULLIF returns NULL and we coalesce into setting the column to the value it already had (i.e. no change)
    --       recordField3 = COALESCE(NULLIF(EXCLUDED.newValue3, NULL), table.recordField3), -- if the new value is not null, it will be set; if it's null, we coalesce into not changing the existing value.
    --       recordField4 = arbitraryValue -- an arbitrary update independent of what's in the EXCLUDED (new) record
    --     WHERE
    --       recordField4 <> anotherValue -- only do the above updates if the value for the existing row's recordField4 is not "anotherValue"
    -- @
    --
    -- @since 2.12.1.0
    upsertManyWhere
        :: forall record backend m
         . ( backend ~ PersistEntityBackend record
           , BackendCompatible SqlBackend backend
           , PersistEntityBackend record ~ SqlBackend
           , PersistEntity record
           , OnlyOneUniqueKey record
           , MonadIO m
           )
        => [record]
        -- ^ A list of the records you want to insert, or update
        -> [HandleUpdateCollision record]
        -- ^ A list of the fields you want to copy over.
        -> [Update record]
        -- ^ A list of the updates to apply that aren't dependent on the record
        -- being inserted.
        -> [Filter record]
        -- ^ A filter condition that dictates the scope of the updates
        -> ReaderT backend m ()
    upsertManyWhere :: forall record backend (m :: * -> *).
    (backend ~ PersistEntityBackend record,
     BackendCompatible SqlBackend backend,
     PersistEntityBackend record ~ SqlBackend, PersistEntity record,
     OnlyOneUniqueKey record, MonadIO m) =>
    [record]
    -> [HandleUpdateCollision record]
    -> [Update record]
    -> [Filter record]
    -> ReaderT backend m ()
    upsertManyWhere [] [HandleUpdateCollision record]
    _ [Update record]
    _ [Filter record]
    _ = () -> ReaderT backend m ()
    forall a. a -> ReaderT backend m a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ()
    upsertManyWhere [record]
    records [HandleUpdateCollision record]
    fieldValues [Update record]
    updates [Filter record]
    filters = do
        conn <- (backend -> SqlBackend) -> ReaderT backend m SqlBackend
    forall (m :: * -> *) r a. Monad m => (r -> a) -> ReaderT r m a
    asks backend -> SqlBackend
    forall sup sub. BackendCompatible sup sub => sub -> sup
    projectBackend
        let
            uniqDef = Proxy record -> UniqueDef
    forall record (proxy :: * -> *).
    (OnlyOneUniqueKey record, Monad proxy) =>
    proxy record -> UniqueDef
    onlyOneUniqueDef (Proxy record
    forall {k} (t :: k). Proxy t
    Proxy :: Proxy record)
        uncurry rawExecute $
            mkBulkUpsertQuery records conn fieldValues updates filters uniqDef

    -- | Exclude any record field if it doesn't match the filter record.  Used only in `upsertWhere` and
    -- `upsertManyWhere`
    --
    -- TODO: we could probably make a sum type for the `Filter` record that's passed into the `upsertWhere` and
    -- `upsertManyWhere` methods that has similar behavior to the HandleCollisionUpdate type.
    --
    -- @since 2.12.1.0
    excludeNotEqualToOriginal
        :: (PersistField typ, PersistEntity rec)
        => EntityField rec typ
        -> Filter rec
    excludeNotEqualToOriginal :: forall typ rec.
    (PersistField typ, PersistEntity rec) =>
    EntityField rec typ -> Filter rec
    excludeNotEqualToOriginal EntityField rec typ
    field =
        Filter
            { filterField :: EntityField rec typ
    filterField =
                EntityField rec typ
    field
            , filterFilter :: PersistFilter
    filterFilter =
                PersistFilter
    Ne
            , filterValue :: FilterValue typ
    filterValue =
                PersistValue -> FilterValue typ
    forall a typ. PersistField a => a -> FilterValue typ
    UnsafeValue (PersistValue -> FilterValue typ)
    -> PersistValue -> FilterValue typ
    forall a b. (a -> b) -> a -> b
    $
                    LiteralType -> ConnectionString -> PersistValue
    PersistLiteral_
                        LiteralType
    Unescaped
                        ConnectionString
    bsForExcludedField
            }
      where
        bsForExcludedField :: ConnectionString
    bsForExcludedField =
            Text -> ConnectionString
    T.encodeUtf8 (Text -> ConnectionString) -> Text -> ConnectionString
    forall a b. (a -> b) -> a -> b
    $
                Text
    "EXCLUDED."
                    Text -> Text -> Text
    forall a. Semigroup a => a -> a -> a
    <> EntityField rec typ -> Text
    forall record typ.
    PersistEntity record =>
    EntityField record typ -> Text
    fieldName EntityField rec typ
    field

    -- | This creates the query for 'upsertManyWhere'. If you
    -- provide an empty list of updates to perform, then it will generate
    -- a dummy/no-op update using the first field of the record. This avoids
    -- duplicate key exceptions.
    mkBulkUpsertQuery
        :: ( PersistEntity record
           , PersistEntityBackend record ~ SqlBackend
           , OnlyOneUniqueKey record
           )
        => [record]
        -- ^ A list of the records you want to insert, or update
        -> SqlBackend
        -> [HandleUpdateCollision record]
        -- ^ A list of the fields you want to copy over.
        -> [Update record]
        -- ^ A list of the updates to apply that aren't dependent on the record being inserted.
        -> [Filter record]
        -- ^ A filter condition that dictates the scope of the updates
        -> UniqueDef
        -- ^ The specific uniqueness constraint to use on the record. Postgres
        -- rquires that we use exactly one relevant constraint, and it can't do
        -- a catch-all. How frustrating!
        -> (Text, [PersistValue])
    mkBulkUpsertQuery :: forall record.
    (PersistEntity record, PersistEntityBackend record ~ SqlBackend,
     OnlyOneUniqueKey record) =>
    [record]
    -> SqlBackend
    -> [HandleUpdateCollision record]
    -> [Update record]
    -> [Filter record]
    -> UniqueDef
    -> (Text, [PersistValue])
    mkBulkUpsertQuery [record]
    records SqlBackend
    conn [HandleUpdateCollision record]
    fieldValues [Update record]
    updates [Filter record]
    filters UniqueDef
    uniqDef =
        (Text
    q, [PersistValue]
    recordValues [PersistValue] -> [PersistValue] -> [PersistValue]
    forall a. Semigroup a => a -> a -> a
    <> [PersistValue]
    updsValues [PersistValue] -> [PersistValue] -> [PersistValue]
    forall a. Semigroup a => a -> a -> a
    <> [PersistValue]
    copyUnlessValues [PersistValue] -> [PersistValue] -> [PersistValue]
    forall a. Semigroup a => a -> a -> a
    <> [PersistValue]
    whereVals)
      where
        mfieldDef :: HandleUpdateCollision record -> Either (Text, PersistValue) Text
    mfieldDef HandleUpdateCollision record
    x = case HandleUpdateCollision record
    x of
            CopyField EntityField record typ
    rec -> Text -> Either (Text, PersistValue) Text
    forall a b. b -> Either a b
    Right (FieldDef -> Text
    fieldDbToText (EntityField record typ -> FieldDef
    forall record typ.
    PersistEntity record =>
    EntityField record typ -> FieldDef
    forall typ. EntityField record typ -> FieldDef
    persistFieldDef EntityField record typ
    rec))
            CopyUnlessEq EntityField record typ
    rec typ
    val -> (Text, PersistValue) -> Either (Text, PersistValue) Text
    forall a b. a -> Either a b
    Left (FieldDef -> Text
    fieldDbToText (EntityField record typ -> FieldDef
    forall record typ.
    PersistEntity record =>
    EntityField record typ -> FieldDef
    forall typ. EntityField record typ -> FieldDef
    persistFieldDef EntityField record typ
    rec), typ -> PersistValue
    forall a. PersistField a => a -> PersistValue
    toPersistValue typ
    val)
        ([(Text, PersistValue)]
    fieldsToMaybeCopy, [Text]
    updateFieldNames) = [Either (Text, PersistValue) Text]
    -> ([(Text, PersistValue)], [Text])
    forall a b. [Either a b] -> ([a], [b])
    partitionEithers ([Either (Text, PersistValue) Text]
     -> ([(Text, PersistValue)], [Text]))
    -> [Either (Text, PersistValue) Text]
    -> ([(Text, PersistValue)], [Text])
    forall a b. (a -> b) -> a -> b
    $ (HandleUpdateCollision record -> Either (Text, PersistValue) Text)
    -> [HandleUpdateCollision record]
    -> [Either (Text, PersistValue) Text]
    forall a b. (a -> b) -> [a] -> [b]
    map HandleUpdateCollision record -> Either (Text, PersistValue) Text
    forall {record}.
    PersistEntity record =>
    HandleUpdateCollision record -> Either (Text, PersistValue) Text
    mfieldDef [HandleUpdateCollision record]
    fieldValues
        fieldDbToText :: FieldDef -> Text
    fieldDbToText = FieldNameDB -> Text
    escapeF (FieldNameDB -> Text)
    -> (FieldDef -> FieldNameDB) -> FieldDef -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . FieldDef -> FieldNameDB
    fieldDB
        entityDef' :: EntityDef
    entityDef' = [record] -> EntityDef
    forall record (proxy :: * -> *).
    PersistEntity record =>
    proxy record -> EntityDef
    forall (proxy :: * -> *). proxy record -> EntityDef
    entityDef [record]
    records
        conflictColumns :: [Text]
    conflictColumns =
            ((FieldNameHS, FieldNameDB) -> Text)
    -> [(FieldNameHS, FieldNameDB)] -> [Text]
    forall a b. (a -> b) -> [a] -> [b]
    map (FieldNameDB -> Text
    escapeF (FieldNameDB -> Text)
    -> ((FieldNameHS, FieldNameDB) -> FieldNameDB)
    -> (FieldNameHS, FieldNameDB)
    -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (FieldNameHS, FieldNameDB) -> FieldNameDB
    forall a b. (a, b) -> b
    snd) ([(FieldNameHS, FieldNameDB)] -> [Text])
    -> [(FieldNameHS, FieldNameDB)] -> [Text]
    forall a b. (a -> b) -> a -> b
    $ NonEmpty (FieldNameHS, FieldNameDB) -> [(FieldNameHS, FieldNameDB)]
    forall a. NonEmpty a -> [a]
    NEL.toList (NonEmpty (FieldNameHS, FieldNameDB)
     -> [(FieldNameHS, FieldNameDB)])
    -> NonEmpty (FieldNameHS, FieldNameDB)
    -> [(FieldNameHS, FieldNameDB)]
    forall a b. (a -> b) -> a -> b
    $ UniqueDef -> NonEmpty (FieldNameHS, FieldNameDB)
    uniqueFields UniqueDef
    uniqDef
        firstField :: Text
    firstField = case [Text]
    entityFieldNames of
            [] -> String -> Text
    forall a. HasCallStack => String -> a
    error String
    "The entity you're trying to insert does not have any fields."
            (Text
    field : [Text]
    _) -> Text
    field
        entityFieldNames :: [Text]
    entityFieldNames = (FieldDef -> Text) -> [FieldDef] -> [Text]
    forall a b. (a -> b) -> [a] -> [b]
    map FieldDef -> Text
    fieldDbToText (EntityDef -> [FieldDef]
    getEntityFields EntityDef
    entityDef')
        nameOfTable :: Text
    nameOfTable = EntityNameDB -> Text
    escapeE (EntityNameDB -> Text)
    -> (EntityDef -> EntityNameDB) -> EntityDef -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . EntityDef -> EntityNameDB
    getEntityDBName (EntityDef -> Text) -> EntityDef -> Text
    forall a b. (a -> b) -> a -> b
    $ EntityDef
    entityDef'
        copyUnlessValues :: [PersistValue]
    copyUnlessValues = ((Text, PersistValue) -> PersistValue)
    -> [(Text, PersistValue)] -> [PersistValue]
    forall a b. (a -> b) -> [a] -> [b]
    map (Text, PersistValue) -> PersistValue
    forall a b. (a, b) -> b
    snd [(Text, PersistValue)]
    fieldsToMaybeCopy
        recordValues :: [PersistValue]
    recordValues = (record -> [PersistValue]) -> [record] -> [PersistValue]
    forall (t :: * -> *) a b. Foldable t => (a -> [b]) -> t a -> [b]
    concatMap ((PersistValue -> PersistValue) -> [PersistValue] -> [PersistValue]
    forall a b. (a -> b) -> [a] -> [b]
    map PersistValue -> PersistValue
    forall a. PersistField a => a -> PersistValue
    toPersistValue ([PersistValue] -> [PersistValue])
    -> (record -> [PersistValue]) -> record -> [PersistValue]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . record -> [PersistValue]
    forall record. PersistEntity record => record -> [PersistValue]
    toPersistFields) [record]
    records
        recordPlaceholders :: Text
    recordPlaceholders =
            [Text] -> Text
    Util.commaSeparated
                ([Text] -> Text) -> [Text] -> Text
    forall a b. (a -> b) -> a -> b
    $ (record -> Text) -> [record] -> [Text]
    forall a b. (a -> b) -> [a] -> [b]
    map
                    (Text -> Text
    Util.parenWrapped (Text -> Text) -> (record -> Text) -> record -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [Text] -> Text
    Util.commaSeparated ([Text] -> Text) -> (record -> [Text]) -> record -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . (PersistValue -> Text) -> [PersistValue] -> [Text]
    forall a b. (a -> b) -> [a] -> [b]
    map (Text -> PersistValue -> Text
    forall a b. a -> b -> a
    const Text
    "?") ([PersistValue] -> [Text])
    -> (record -> [PersistValue]) -> record -> [Text]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . record -> [PersistValue]
    forall record. PersistEntity record => record -> [PersistValue]
    toPersistFields)
                ([record] -> [Text]) -> [record] -> [Text]
    forall a b. (a -> b) -> a -> b
    $ [record]
    records
        mkCondFieldSet :: Text -> PersistValue -> Text
    mkCondFieldSet Text
    n PersistValue
    _ =
            [Text] -> Text
    T.concat
                [ Text
    n
                , Text
    "=COALESCE("
                , Text
    "NULLIF("
                , Text
    "EXCLUDED."
                , Text
    n
                , Text
    ","
                , Text
    "?"
                , Text
    ")"
                , Text
    ","
                , Text
    nameOfTable
                , Text
    "."
                , Text
    n
                , Text
    ")"
                ]
        condFieldSets :: [Text]
    condFieldSets = ((Text, PersistValue) -> Text) -> [(Text, PersistValue)] -> [Text]
    forall a b. (a -> b) -> [a] -> [b]
    map ((Text -> PersistValue -> Text) -> (Text, PersistValue) -> Text
    forall a b c. (a -> b -> c) -> (a, b) -> c
    uncurry Text -> PersistValue -> Text
    mkCondFieldSet) [(Text, PersistValue)]
    fieldsToMaybeCopy
        fieldSets :: [Text]
    fieldSets = (Text -> Text) -> [Text] -> [Text]
    forall a b. (a -> b) -> [a] -> [b]
    map (\Text
    n -> [Text] -> Text
    T.concat [Text
    n, Text
    "=EXCLUDED.", Text
    n, Text
    ""]) [Text]
    updateFieldNames
        upds :: [Text]
    upds =
            (Update record -> Text) -> [Update record] -> [Text]
    forall a b. (a -> b) -> [a] -> [b]
    map
                ((FieldNameDB -> Text) -> (Text -> Text) -> Update record -> Text
    forall record.
    PersistEntity record =>
    (FieldNameDB -> Text) -> (Text -> Text) -> Update record -> Text
    Util.mkUpdateText' (FieldNameDB -> Text
    escapeF) (\Text
    n -> [Text] -> Text
    T.concat [Text
    nameOfTable, Text
    ".", Text
    n]))
                [Update record]
    updates
        updsValues :: [PersistValue]
    updsValues = (Update record -> PersistValue)
    -> [Update record] -> [PersistValue]
    forall a b. (a -> b) -> [a] -> [b]
    map (\(Update EntityField record typ
    _ typ
    val PersistUpdate
    _) -> typ -> PersistValue
    forall a. PersistField a => a -> PersistValue
    toPersistValue typ
    val) [Update record]
    updates
        (Text
    wher, [PersistValue]
    whereVals) =
            if [Filter record] -> Bool
    forall a. [a] -> Bool
    forall (t :: * -> *) a. Foldable t => t a -> Bool
    null [Filter record]
    filters
                then (Text
    "", [])
                else (Maybe FilterTablePrefix
    -> SqlBackend -> [Filter record] -> (Text, [PersistValue])
    forall val.
    PersistEntity val =>
    Maybe FilterTablePrefix
    -> SqlBackend -> [Filter val] -> (Text, [PersistValue])
    filterClauseWithVals (FilterTablePrefix -> Maybe FilterTablePrefix
    forall a. a -> Maybe a
    Just FilterTablePrefix
    PrefixTableName) SqlBackend
    conn [Filter record]
    filters)
        updateText :: Text
    updateText =
            case [Text]
    fieldSets [Text] -> [Text] -> [Text]
    forall a. Semigroup a => a -> a -> a
    <> [Text]
    upds [Text] -> [Text] -> [Text]
    forall a. Semigroup a => a -> a -> a
    <> [Text]
    condFieldSets of
                [] ->
                    -- This case is really annoying, and probably unlikely to be
                    -- actually hit - someone would have had to call something like
                    -- `upsertManyWhere [] [] []`, but that would have been caught
                    -- by the prior case.
                    -- Would be nice to have something like a `NonEmpty (These ...)`
                    -- instead of multiple lists...
                    [Text] -> Text
    T.concat [Text
    firstField, Text
    "=", Text
    nameOfTable, Text
    ".", Text
    firstField]
                [Text]
    xs ->
                    [Text] -> Text
    Util.commaSeparated [Text]
    xs
        q :: Text
    q =
            [Text] -> Text
    T.concat
                [ Text
    "INSERT INTO "
                , Text
    nameOfTable
                , Text -> Text
    Util.parenWrapped (Text -> Text) -> ([Text] -> Text) -> [Text] -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [Text] -> Text
    Util.commaSeparated ([Text] -> Text) -> [Text] -> Text
    forall a b. (a -> b) -> a -> b
    $ [Text]
    entityFieldNames
                , Text
    " VALUES "
                , Text
    recordPlaceholders
                , Text
    " ON CONFLICT "
                , Text -> Text
    Util.parenWrapped (Text -> Text) -> Text -> Text
    forall a b. (a -> b) -> a -> b
    $ [Text] -> Text
    Util.commaSeparated ([Text] -> Text) -> [Text] -> Text
    forall a b. (a -> b) -> a -> b
    $ [Text]
    conflictColumns
                , Text
    " DO UPDATE SET "
                , Text
    updateText
                , Text
    wher
                ]

    putManySql' :: [Text] -> [FieldDef] -> EntityDef -> Int -> Text
    putManySql' :: [Text] -> [FieldDef] -> EntityDef -> Int -> Text
    putManySql' [Text]
    conflictColumns ((FieldDef -> Bool) -> [FieldDef] -> [FieldDef]
    forall a. (a -> Bool) -> [a] -> [a]
    filter FieldDef -> Bool
    isFieldNotGenerated -> [FieldDef]
    fields) EntityDef
    ent Int
    n = Text
    q
      where
        fieldDbToText :: FieldDef -> Text
    fieldDbToText = FieldNameDB -> Text
    escapeF (FieldNameDB -> Text)
    -> (FieldDef -> FieldNameDB) -> FieldDef -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . FieldDef -> FieldNameDB
    fieldDB
        mkAssignment :: Text -> Text
    mkAssignment Text
    f = [Text] -> Text
    T.concat [Text
    f, Text
    "=EXCLUDED.", Text
    f]

        table :: Text
    table = EntityNameDB -> Text
    escapeE (EntityNameDB -> Text)
    -> (EntityDef -> EntityNameDB) -> EntityDef -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . EntityDef -> EntityNameDB
    getEntityDBName (EntityDef -> Text) -> EntityDef -> Text
    forall a b. (a -> b) -> a -> b
    $ EntityDef
    ent
        columns :: Text
    columns = [Text] -> Text
    Util.commaSeparated ([Text] -> Text) -> [Text] -> Text
    forall a b. (a -> b) -> a -> b
    $ (FieldDef -> Text) -> [FieldDef] -> [Text]
    forall a b. (a -> b) -> [a] -> [b]
    map FieldDef -> Text
    fieldDbToText [FieldDef]
    fields
        placeholders :: [Text]
    placeholders = (FieldDef -> Text) -> [FieldDef] -> [Text]
    forall a b. (a -> b) -> [a] -> [b]
    map (Text -> FieldDef -> Text
    forall a b. a -> b -> a
    const Text
    "?") [FieldDef]
    fields
        updates :: [Text]
    updates = (FieldDef -> Text) -> [FieldDef] -> [Text]
    forall a b. (a -> b) -> [a] -> [b]
    map (Text -> Text
    mkAssignment (Text -> Text) -> (FieldDef -> Text) -> FieldDef -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . FieldDef -> Text
    fieldDbToText) [FieldDef]
    fields

        q :: Text
    q =
            [Text] -> Text
    T.concat
                [ Text
    "INSERT INTO "
                , Text
    table
                , Text -> Text
    Util.parenWrapped Text
    columns
                , Text
    " VALUES "
                , [Text] -> Text
    Util.commaSeparated
                    ([Text] -> Text) -> ([Text] -> [Text]) -> [Text] -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Int -> Text -> [Text]
    forall a. Int -> a -> [a]
    replicate Int
    n
                    (Text -> [Text]) -> ([Text] -> Text) -> [Text] -> [Text]
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . Text -> Text
    Util.parenWrapped
                    (Text -> Text) -> ([Text] -> Text) -> [Text] -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [Text] -> Text
    Util.commaSeparated
                    ([Text] -> Text) -> [Text] -> Text
    forall a b. (a -> b) -> a -> b
    $ [Text]
    placeholders
                , Text
    " ON CONFLICT "
                , Text -> Text
    Util.parenWrapped (Text -> Text) -> ([Text] -> Text) -> [Text] -> Text
    forall b c a. (b -> c) -> (a -> b) -> a -> c
    . [Text] -> Text
    Util.commaSeparated ([Text] -> Text) -> [Text] -> Text
    forall a b. (a -> b) -> a -> b
    $ [Text]
    conflictColumns
                , Text
    " DO UPDATE SET "
                , [Text] -> Text
    Util.commaSeparated [Text]
    updates
                ]

    -- | Enable a Postgres extension. See https://www.postgresql.org/docs/current/static/contrib.html
    -- for a list.
    migrateEnableExtension :: Text -> Migration
    migrateEnableExtension :: Text -> Migration
    migrateEnableExtension Text
    extName = WriterT [(Bool, Text)] (ReaderT SqlBackend IO) ((), [Text])
    -> Migration
    forall w (m :: * -> *) a. m (a, w) -> WriterT w m a
    WriterT (WriterT [(Bool, Text)] (ReaderT SqlBackend IO) ((), [Text])
     -> Migration)
    -> WriterT [(Bool, Text)] (ReaderT SqlBackend IO) ((), [Text])
    -> Migration
    forall a b. (a -> b) -> a -> b
    $ ReaderT SqlBackend IO (((), [Text]), [(Bool, Text)])
    -> WriterT [(Bool, Text)] (ReaderT SqlBackend IO) ((), [Text])
    forall w (m :: * -> *) a. m (a, w) -> WriterT w m a
    WriterT (ReaderT SqlBackend IO (((), [Text]), [(Bool, Text)])
     -> WriterT [(Bool, Text)] (ReaderT SqlBackend IO) ((), [Text]))
    -> ReaderT SqlBackend IO (((), [Text]), [(Bool, Text)])
    -> WriterT [(Bool, Text)] (ReaderT SqlBackend IO) ((), [Text])
    forall a b. (a -> b) -> a -> b
    $ do
        res :: [Single Int] <-
            Text -> [PersistValue] -> ReaderT SqlBackend IO [Single Int]
    forall a (m :: * -> *) backend.
    (RawSql a, MonadIO m, BackendCompatible SqlBackend backend) =>
    Text -> [PersistValue] -> ReaderT backend m [a]
    rawSql
                Text
    "SELECT COUNT(*) FROM pg_catalog.pg_extension WHERE extname = ?"
                [Text -> PersistValue
    PersistText Text
    extName]
        if res == [Single 0]
            then return (((), []), [(False, "CREATe EXTENSION \"" <> extName <> "\"")])
            else return (((), []), [])

    -- | Wrapper for persistent SqlBackends that carry the corresponding
    -- `Postgresql.Connection`.
    --
    -- @since 2.13.1.0
    data RawPostgresql backend = RawPostgresql
        { forall backend. RawPostgresql backend -> backend
    persistentBackend :: backend
        -- ^ The persistent backend
        --
        -- @since 2.13.1.0
        , forall backend. RawPostgresql backend -> Connection
    rawPostgresqlConnection :: PG.Connection
        -- ^ The underlying `PG.Connection`
        --
        -- @since 2.13.1.0
        }

    instance BackendCompatible (RawPostgresql b) (RawPostgresql b) where
        projectBackend :: RawPostgresql b -> RawPostgresql b
    projectBackend = RawPostgresql b -> RawPostgresql b
    forall a. a -> a
    id

    instance BackendCompatible b (RawPostgresql b) where
        projectBackend :: RawPostgresql b -> b
    projectBackend = RawPostgresql b -> b
    forall backend. RawPostgresql backend -> backend
    persistentBackend

    withRawConnection
        :: (PG.Connection -> SqlBackend)
        -> PG.Connection
        -> RawPostgresql SqlBackend
    withRawConnection :: (Connection -> SqlBackend)
    -> Connection -> RawPostgresql SqlBackend
    withRawConnection Connection -> SqlBackend
    f Connection
    conn =
        RawPostgresql
            { persistentBackend :: SqlBackend
    persistentBackend = Connection -> SqlBackend
    f Connection
    conn
            , rawPostgresqlConnection :: Connection
    rawPostgresqlConnection = Connection
    conn
            }

    -- | Create a PostgreSQL connection pool which also exposes the
    -- raw connection. The raw counterpart to 'createPostgresqlPool'.
    --
    -- @since 2.13.1.0
    createRawPostgresqlPool
        :: (MonadUnliftIO m, MonadLoggerIO m)
        => ConnectionString
        -- ^ Connection string to the database.
        -> Int
        -- ^ Number of connections to be kept open
        -- in the pool.
        -> m (Pool (RawPostgresql SqlBackend))
    createRawPostgresqlPool :: forall (m :: * -> *).
    (MonadUnliftIO m, MonadLoggerIO m) =>
    ConnectionString -> Int -> m (Pool (RawPostgresql SqlBackend))
    createRawPostgresqlPool = (Connection -> IO ())
    -> ConnectionString -> Int -> m (Pool (RawPostgresql SqlBackend))
    forall (m :: * -> *).
    (MonadUnliftIO m, MonadLoggerIO m) =>
    (Connection -> IO ())
    -> ConnectionString -> Int -> m (Pool (RawPostgresql SqlBackend))
    createRawPostgresqlPoolModified (IO () -> Connection -> IO ()
    forall a b. a -> b -> a
    const (IO () -> Connection -> IO ()) -> IO () -> Connection -> IO ()
    forall a b. (a -> b) -> a -> b
    $ () -> IO ()
    forall a. a -> IO a
    forall (m :: * -> *) a. Monad m => a -> m a
    return ())

    -- | The raw counterpart to 'createPostgresqlPoolModified'.
    --
    -- @since 2.13.1.0
    createRawPostgresqlPoolModified
        :: (MonadUnliftIO m, MonadLoggerIO m)
        => (PG.Connection -> IO ())
        -- ^ Action to perform after connection is created.
        -> ConnectionString
        -- ^ Connection string to the database.
        -> Int
        -- ^ Number of connections to be kept open in the pool.
        -> m (Pool (RawPostgresql SqlBackend))
    createRawPostgresqlPoolModified :: forall (m :: * -> *).
    (MonadUnliftIO m, MonadLoggerIO m) =>
    (Connection -> IO ())
    -> ConnectionString -> Int -> m (Pool (RawPostgresql SqlBackend))
    createRawPostgresqlPoolModified = (Connection -> IO (Maybe Double))
    -> (Connection -> IO ())
    -> ConnectionString
    -> Int
    -> m (Pool (RawPostgresql SqlBackend))
    forall (m :: * -> *).
    (MonadUnliftIO m, MonadLoggerIO m) =>
    (Connection -> IO (Maybe Double))
    -> (Connection -> IO ())
    -> ConnectionString
    -> Int
    -> m (Pool (RawPostgresql SqlBackend))
    createRawPostgresqlPoolModifiedWithVersion Connection -> IO (Maybe Double)
    getServerVersion

    -- | The raw counterpart to 'createPostgresqlPoolModifiedWithVersion'.
    --
    -- @since 2.13.1.0
    createRawPostgresqlPoolModifiedWithVersion
        :: (MonadUnliftIO m, MonadLoggerIO m)
        => (PG.Connection -> IO (Maybe Double))
        -- ^ Action to perform to get the server version.
        -> (PG.Connection -> IO ())
        -- ^ Action to perform after connection is created.
        -> ConnectionString
        -- ^ Connection string to the database.
        -> Int
        -- ^ Number of connections to be kept open in the pool.
        -> m (Pool (RawPostgresql SqlBackend))
    createRawPostgresqlPoolModifiedWithVersion :: forall (m :: * -> *).
    (MonadUnliftIO m, MonadLoggerIO m) =>
    (Connection -> IO (Maybe Double))
    -> (Connection -> IO ())
    -> ConnectionString
    -> Int
    -> m (Pool (RawPostgresql SqlBackend))
    createRawPostgresqlPoolModifiedWithVersion Connection -> IO (Maybe Double)
    getVerDouble Connection -> IO ()
    modConn ConnectionString
    ci = do
        let
            getVer :: Connection -> IO (NonEmpty Word)
    getVer = (Connection -> IO (Maybe Double))
    -> Connection -> IO (NonEmpty Word)
    oldGetVersionToNew Connection -> IO (Maybe Double)
    getVerDouble
        (LogFunc -> IO (RawPostgresql SqlBackend))
    -> Int -> m (Pool (RawPostgresql SqlBackend))
    forall backend (m :: * -> *).
    (MonadLoggerIO m, MonadUnliftIO m,
     BackendCompatible SqlBackend backend) =>
    (LogFunc -> IO backend) -> Int -> m (Pool backend)
    createSqlPool ((LogFunc -> IO (RawPostgresql SqlBackend))
     -> Int -> m (Pool (RawPostgresql SqlBackend)))
    -> (LogFunc -> IO (RawPostgresql SqlBackend))
    -> Int
    -> m (Pool (RawPostgresql SqlBackend))
    forall a b. (a -> b) -> a -> b
    $ (Connection -> IO ())
    -> (Connection -> IO (NonEmpty Word))
    -> ((Connection -> SqlBackend)
        -> Connection -> RawPostgresql SqlBackend)
    -> ConnectionString
    -> LogFunc
    -> IO (RawPostgresql SqlBackend)
    forall backend.
    (Connection -> IO ())
    -> (Connection -> IO (NonEmpty Word))
    -> ((Connection -> SqlBackend) -> Connection -> backend)
    -> ConnectionString
    -> LogFunc
    -> IO backend
    open' Connection -> IO ()
    modConn Connection -> IO (NonEmpty Word)
    getVer (Connection -> SqlBackend)
    -> Connection -> RawPostgresql SqlBackend
    withRawConnection ConnectionString
    ci

    -- | The raw counterpart to 'createPostgresqlPoolWithConf'.
    --
    -- @since 2.13.1.0
    createRawPostgresqlPoolWithConf
        :: (MonadUnliftIO m, MonadLoggerIO m)
        => PostgresConf
        -- ^ Configuration for connecting to Postgres
        -> PostgresConfHooks
        -- ^ Record of callback functions
        -> m (Pool (RawPostgresql SqlBackend))
    createRawPostgresqlPoolWithConf :: forall (m :: * -> *).
    (MonadUnliftIO m, MonadLoggerIO m) =>
    PostgresConf
    -> PostgresConfHooks -> m (Pool (RawPostgresql SqlBackend))
    createRawPostgresqlPoolWithConf PostgresConf
    conf PostgresConfHooks
    hooks = do
        let
            getVer :: Connection -> IO (NonEmpty Word)
    getVer = PostgresConfHooks -> Connection -> IO (NonEmpty Word)
    pgConfHooksGetServerVersion PostgresConfHooks
    hooks
            modConn :: Connection -> IO ()
    modConn = PostgresConfHooks -> Connection -> IO ()
    pgConfHooksAfterCreate PostgresConfHooks
    hooks
        (LogFunc -> IO (RawPostgresql SqlBackend))
    -> ConnectionPoolConfig -> m (Pool (RawPostgresql SqlBackend))
    forall (m :: * -> *) backend.
    (MonadLoggerIO m, MonadUnliftIO m,
     BackendCompatible SqlBackend backend) =>
    (LogFunc -> IO backend) -> ConnectionPoolConfig -> m (Pool backend)
    createSqlPoolWithConfig
            ((Connection -> IO ())
    -> (Connection -> IO (NonEmpty Word))
    -> ((Connection -> SqlBackend)
        -> Connection -> RawPostgresql SqlBackend)
    -> ConnectionString
    -> LogFunc
    -> IO (RawPostgresql SqlBackend)
    forall backend.
    (Connection -> IO ())
    -> (Connection -> IO (NonEmpty Word))
    -> ((Connection -> SqlBackend) -> Connection -> backend)
    -> ConnectionString
    -> LogFunc
    -> IO backend
    open' Connection -> IO ()
    modConn Connection -> IO (NonEmpty Word)
    getVer (Connection -> SqlBackend)
    -> Connection -> RawPostgresql SqlBackend
    withRawConnection (PostgresConf -> ConnectionString
    pgConnStr PostgresConf
    conf))
            (PostgresConf -> ConnectionPoolConfig
    postgresConfToConnectionPoolConfig PostgresConf
    conf)

    #if MIN_VERSION_base(4,12,0)
    instance (PersistCore b) => PersistCore (RawPostgresql b) where
      newtype BackendKey (RawPostgresql b) = RawPostgresqlKey { forall b.
    BackendKey (RawPostgresql b)
    -> BackendKey (Compatible b (RawPostgresql b))
    unRawPostgresqlKey :: BackendKey (Compatible b (RawPostgresql b)) }

    makeCompatibleKeyInstances [t| forall b. Compatible b (RawPostgresql b) |]
    #else
    instance (PersistCore b) => PersistCore (RawPostgresql b) where
      newtype BackendKey (RawPostgresql b) = RawPostgresqlKey { unRawPostgresqlKey :: BackendKey (RawPostgresql b) }

    deriving instance (Show (BackendKey b)) => Show (BackendKey (RawPostgresql b))
    deriving instance (Read (BackendKey b)) => Read (BackendKey (RawPostgresql b))
    deriving instance (Eq (BackendKey b)) => Eq (BackendKey (RawPostgresql b))
    deriving instance (Ord (BackendKey b)) => Ord (BackendKey (RawPostgresql b))
    deriving instance (Num (BackendKey b)) => Num (BackendKey (RawPostgresql b))
    deriving instance (Integral (BackendKey b)) => Integral (BackendKey (RawPostgresql b))
    deriving instance (PersistField (BackendKey b)) => PersistField (BackendKey (RawPostgresql b))
    deriving instance (PersistFieldSql (BackendKey b)) => PersistFieldSql (BackendKey (RawPostgresql b))
    deriving instance (Real (BackendKey b)) => Real (BackendKey (RawPostgresql b))
    deriving instance (Enum (BackendKey b)) => Enum (BackendKey (RawPostgresql b))
    deriving instance (Bounded (BackendKey b)) => Bounded (BackendKey (RawPostgresql b))
    deriving instance (ToJSON (BackendKey b)) => ToJSON (BackendKey (RawPostgresql b))
    deriving instance (FromJSON (BackendKey b)) => FromJSON (BackendKey (RawPostgresql b))
    #endif

    #if MIN_VERSION_base(4,12,0)
    $(pure [])

    makeCompatibleInstances [t| forall b. Compatible b (RawPostgresql b) |]
    #else
    instance HasPersistBackend b => HasPersistBackend (RawPostgresql b) where
        type BaseBackend (RawPostgresql b) = BaseBackend b
        persistBackend = persistBackend . persistentBackend

    instance (PersistStoreRead b) => PersistStoreRead (RawPostgresql b) where
        get = withReaderT persistentBackend . get
        getMany = withReaderT persistentBackend . getMany

    instance (PersistQueryRead b) => PersistQueryRead (RawPostgresql b) where
        selectSourceRes filts opts = withReaderT persistentBackend $ selectSourceRes filts opts
        selectFirst filts opts = withReaderT persistentBackend $ selectFirst filts opts
        selectKeysRes filts opts = withReaderT persistentBackend $ selectKeysRes filts opts
        count = withReaderT persistentBackend . count
        exists = withReaderT persistentBackend . exists

    instance (PersistQueryWrite b) => PersistQueryWrite (RawPostgresql b) where
        updateWhere filts updates = withReaderT persistentBackend $ updateWhere filts updates
        deleteWhere = withReaderT persistentBackend . deleteWhere

    instance (PersistUniqueRead b) => PersistUniqueRead (RawPostgresql b) where
        getBy = withReaderT persistentBackend . getBy

    instance (PersistStoreWrite b) => PersistStoreWrite (RawPostgresql b) where
        insert = withReaderT persistentBackend . insert
        insert_ = withReaderT persistentBackend . insert_
        insertMany = withReaderT persistentBackend . insertMany
        insertMany_ = withReaderT persistentBackend . insertMany_
        insertEntityMany = withReaderT persistentBackend . insertEntityMany
        insertKey k = withReaderT persistentBackend . insertKey k
        repsert k = withReaderT persistentBackend . repsert k
        repsertMany = withReaderT persistentBackend . repsertMany
        replace k = withReaderT persistentBackend . replace k
        delete = withReaderT persistentBackend . delete
        update k = withReaderT persistentBackend . update k
        updateGet k = withReaderT persistentBackend . updateGet k

    instance (PersistUniqueWrite b) => PersistUniqueWrite (RawPostgresql b) where
        deleteBy = withReaderT persistentBackend . deleteBy
        insertUnique = withReaderT persistentBackend . insertUnique
        upsert rec = withReaderT persistentBackend . upsert rec
        upsertBy uniq rec = withReaderT persistentBackend . upsertBy uniq rec
        putMany = withReaderT persistentBackend . putMany
    #endif