/** @packageDocumentation
 * @module ECDb
 */
import { Id64String } from "@itwin/core-bentley";
import { IModelDb } from "./IModelDb";
import { ChangeInstance, ChangesetReaderArgs, ChangeSource } from "./ChangesetReaderTypes";
import { AnyDb, SqliteChangeOp } from "./SqliteChangesetReader";
/**
 * Reads EC-typed changeset data natively from a changeset file, changeset group,
 * in-memory transaction, or local un-pushed changes.
 *
 * Implements [ChangeSource]($backend) so rows can be fed directly into
 * [PartialChangeUnifier]($backend) to merge partial (per-table) instances into
 * complete EC instances.
 *
 * When the current row is a non-EC internal SQLite table, [[isECTable]] is `false`
 * and both [[inserted]] and [[deleted]] remain `undefined`.
 *
 * @note The native reader operates one SQLite table-row at a time. Multi-table EC
 * instances must be merged using [PartialChangeUnifier]($backend).
 * @beta
 */
export declare class ChangesetReader implements Disposable, ChangeSource {
    private static readonly defaultSpillThresholdInBytes;
    private readonly _nativeReader;
    private _rowOptions?;
    private _batchSizeOverride?;
    private _propFilter;
    private _changeIndex;
    /** Rows fetched in the most recent native batch call. */
    private _cache;
    /**
     * Index of the current row in `_cache`.
     * Equals `_cache.length` (i.e. out-of-bounds) when no row is active:
     * initial state, after exhaustion, or after close().
     */
    private _cacheIndex;
    /** Cached result of the `inserted` getter for the current row. `undefined` when not yet computed or not applicable. */
    private _cachedInserted;
    /** Cached result of the `deleted` getter for the current row. `undefined` when not yet computed or not applicable. */
    private _cachedDeleted;
    /** The db used for EC schema resolution. */
    readonly db: AnyDb;
    /** Returns the active cached row, throwing if no row is current.
     * @internal */
    private get _currentRow();
    /** Returns the batch size to use for native step() calls based on the active property filter.
     * @internal */
    private get _batchSize();
    /**
     * `true` when the current row belongs to an EC-mapped table.
     * Valid only after a successful call to [[step]].
     * @throws [[IModelError]] if called before a successful [[step]] call.
     * @beta
     */
    get isECTable(): boolean;
    /**
     * Name of the SQLite table for the current change row.
     * Valid only after a successful call to [[step]].
     * @throws [[IModelError]] if called before a successful [[step]] call.
     * @beta
     */
    get tableName(): string;
    /**
     * `true` when the current change was applied indirectly
     * Valid only after a successful call to [[step]].
     * @throws [[IModelError]] if called before a successful [[step]] call.
     * @beta
     */
    get isIndirectChange(): boolean;
    /**
     * Post-change (inserted or updated-new) EC instance, computed lazily after each [[step]] call.
     * `undefined` when the current row is a Delete or a non-EC table row or [[step]] returned false.
     * For UPDATE,inserted instances indicate the new state of the instance after the change has been applied and
     * deleted instances indicate the old state of the instance before the change has been applied.
     * For INSERT, inserted instances indicate the new state of the instance after the change has been applied and deleted instances are undefined.
     * For DELETE, deleted instances indicate the old state of the instance before the change has been applied and inserted instances are undefined.
     * @beta
     */
    get inserted(): ChangeInstance | undefined;
    /**
     * Pre-change (deleted or updated-old) EC instance, computed lazily after each [[step]] call.
     * `undefined` when the current row is an Insert or a non-EC table row or [[step]] returned false.
     * @beta
     */
    get deleted(): ChangeInstance | undefined;
    private constructor();
    /** Map public RowFormatOptions to the native adaptor options.
     * @internal */
    private toNativeRowOptions;
    /**
     * Open a changeset file from disk.
     * @param args.fileName Absolute path to the changeset file.
     * @param args.db Database at or after the changeset's ending state, used for schema resolution.
     * @param args.invert When `true`, invert all operations (Insert↔Delete, New↔Old).
     * @param args.rowOptions Row adaptor options controlling how EC property values are formatted.
     * @param args.propFilter Controls which properties are included. Defaults to `All`.
     * @throws if the native layer fails to open the file.
     * @beta
     */
    static openFile(args: {
        readonly fileName: string;
    } & ChangesetReaderArgs): ChangesetReader;
    /**
     * Concatenate multiple changeset files and read them as a single logical stream.
     * @param args.changesetFiles Ordered list of changeset file paths.
     * @param args.db Database with schema at or ahead of the last changeset.
     * @param args.invert When `true`, invert all operations (Insert↔Delete, New↔Old).
     * @param args.rowOptions Row adaptor options controlling how EC property values are formatted.
     * @param args.propFilter Controls which properties are included. Defaults to `All`.
     * @param args.spillThresholdInBytes When the total size of the changeset data in the change group exceeds this threshold (in bytes),
     * the reader writes the data to a temporary file on disk and streams it from there instead of buffering everything in memory.
     * This keeps peak memory usage bounded, making the API suitable for processing large changeset groups under low-memory conditions.
     * Defaults to 50 MiB.
     * @throws if `changesetFiles` is empty, or if the native layer fails to open
     * the group.
     * @beta
     */
    static openGroup(args: {
        readonly changesetFiles: string[];
        spillThresholdInBytes?: number;
    } & ChangesetReaderArgs): ChangesetReader;
    /**
     * Read pending (not yet pushed) local changes from an open IModelDb.
     * @param args.db Must be an [IModelDb]($backend) (not [ECDb]($backend)).
     * @param args.includeInMemoryChanges Also include in-memory (not yet saved to disk) changes.
     * @param args.invert When `true`, invert all operations (Insert↔Delete, New↔Old).
     * @param args.rowOptions Row adaptor options controlling how EC property values are formatted.
     * @param args.propFilter Controls which properties are included. Defaults to `All`.
     * @param args.spillThresholdInBytes When the total size of all local un-pushed saved changes exceeds this threshold (in bytes),
     * the reader writes the data to a temporary file on disk and streams it from there instead of buffering everything in memory.
     * This keeps peak memory usage bounded, making the API suitable for iModels with large local change backlogs under low-memory conditions.
     * Defaults to 50 MiB.
     * @throws if the native layer
     * fails to open the local changes.
     * @beta
     */
    static openLocalChanges(args: Omit<ChangesetReaderArgs, "db"> & {
        db: IModelDb;
        includeInMemoryChanges?: boolean;
        spillThresholdInBytes?: number;
    }): ChangesetReader;
    /**
     * Read the in-memory (not yet saved to disk) changes of an open IModelDb.
     * @param args.db Must be an [IModelDb]($backend).
     * @param args.invert When `true`, invert all operations (Insert↔Delete, New↔Old).
     * @param args.rowOptions Row adaptor options controlling how EC property values are formatted.
     * @param args.propFilter Controls which properties are included. Defaults to `All`.
     * @param args.spillThresholdInBytes When the total size of the in-memory (unsaved) change data exceeds this threshold (in bytes),
     * the reader writes the data to a temporary file on disk and streams it from there instead of buffering everything in memory.
     * This keeps peak memory usage bounded, making the API suitable for large in-memory transactions under low-memory conditions.
     * Defaults to 50 MiB.
     * @throws if the native layer encounters an error while opening the in-memory changes.
     * @beta
     */
    static openInMemoryChanges(args: Omit<ChangesetReaderArgs, "db"> & {
        db: IModelDb;
        spillThresholdInBytes?: number;
    }): ChangesetReader;
    /**
     * Read a single saved transaction by its id.
     * @param args.db Must be an [IModelDb]($backend) ([ECDb]($backend) does not support transactions).
     * @param args.txnId The id of the saved transaction to read.
     * @param args.invert When `true`, invert all operations (Insert↔Delete, New↔Old).
     * @param args.rowOptions Row adaptor options controlling how EC property values are formatted.
     * @param args.propFilter Controls which properties are included. Defaults to `All`.
     * @param args.spillThresholdInBytes When the total size of the transaction's change data exceeds this threshold (in bytes),
     * the reader writes the data to a temporary file on disk and streams it from there instead of buffering everything in memory.
     * This keeps peak memory usage bounded, making the API suitable for large transactions under low-memory conditions.
     * Defaults to 50 MiB.
     * @throws if `txnId` is not found, or
     * the native layer fails to open the transaction data.
     * @beta
     */
    static openTxn(args: Omit<ChangesetReaderArgs, "db"> & {
        db: IModelDb;
        txnId: Id64String;
        spillThresholdInBytes?: number;
    }): ChangesetReader;
    /** Throws if [[step]] has already been called, preventing filter/mode changes mid-iteration.
     * @internal */
    private throwIfAlreadyStepped;
    /** Handle errors that occur while auto closing the reader if there is also an error while opening the reader */
    private handleCloseErrorWhileOpening;
    /**
     * Set the number of rows to fetch and cache while stepping.
     * This is an advanced option that can be used to tune performance for large changesets.
     * Increasing the batch size improves throughput at the cost of higher peak memory; decreasing it keeps memory consumption lower.
     *
     * Default batch sizes when `setBatchSize` is not called:
     * - `InstanceKey` filter: **100**.
     * - `BisCoreElement` filter (any `abbreviateBlobs` setting): **20**.
     * - `All` filter, `abbreviateBlobs: false`: **5**.
     * - `All` filter (blobs abbreviated or unset): **10**.
     *
     * @param batchSize Number of rows to fetch and cache while stepping. Must be a positive integer.
     * @throws [[IModelError]] if [[step]] has already been called successfully, or if `batchSize` is not a positive integer.
     * @beta
     */
    setBatchSize(batchSize: number): void;
    /**
     * Restrict iteration to changes from the named SQLite tables.
     * That means the rows for changes from other tables will be skipped entirely and won't be visible through the reader.
     * @param tableNames SQLite table names to include.
     * Note: Table names must be provided in the correct case for proper filtering.
     * @throws if [[step]] has already been called and the reader successfully stepped at least once(i.e. returned true for a step() call) or if the native layer encounters an error while setting the filter.
     * @beta
     */
    setTableNameFilters(tableNames: Set<string>): void;
    /**
     * Restrict iteration to changes with the given operation types.
     * That means the rows for changes with other operation types will be skipped entirely and won't be visible through the reader.
     * @param ops Operations to include.
     * @throws if [[step]] has already been called and the reader successfully stepped at least once(i.e. returned true for a step() call) or if the native layer encounters an error while setting the filter.
     * @beta
     */
    setOpCodeFilters(ops: Set<SqliteChangeOp>): void;
    /**
     * Restrict iteration to changes for the given EC class names.
     * That means the rows for changes from other EC classes will be skipped entirely and won't be visible through the reader.
     * @param classNames EC class names to include. The classNames should be in the full name format(i.e. "SchemaName:ClassName").
     * Note: Schema names and class names must be provided in the correct case for proper filtering. Derived classes are not automatically included, so they must be specified explicitly if needed.
     * @throws if [[step]] has already been called and the reader successfully stepped at least once(i.e. returned true for a step() call) or if the native layer encounters an error while setting the filter.
     * @beta
     */
    setClassNameFilters(classNames: Set<string>): void;
    /**
     * Remove the table-name filters
     * @throws if [[step]] has already been called and the reader successfully stepped at least once(i.e. returned true for a step() call) or if the native layer encounters an error.
     * @beta
     */
    clearTableNameFilters(): void;
    /**
     * Remove the op-code filters
     * @throws if [[step]] has already been called and the reader successfully stepped at least once(i.e. returned true for a step() call) or if the native layer encounters an error.
     * @beta
     */
    clearOpCodeFilters(): void;
    /**
     * Remove the class-name filters
     * @throws if [[step]] has already been called and the reader successfully stepped at least once(i.e. returned true for a step() call) or if the native layer encounters an error.
     * @beta
     */
    clearClassNameFilters(): void;
    /**
     * Enable strict mode on the reader.
     *
     * Strict mode affects how the reader handles a **column-count mismatch** between a change
     * record and the corresponding live database table. Such a mismatch can occur when columns
     * have been added to a table after the changeset was created.
     *
     * When strict mode is **enabled**: if the number of columns recorded in a change row differs
     * from the number of columns currently present in the live table, the reader throws an error
     * instead of processing that row.
     *
     * Use strict mode when you need to be certain that every change row is interpreted against
     * exactly the schema that was in effect when the changeset was written.
     *
     * @see [[disableStrictMode]] — the default (lenient) behaviour.
     * @throws if [[step]] has already been called and the reader successfully stepped at least once(i.e. returned true for a step() call) or if the native layer encounters an error.
     * @beta
     */
    enableStrictMode(): void;
    /**
     * Disable strict mode on the reader (this is the default).
     *
     * When strict mode is **disabled**: if the number of columns recorded in a change row differs
     * from the number of columns currently present in the live table, the reader takes the
     * **minimum** of the two column counts and proceeds normally with that subset. This is safe
     * because SQLite only ever appends new columns at the end of a table and never removes them —
     * so older change records simply lack the trailing columns that were added later, and those
     * missing columns are silently ignored.
     *
     * @see [[enableStrictMode]] — throw on column-count mismatches instead.
     * @throws if [[step]] has already been called and the reader successfully stepped at least once(i.e. returned true for a step() call) or if the native layer encounters an error.
     * @beta
     */
    disableStrictMode(): void;
    /**
     * Advance to the next change.
     * @returns `true` while positioned on a valid change; `false` when the stream is exhausted.
     * @throws if the native layer encounters an error while reading or decoding
     * the next change.
     * @beta
     */
    step(): boolean;
    /**
     * SQLite opcode of the current change.
     * Valid only after a successful call to [[step]].
     * @throws [[IModelError]] if called before a successful [[step]] call.
     * @beta
     */
    get op(): SqliteChangeOp;
    /**
     * Close the reader and release all native resources.
     *
     * @throws if the native layer encounters an error during cleanup. Native resources
     * are not fully released when this throws — check the native error
     * logs for details.
     * @beta
     */
    close(): void;
    /**
     * Implements the `Disposable` contract — delegates to [[close]].
     *
     * @throws if the native layer fails to release its resources (re-thrown from [[close]]).
     * @beta
     */
    [Symbol.dispose](): void;
}
//# sourceMappingURL=ChangesetReader.d.ts.map