    {-# LANGUAGE RankNTypes #-}
    {-# LANGUAGE RecordWildCards #-}

    module Database.Persist.SqlBackend.Internal where

    import Data.List.NonEmpty (NonEmpty)
    import Data.Text (Text)
    import Data.Vault.Strict (Vault)
    import qualified Data.Vault.Strict as Vault
    import Database.Persist.Class.PersistStore
    import Database.Persist.Names
    import Database.Persist.SqlBackend.Internal.InsertSqlResult
    import Database.Persist.SqlBackend.Internal.IsolationLevel
    import Database.Persist.SqlBackend.Internal.MkSqlBackend
    import Database.Persist.SqlBackend.Internal.Statement
    import Database.Persist.SqlBackend.StatementCache
    import Database.Persist.Types.Base

    -- | A 'SqlBackend' represents a handle or connection to a database. It
    -- contains functions and values that allow databases to have more
    -- optimized implementations, as well as references that benefit
    -- performance and sharing.
    --
    -- Instead of using the 'SqlBackend' constructor directly, use the
    -- 'mkSqlBackend' function.
    --
    -- A 'SqlBackend' is *not* thread-safe. You should not assume that
    -- a 'SqlBackend' can be shared among threads and run concurrent queries.
    -- This *will* result in problems. Instead, you should create a @'Pool'
    -- 'SqlBackend'@, known as a 'ConnectionPool', and pass that around in
    -- multi-threaded applications.
    --
    -- To run actions in the @persistent@ library, you should use the
    -- 'runSqlConn' function. If you're using a multithreaded application, use
    -- the 'runSqlPool' function.
    data SqlBackend = SqlBackend
        { SqlBackend -> Text -> IO Statement
    connPrepare :: Text -> IO Statement
        -- ^ This function should prepare a 'Statement' in the target database,
        -- which should allow for efficient query reuse.
        , SqlBackend -> EntityDef -> [PersistValue] -> InsertSqlResult
    connInsertSql :: EntityDef -> [PersistValue] -> InsertSqlResult
        -- ^ This function generates the SQL and values necessary for
        -- performing an insert against the database.
        , SqlBackend
    -> Maybe (EntityDef -> [[PersistValue]] -> InsertSqlResult)
    connInsertManySql :: Maybe (EntityDef -> [[PersistValue]] -> InsertSqlResult)
        -- ^ SQL for inserting many rows and returning their primary keys, for
        -- backends that support this functionality. If 'Nothing', rows will be
        -- inserted one-at-a-time using 'connInsertSql'.
        , SqlBackend
    -> Maybe
         (EntityDef -> NonEmpty (FieldNameHS, FieldNameDB) -> Text -> Text)
    connUpsertSql :: Maybe (EntityDef -> NonEmpty (FieldNameHS, FieldNameDB) -> Text -> Text)
        -- ^ Some databases support performing UPSERT _and_ RETURN entity
        -- in a single call.
        --
        -- This field when set will be used to generate the UPSERT+RETURN sql given
        -- * an entity definition
        -- * updates to be run on unique key(s) collision
        --
        -- When left as 'Nothing', we find the unique key from entity def before
        -- * trying to fetch an entity by said key
        -- * perform an update when result found, else issue an insert
        -- * return new entity from db
        --
        -- @since 2.6
        , SqlBackend -> Maybe (EntityDef -> Int -> Text)
    connPutManySql :: Maybe (EntityDef -> Int -> Text)
        -- ^ Some databases support performing bulk UPSERT, specifically
        -- "insert or replace many records" in a single call.
        --
        -- This field when set, given
        -- * an entity definition
        -- * number of records to be inserted
        -- should produce a PUT MANY sql with placeholders for records
        --
        -- When left as 'Nothing', we default to using 'defaultPutMany'.
        --
        -- @since 2.8.1
        , SqlBackend -> StatementCache
    connStmtMap :: StatementCache
        -- ^ A reference to the cache of statements. 'Statement's are keyed by
        -- the 'Text' queries that generated them.
        , SqlBackend -> IO ()
    connClose :: IO ()
        -- ^ Close the underlying connection.
        , SqlBackend
    -> [EntityDef]
    -> (Text -> IO Statement)
    -> EntityDef
    -> IO (Either [Text] [(Bool, Text)])
    connMigrateSql
            :: [EntityDef]
            -> (Text -> IO Statement)
            -> EntityDef
            -> IO (Either [Text] [(Bool, Text)])
        -- ^ This function returns the migrations required to include the
        -- 'EntityDef' parameter in the @['EntityDef']@ database. This might
        -- include creating a new table if the entity is not present, or
        -- altering an existing table if it is.
        , SqlBackend
    -> (Text -> IO Statement) -> Maybe IsolationLevel -> IO ()
    connBegin :: (Text -> IO Statement) -> Maybe IsolationLevel -> IO ()
        -- ^ A function to begin a transaction for the underlying database.
        , SqlBackend -> (Text -> IO Statement) -> IO ()
    connCommit :: (Text -> IO Statement) -> IO ()
        -- ^ A function to commit a transaction to the underlying database.
        , SqlBackend -> (Text -> IO Statement) -> IO ()
    connRollback :: (Text -> IO Statement) -> IO ()
        -- ^ A function to roll back a transaction on the underlying database.
        , SqlBackend -> FieldNameDB -> Text
    connEscapeFieldName :: FieldNameDB -> Text
        -- ^ A function to extract and escape the name of the column corresponding
        -- to the provided field.
        --
        -- @since 2.12.0.0
        , SqlBackend -> EntityDef -> Text
    connEscapeTableName :: EntityDef -> Text
        -- ^ A function to extract and escape the name of the table corresponding
        -- to the provided entity. PostgreSQL uses this to support schemas.
        --
        -- @since 2.12.0.0
        , SqlBackend -> Text -> Text
    connEscapeRawName :: Text -> Text
        -- ^ A function to escape raw DB identifiers. MySQL uses backticks, while
        -- PostgreSQL uses quotes, and so on.
        --
        -- @since 2.12.0.0
        , SqlBackend -> Text
    connNoLimit :: Text
        , SqlBackend -> Text
    connRDBMS :: Text
        -- ^ A tag displaying what database the 'SqlBackend' is for. Can be
        -- used to differentiate features in downstream libraries for different
        -- database backends.
        , SqlBackend -> (Int, Int) -> Text -> Text
    connLimitOffset :: (Int,Int) -> Text -> Text
        -- ^ Attach a 'LIMIT/OFFSET' clause to a SQL query. Note that
        -- LIMIT/OFFSET is problematic for performance, and indexed range
        -- queries are the superior way to offer pagination.
        , SqlBackend -> LogFunc
    connLogFunc :: LogFunc
        -- ^ A log function for the 'SqlBackend' to use.
        , SqlBackend -> Maybe Int
    connMaxParams :: Maybe Int
        -- ^ Some databases (probably only Sqlite) have a limit on how
        -- many question-mark parameters may be used in a statement
        --
        -- @since 2.6.1
        , SqlBackend -> Maybe (EntityDef -> Int -> Text)
    connRepsertManySql :: Maybe (EntityDef -> Int -> Text)
        -- ^ Some databases support performing bulk an atomic+bulk INSERT where
        -- constraint conflicting entities can replace existing entities.
        --
        -- This field when set, given
        -- * an entity definition
        -- * number of records to be inserted
        -- should produce a INSERT sql with placeholders for primary+record fields
        --
        -- When left as 'Nothing', we default to using 'defaultRepsertMany'.
        --
        -- @since 2.9.0
        , SqlBackend -> Vault
    connVault :: Vault
        -- ^ Carry arbitrary payloads for the connection that
        -- may be used to propagate information into hooks.
        , SqlBackend -> SqlBackendHooks
    connHooks :: SqlBackendHooks
        -- ^ Instrumentation hooks that may be used to track the
        -- behaviour of a backend.
        }

    newtype SqlBackendHooks = SqlBackendHooks
        { SqlBackendHooks -> SqlBackend -> Text -> Statement -> IO Statement
    hookGetStatement :: SqlBackend -> Text -> Statement -> IO Statement
        }

    emptySqlBackendHooks :: SqlBackendHooks
    emptySqlBackendHooks :: SqlBackendHooks
    emptySqlBackendHooks = SqlBackendHooks
        { hookGetStatement :: SqlBackend -> Text -> Statement -> IO Statement
    hookGetStatement = \SqlBackend
    _ Text
    _ Statement
    s -> Statement -> IO Statement
    forall a. a -> IO a
    forall (f :: * -> *) a. Applicative f => a -> f a
    pure Statement
    s
        }

    -- | A function for creating a value of the 'SqlBackend' type. You should prefer
    -- to use this instead of the constructor for 'SqlBackend', because default
    -- values for this will be provided for new fields on the record when new
    -- functionality is added.
    --
    -- @since 2.13.0.0
    mkSqlBackend :: MkSqlBackendArgs -> SqlBackend
    mkSqlBackend :: MkSqlBackendArgs -> SqlBackend
    mkSqlBackend MkSqlBackendArgs {IO ()
    Text
    IORef (Map Text Statement)
    [EntityDef]
    -> (Text -> IO Statement)
    -> EntityDef
    -> IO (Either [Text] [(Bool, Text)])
    (Int, Int) -> Text -> Text
    Text -> IO Statement
    Text -> Text
    LogFunc
    FieldNameDB -> Text
    EntityDef -> Text
    EntityDef -> [PersistValue] -> InsertSqlResult
    (Text -> IO Statement) -> IO ()
    (Text -> IO Statement) -> Maybe IsolationLevel -> IO ()
    connInsertSql :: MkSqlBackendArgs -> EntityDef -> [PersistValue] -> InsertSqlResult
    connPrepare :: Text -> IO Statement
    connInsertSql :: EntityDef -> [PersistValue] -> InsertSqlResult
    connStmtMap :: IORef (Map Text Statement)
    connClose :: IO ()
    connMigrateSql :: [EntityDef]
    -> (Text -> IO Statement)
    -> EntityDef
    -> IO (Either [Text] [(Bool, Text)])
    connBegin :: (Text -> IO Statement) -> Maybe IsolationLevel -> IO ()
    connCommit :: (Text -> IO Statement) -> IO ()
    connRollback :: (Text -> IO Statement) -> IO ()
    connEscapeFieldName :: FieldNameDB -> Text
    connEscapeTableName :: EntityDef -> Text
    connEscapeRawName :: Text -> Text
    connNoLimit :: Text
    connRDBMS :: Text
    connLimitOffset :: (Int, Int) -> Text -> Text
    connLogFunc :: LogFunc
    connLogFunc :: MkSqlBackendArgs -> LogFunc
    connLimitOffset :: MkSqlBackendArgs -> (Int, Int) -> Text -> Text
    connRDBMS :: MkSqlBackendArgs -> Text
    connNoLimit :: MkSqlBackendArgs -> Text
    connEscapeRawName :: MkSqlBackendArgs -> Text -> Text
    connEscapeTableName :: MkSqlBackendArgs -> EntityDef -> Text
    connEscapeFieldName :: MkSqlBackendArgs -> FieldNameDB -> Text
    connRollback :: MkSqlBackendArgs -> (Text -> IO Statement) -> IO ()
    connCommit :: MkSqlBackendArgs -> (Text -> IO Statement) -> IO ()
    connBegin :: MkSqlBackendArgs
    -> (Text -> IO Statement) -> Maybe IsolationLevel -> IO ()
    connMigrateSql :: MkSqlBackendArgs
    -> [EntityDef]
    -> (Text -> IO Statement)
    -> EntityDef
    -> IO (Either [Text] [(Bool, Text)])
    connClose :: MkSqlBackendArgs -> IO ()
    connStmtMap :: MkSqlBackendArgs -> IORef (Map Text Statement)
    connPrepare :: MkSqlBackendArgs -> Text -> IO Statement
    ..} =
        SqlBackend
            { connMaxParams :: Maybe Int
    connMaxParams = Maybe Int
    forall a. Maybe a
    Nothing
            , connRepsertManySql :: Maybe (EntityDef -> Int -> Text)
    connRepsertManySql = Maybe (EntityDef -> Int -> Text)
    forall a. Maybe a
    Nothing
            , connPutManySql :: Maybe (EntityDef -> Int -> Text)
    connPutManySql = Maybe (EntityDef -> Int -> Text)
    forall a. Maybe a
    Nothing
            , connUpsertSql :: Maybe
      (EntityDef -> NonEmpty (FieldNameHS, FieldNameDB) -> Text -> Text)
    connUpsertSql = Maybe
      (EntityDef -> NonEmpty (FieldNameHS, FieldNameDB) -> Text -> Text)
    forall a. Maybe a
    Nothing
            , connInsertManySql :: Maybe (EntityDef -> [[PersistValue]] -> InsertSqlResult)
    connInsertManySql = Maybe (EntityDef -> [[PersistValue]] -> InsertSqlResult)
    forall a. Maybe a
    Nothing
            , connVault :: Vault
    connVault = Vault
    Vault.empty
            , connHooks :: SqlBackendHooks
    connHooks = SqlBackendHooks
    emptySqlBackendHooks
            , connStmtMap :: StatementCache
    connStmtMap = MkStatementCache -> StatementCache
    mkStatementCache (MkStatementCache -> StatementCache)
    -> MkStatementCache -> StatementCache
    forall a b. (a -> b) -> a -> b
    $ IORef (Map Text Statement) -> MkStatementCache
    mkSimpleStatementCache IORef (Map Text Statement)
    connStmtMap
            , IO ()
    Text
    [EntityDef]
    -> (Text -> IO Statement)
    -> EntityDef
    -> IO (Either [Text] [(Bool, Text)])
    (Int, Int) -> Text -> Text
    Text -> IO Statement
    Text -> Text
    LogFunc
    FieldNameDB -> Text
    EntityDef -> Text
    EntityDef -> [PersistValue] -> InsertSqlResult
    (Text -> IO Statement) -> IO ()
    (Text -> IO Statement) -> Maybe IsolationLevel -> IO ()
    connPrepare :: Text -> IO Statement
    connInsertSql :: EntityDef -> [PersistValue] -> InsertSqlResult
    connClose :: IO ()
    connMigrateSql :: [EntityDef]
    -> (Text -> IO Statement)
    -> EntityDef
    -> IO (Either [Text] [(Bool, Text)])
    connBegin :: (Text -> IO Statement) -> Maybe IsolationLevel -> IO ()
    connCommit :: (Text -> IO Statement) -> IO ()
    connRollback :: (Text -> IO Statement) -> IO ()
    connEscapeFieldName :: FieldNameDB -> Text
    connEscapeTableName :: EntityDef -> Text
    connEscapeRawName :: Text -> Text
    connNoLimit :: Text
    connRDBMS :: Text
    connLimitOffset :: (Int, Int) -> Text -> Text
    connLogFunc :: LogFunc
    connPrepare :: Text -> IO Statement
    connInsertSql :: EntityDef -> [PersistValue] -> InsertSqlResult
    connClose :: IO ()
    connMigrateSql :: [EntityDef]
    -> (Text -> IO Statement)
    -> EntityDef
    -> IO (Either [Text] [(Bool, Text)])
    connBegin :: (Text -> IO Statement) -> Maybe IsolationLevel -> IO ()
    connCommit :: (Text -> IO Statement) -> IO ()
    connRollback :: (Text -> IO Statement) -> IO ()
    connEscapeFieldName :: FieldNameDB -> Text
    connEscapeTableName :: EntityDef -> Text
    connEscapeRawName :: Text -> Text
    connNoLimit :: Text
    connRDBMS :: Text
    connLimitOffset :: (Int, Int) -> Text -> Text
    connLogFunc :: LogFunc
    ..
            }

    instance HasPersistBackend SqlBackend where
        type BaseBackend SqlBackend = SqlBackend
        persistBackend :: SqlBackend -> BaseBackend SqlBackend
    persistBackend = SqlBackend -> BaseBackend SqlBackend
    SqlBackend -> SqlBackend
    forall a. a -> a
    id

    instance IsPersistBackend SqlBackend where
        mkPersistBackend :: BaseBackend SqlBackend -> SqlBackend
    mkPersistBackend = BaseBackend SqlBackend -> SqlBackend
    SqlBackend -> SqlBackend
    forall a. a -> a
    id