import * as Context from "../Context.ts";
import * as Effect from "../Effect.ts";
import type * as Queue from "../Queue.ts";
import { Reactivity } from "../reactivity/Reactivity.ts";
import type { ReadonlyRecord } from "../Record.ts";
import * as Scope from "../Scope.ts";
import * as Semaphore from "../Semaphore.ts";
import * as Stream from "../Stream.ts";
import type { NoInfer } from "../Types.ts";
import type * as Connection from "./SqlConnection.ts";
import { SqlError } from "./SqlError.ts";
import type { Compiler, Constructor } from "./Statement.ts";
declare const TypeId = "~effect/sql/SqlClient";
/**
 * SQL client service interface, combining the statement constructor API with
 * connection reservation, transaction handling, and reactive query helpers.
 *
 * @stability unstable
 * @category models
 * @since 4.0.0
 */
export interface SqlClient extends Constructor {
    readonly [TypeId]: typeof TypeId;
    /**
     * Copy of the client for safeql etc.
     */
    readonly safe: this;
    /**
     * Copy of the client without transformations.
     */
    readonly withoutTransforms: () => this;
    readonly reserve: Effect.Effect<Connection.Connection, SqlError, Scope.Scope>;
    /**
     * With the given effect, ensure all sql queries are run in a transaction.
     */
    readonly withTransaction: <R, E, A>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E | SqlError, R>;
    /**
     * The transaction service for this client.
     */
    readonly transactionService: Context.Service<TransactionConnection, TransactionConnection.Service>;
    /**
     * Use the Reactivity service to create a reactive query.
     */
    readonly reactive: <A, E, R>(keys: ReadonlyArray<unknown> | ReadonlyRecord<string, ReadonlyArray<unknown>>, effect: Effect.Effect<A, E, R>) => Stream.Stream<A, E, R>;
    /**
     * Use the Reactivity service to create a reactive
     * query.
     */
    readonly reactiveMailbox: <A, E, R>(keys: ReadonlyArray<unknown> | ReadonlyRecord<string, ReadonlyArray<unknown>>, effect: Effect.Effect<A, E, R>) => Effect.Effect<Queue.Dequeue<A, E>, never, R | Scope.Scope>;
}
/**
 * Service tag for the active SQL client service.
 *
 * **When to use**
 *
 * Use to access or provide the SQL client used to build statements, stream
 * rows, reserve connections, and run transactions.
 *
 * @stability unstable
 * @category services
 * @since 4.0.0
 */
export declare const SqlClient: Context.Service<SqlClient, SqlClient>;
/**
 * Namespace containing types associated with the `SqlClient` service.
 *
 * @stability unstable
 * @since 4.0.0
 */
export declare namespace SqlClient {
    /**
     * Options used to construct a `SqlClient`, including connection acquirers,
     * the SQL compiler, transaction SQL, row transformation, tracing attributes,
     * and optional reactive query integration.
     *
     * @stability unstable
     * @category options
     * @since 4.0.0
     */
    interface MakeOptions {
        readonly acquirer: Connection.Acquirer;
        /**
         * Lends a connection for one statement instead of leasing one into a
         * scope. A client that can do this saves the scope and finalizer per
         * statement; `stream`, transactions, and `reserve` keep the `acquirer`,
         * whose lease outlives the effect that starts it.
         */
        readonly borrower?: Connection.Borrower | undefined;
        readonly compiler: Compiler;
        readonly transactionAcquirer?: Connection.Acquirer;
        readonly spanAttributes: ReadonlyArray<readonly [string, unknown]>;
        readonly transactionService?: Context.Service<TransactionConnection, TransactionConnection.Service>;
        /**
         * Whether the transaction control statements - `BEGIN`, `COMMIT`,
         * `ROLLBACK`, and the savepoint pair - can be prepared like any other
         * statement.
         *
         * **Details**
         *
         * They run on every transaction and never change, so a database that can
         * prepare them stops parsing them again each time. Off by default,
         * because several databases refuse to prepare transaction control at all;
         * a driver has to say that its own does not.
         */
        readonly prepareTransactionControls?: boolean | undefined;
        readonly beginTransaction?: string | undefined;
        readonly rollback?: string | undefined;
        /** Commit SQL, or an effect that commits on the connection and checks the result. */
        readonly commit?: string | ((conn: Connection.Connection) => Effect.Effect<void, SqlError>) | undefined;
        /** Cleanup on the same connection when COMMIT fails. Omit when the driver already ends the transaction. */
        readonly onCommitFailure?: ((conn: Connection.Connection) => Effect.Effect<void, SqlError>) | undefined;
        readonly savepoint?: ((name: string) => string) | undefined;
        /**
         * SQL to release a nested savepoint after success or a successful rollback.
         * Omit to leave savepoints unreleased, including for dialects such as MSSQL
         * that do not support releasing savepoints.
         */
        readonly releaseSavepoint?: ((name: string) => string) | undefined;
        readonly rollbackSavepoint?: ((name: string) => string) | undefined;
        readonly transformRows?: (<A extends object>(row: ReadonlyArray<A>) => ReadonlyArray<A>) | undefined;
        readonly reactiveQueue?: <A, E, R>(keys: ReadonlyArray<unknown> | ReadonlyRecord<string, ReadonlyArray<unknown>>, effect: Effect.Effect<A, E, R>) => Effect.Effect<Queue.Dequeue<A, E>, never, R | Scope.Scope>;
    }
}
/**
 * Constructs a `SqlClient` from connection acquirers, a compiler, transaction
 * commands, tracing attributes, optional row transforms, and reactive query
 * integration.
 *
 * @stability unstable
 * @category constructors
 * @since 4.0.0
 */
export declare const make: (options: SqlClient.MakeOptions) => Effect.Effect<SqlClient, never, Reactivity>;
/**
 * Builds the acquirers and failed-COMMIT cleanup for a SQLite client that
 * shares one connection through a semaphore.
 *
 * **Details**
 *
 * Both acquirers lease the connection into the current scope and hold the
 * semaphore until that scope closes, so a statement or stream keeps the
 * connection until it finishes and another fiber cannot begin a transaction
 * underneath it. Effects that use the connection directly, such as an export,
 * have to run inside `Effect.scoped`.
 *
 * SQLite can keep a transaction open after COMMIT fails, for example on a
 * deferred foreign key violation. `onCommitFailure` rolls it back before the
 * connection is reused. If that ROLLBACK fails, the connection is rejected, and
 * each acquisition retries the ROLLBACK once while holding the semaphore until
 * it succeeds. The database is never reopened, and transactions started with a
 * plain `BEGIN` are only touched after a failed cleanup.
 *
 * Pass `isTransaction` when the driver can report whether a transaction is
 * open. Without it, ROLLBACK always runs and SQLite's "no transaction is
 * active" error counts as clean.
 *
 * @stability unstable
 * @category constructors
 * @since 4.0.0
 */
export declare const makeSqliteAcquirers: <C extends Connection.Connection>(options: {
    readonly connection: Effect.Effect<C, SqlError>;
    readonly semaphore: Semaphore.Semaphore;
    readonly isTransaction?: ((conn: C) => boolean) | undefined;
}) => {
    readonly acquirer: Effect.Effect<C, SqlError, Scope.Scope>;
    readonly transactionAcquirer: Effect.Effect<C, SqlError, Scope.Scope>;
    readonly onCommitFailure: (conn: Connection.Connection) => Effect.Effect<void, SqlError>;
};
/**
 * Builds a transaction wrapper that begins top-level transactions, uses
 * savepoints for nested transactions, commits on success, and rolls back on
 * failure or interruption. Releases nested savepoints when `releaseSavepoint`
 * is provided.
 *
 * @stability unstable
 * @category transactions
 * @since 4.0.0
 */
export declare const makeWithTransaction: <I, S>(options: {
    readonly transactionService: Context.Key<I, readonly [conn: S, counter: number]>;
    readonly spanAttributes: ReadonlyArray<readonly [string, unknown]>;
    readonly acquireConnection: Effect.Effect<readonly [Scope.Closeable | undefined, S], SqlError>;
    readonly begin: (conn: NoInfer<S>) => Effect.Effect<void, SqlError>;
    readonly savepoint: (conn: NoInfer<S>, id: number) => Effect.Effect<void, SqlError>;
    /**
     * Releases a nested savepoint after success or a successful rollback.
     * Omit to leave savepoints unreleased, including for dialects such as MSSQL
     * that do not support releasing savepoints.
     */
    readonly releaseSavepoint?: ((conn: NoInfer<S>, id: number) => Effect.Effect<void, SqlError>) | undefined;
    readonly commit: (conn: NoInfer<S>) => Effect.Effect<void, SqlError>;
    /** Driver-specific recovery before the connection is released after a failed COMMIT. */
    readonly onCommitFailure?: ((conn: NoInfer<S>) => Effect.Effect<void, SqlError>) | undefined;
    readonly rollback: (conn: NoInfer<S>) => Effect.Effect<void, SqlError>;
    readonly rollbackSavepoint: (conn: NoInfer<S>, id: number) => Effect.Effect<void, SqlError>;
}) => <R, E, A>(effect: Effect.Effect<A, E, R>) => Effect.Effect<A, E | SqlError, R>;
/**
 * Phantom identifier for the scoped transaction connection service associated
 * with a SQL client.
 *
 * @stability unstable
 * @category models
 * @since 4.0.0
 */
export interface TransactionConnection {
    readonly _: unique symbol;
}
/**
 * Namespace containing types associated with transaction connection services.
 *
 * @stability unstable
 * @since 4.0.0
 */
export declare namespace TransactionConnection {
    /**
     * Service payload stored during a transaction, containing the active
     * connection and nested transaction depth.
     *
     * @stability unstable
     * @category services
     * @since 4.0.0
     */
    type Service = readonly [conn: Connection.Connection, depth: number];
}
/**
 * Creates a unique context service tag for the active transaction connection of
 * a specific SQL client.
 *
 * @stability unstable
 * @category services
 * @since 4.0.0
 */
export declare const TransactionConnection: (clientId: number) => Context.Service<TransactionConnection, TransactionConnection.Service>;
/**
 * Context reference used by SQL integrations to opt in to safe integer
 * handling; defaults to `false`.
 *
 * @stability unstable
 * @category services
 * @since 4.0.0
 */
export declare const SafeIntegers: Context.Reference<boolean>;
export {};
//# sourceMappingURL=SqlClient.d.ts.map