dbgate-sqlite-dumper 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +674 -674
- package/README.md +247 -230
- package/dist/better-sqlite3.cjs.map +1 -1
- package/dist/better-sqlite3.d.cts +1 -1
- package/dist/better-sqlite3.d.ts +1 -1
- package/dist/better-sqlite3.js.map +1 -1
- package/dist/d1.cjs +260 -0
- package/dist/d1.cjs.map +1 -0
- package/dist/d1.d.cts +101 -0
- package/dist/d1.d.ts +101 -0
- package/dist/d1.js +229 -0
- package/dist/d1.js.map +1 -0
- package/dist/errors-CplNzuYs.d.cts +20 -0
- package/dist/errors-CplNzuYs.d.ts +20 -0
- package/dist/index.cjs +405 -90
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +58 -24
- package/dist/index.d.ts +58 -24
- package/dist/index.js +400 -89
- package/dist/index.js.map +1 -1
- package/dist/{types-CTyJTzB6.d.cts → types-DziV5ysl.d.cts} +67 -2
- package/dist/{types-CTyJTzB6.d.ts → types-DziV5ysl.d.ts} +67 -2
- package/docs/architecture.md +180 -157
- package/docs/better-sqlite3-adapter.md +83 -83
- package/docs/d1-adapter.md +98 -0
- package/docs/dump-api.md +253 -253
- package/docs/known-limitations.md +100 -88
- package/docs/native-compatibility.md +124 -124
- package/docs/restore-api.md +234 -234
- package/docs/round-trip-testing.md +84 -84
- package/docs/supported-data-types.md +74 -74
- package/docs/supported-objects.md +85 -85
- package/package.json +96 -89
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/connection/types.ts","../src/connection/acquire.ts","../src/connection/session.ts","../src/version/types.ts","../src/version/detect.ts","../src/version/capabilities.ts","../src/security/identifiers.ts","../src/selection/normalize.ts","../src/security/literals.ts","../src/security/redact.ts","../src/writer/streamWriter.ts","../src/writer/bufferWriter.ts","../src/archive/sectionRules.ts","../src/utils/hash.ts","../src/archive/identity.ts","../src/archive/planner.ts","../src/utils/errors.ts","../src/introspection/sqlText.ts","../src/introspection/introspect.ts","../src/renderer/types.ts","../src/restore/complete.ts","../src/renderer/objectRenderers.ts","../src/restore/preview.ts","../src/renderer/plainSql.ts","../src/data/chunkBuilder.ts","../src/data/valueQuery.ts","../src/data/insertExport.ts","../src/compatibility/check.ts","../src/compatibility/unsupported.ts","../src/preflight/preflightRestore.ts","../src/restore/errors.ts","../src/restore/statementInfo.ts","../src/restore/textEncoding.ts","../src/restore/statementParser.ts","../src/restore/sessionState.ts","../src/restore/restoreSqlDump.ts","../src/api/dump.ts"],"sourcesContent":["export * from './connection/index.js';\r\nexport * from './version/index.js';\r\nexport * from './model/index.js';\r\nexport * from './selection/index.js';\r\nexport * from './security/index.js';\r\nexport * from './writer/index.js';\r\nexport * from './archive/index.js';\r\nexport * from './introspection/index.js';\r\nexport * from './renderer/index.js';\r\nexport * from './data/index.js';\r\nexport * from './compatibility/index.js';\r\nexport * from './preflight/index.js';\r\nexport * from './restore/index.js';\r\nexport * from './utils/index.js';\r\nexport * from './api/index.js';\r\n","/**\r\n * Client-agnostic SQLite connection abstraction.\r\n *\r\n * The core package never imports a Node.js driver directly. Callers provide\r\n * a {@link SqliteConnection} (or a {@link SqliteConnectionSource} that can\r\n * acquire one) implemented by an adapter such as\r\n * `dbgate-sqlite-dumper/better-sqlite3`.\r\n *\r\n * SQLite is an embedded engine, so a \"connection\" here is one open database\r\n * handle. The contract is deliberately the same shape the sibling dumper\r\n * packages use for their network drivers, so an application can treat every\r\n * dumper the same way.\r\n */\r\n\r\n/** Scalar values accepted as bound query parameters (`?` placeholders). */\r\nexport type SqliteParameterValue = string | number | bigint | Buffer | Uint8Array | null;\r\n\r\n/** A single SQL statement plus its positional (`?`) parameters. */\r\nexport interface SqliteQuery {\r\n readonly sql: string;\r\n /** Bound in order for each `?` placeholder. Adapters must never string-interpolate these. */\r\n readonly parameters?: readonly SqliteParameterValue[];\r\n}\r\n\r\n/**\r\n * Scalar values that can appear in a returned row: SQLite's five storage\r\n * classes as JavaScript sees them.\r\n *\r\n * `INTEGER` may arrive as `number` or `bigint` depending on the adapter; the\r\n * core never relies on either for exactness. Row data is read through SQL\r\n * that has SQLite itself render every numeric value as text (see\r\n * `data/valueQuery.ts`), so a 64-bit integer or a `REAL`'s exact digits\r\n * never pass through a JavaScript number on the way into the dump.\r\n */\r\nexport type SqliteColumnValue = string | number | bigint | Buffer | Uint8Array | null;\r\n\r\n/** A single result row, keyed by column name. */\r\nexport interface SqliteRow {\r\n readonly [column: string]: SqliteColumnValue;\r\n}\r\n\r\n/** Buffered result of a non-streaming query. */\r\nexport interface SqliteQueryResult<Row extends SqliteRow = SqliteRow> {\r\n readonly rows: readonly Row[];\r\n /** Result column names, in order, when the adapter can report them. */\r\n readonly columns?: readonly string[];\r\n}\r\n\r\nexport interface SqliteStreamOptions {\r\n readonly signal?: AbortSignal;\r\n /**\r\n * Hint for adapters that fetch rows in batches. SQLite steps one row at a\r\n * time in-process, so most adapters simply ignore it.\r\n */\r\n readonly batchSize?: number;\r\n}\r\n\r\n/** Result of executing one statement through {@link SqliteConnection.execute}. */\r\nexport interface SqliteExecResult {\r\n /**\r\n * Rows inserted, updated or deleted by *this* statement — `0` for DDL and\r\n * for statements that return rows. Adapters must not report SQLite's\r\n * `sqlite3_changes()` for a statement that is not DML, because it still\r\n * holds the count from the previous DML statement.\r\n */\r\n readonly changes: number;\r\n}\r\n\r\n/** Structured information about a SQLite error, extracted by an adapter. */\r\nexport interface SqliteErrorInfo {\r\n /** Symbolic (extended) result code, e.g. `SQLITE_CONSTRAINT_UNIQUE`. */\r\n readonly code?: string;\r\n /** Numeric (extended) result code, e.g. `2067`, when the adapter can report it. */\r\n readonly errno?: number;\r\n readonly message: string;\r\n}\r\n\r\n/**\r\n * One open SQLite database handle.\r\n *\r\n * Implementations must serialize statements sent through the same handle.\r\n * In particular, while a {@link stream} is being consumed no other statement\r\n * is sent on it — this package never interleaves them, because most\r\n * synchronous drivers refuse to run a second statement while one is still\r\n * stepping.\r\n */\r\nexport interface SqliteConnection {\r\n query<Row extends SqliteRow = SqliteRow>(\r\n query: SqliteQuery,\r\n signal?: AbortSignal,\r\n ): Promise<SqliteQueryResult<Row>>;\r\n\r\n /** Streams rows without buffering the full result set in memory. */\r\n stream<Row extends SqliteRow = SqliteRow>(\r\n query: SqliteQuery,\r\n options?: SqliteStreamOptions,\r\n ): AsyncIterable<Row>;\r\n\r\n /**\r\n * Executes one already-complete statement's SQL text with no parameter\r\n * binding and no client-side rewriting.\r\n *\r\n * Restore routes every statement through this rather than `query()`\r\n * because a dump's statement text must reach SQLite byte for byte: a driver\r\n * that treats `?` or `:name` as a placeholder would corrupt any `INSERT`\r\n * carrying one inside a string literal. Adapters that cannot make this\r\n * guarantee may omit it; callers then fall back to `query()` with no\r\n * parameters.\r\n */\r\n execute?(sql: string, signal?: AbortSignal): Promise<SqliteExecResult>;\r\n\r\n /** Extracts structured error fields from a driver error, for diagnostics. */\r\n describeError?(error: unknown): SqliteErrorInfo | undefined;\r\n\r\n /**\r\n * Whether a transaction is open on this handle (`!sqlite3_get_autocommit`).\r\n *\r\n * SQLite has no SQL-level way to ask this, and it matters: a restore that\r\n * stops part-way through a dump's own `BEGIN TRANSACTION` must roll it back\r\n * before handing the handle back, or the caller inherits an open\r\n * transaction holding a write lock on the file. Adapters that cannot answer\r\n * may omit it; restore then tracks the script's own transaction statements\r\n * instead.\r\n */\r\n isInTransaction?(): boolean;\r\n\r\n /**\r\n * Turns `SQLITE_DBCONFIG_DEFENSIVE` on or off.\r\n *\r\n * A dump of a database containing virtual tables recreates them by\r\n * inserting into `sqlite_schema` under `PRAGMA writable_schema=ON` — exactly\r\n * as the native `.dump` does — and defensive mode forbids that. Restore\r\n * uses this, when the adapter provides it, to lift the restriction for the\r\n * duration of such a restore and put it back afterwards.\r\n */\r\n setDefensive?(enabled: boolean): Promise<void>;\r\n\r\n /**\r\n * Requests cancellation of the currently executing statement, if any.\r\n * Synchronous drivers cannot interrupt a statement mid-step; they\r\n * implement this as a no-op, and cancellation then takes effect between\r\n * rows and between statements.\r\n */\r\n cancel(): Promise<void>;\r\n}\r\n\r\n/** A connection acquired from a pool-like source, plus its release callback. */\r\nexport interface AcquiredSqliteConnection {\r\n readonly connection: SqliteConnection;\r\n /**\r\n * Whether this handle is exclusively held for the duration of the\r\n * operation. `false` for a bare {@link SqliteConnection} the caller handed\r\n * over directly — it may be shared, so any state this package changes on\r\n * it must be restored rather than assumed discarded.\r\n */\r\n readonly dedicated: boolean;\r\n /** Idempotent; safe to call more than once. */\r\n release(): Promise<void>;\r\n}\r\n\r\n/**\r\n * Represents a resource that must be acquired to obtain one database\r\n * handle, such as a pool of handles onto the same file. Direct\r\n * {@link SqliteConnection} instances are borrowed by the library and are\r\n * never closed by it.\r\n */\r\nexport interface SqliteConnectionSource {\r\n acquire(signal?: AbortSignal): Promise<AcquiredSqliteConnection>;\r\n}\r\n\r\n/** Anything the public API accepts in place of a database handle. */\r\nexport type SqliteConnectionInput = SqliteConnection | SqliteConnectionSource;\r\n\r\nexport function isSqliteConnectionSource(\r\n input: SqliteConnectionInput,\r\n): input is SqliteConnectionSource {\r\n return typeof (input as SqliteConnectionSource).acquire === 'function';\r\n}\r\n","import type {\r\n AcquiredSqliteConnection,\r\n SqliteConnection,\r\n SqliteConnectionInput,\r\n SqliteExecResult,\r\n} from './types.js';\r\nimport { isSqliteConnectionSource } from './types.js';\r\n\r\n/**\r\n * Normalizes a {@link SqliteConnectionInput} into an acquired connection with\r\n * a release callback. A direct connection resolves immediately with a no-op\r\n * release and `dedicated: false` (the caller may be sharing it); a source is\r\n * asked for one handle through its own `acquire()`, which is what snapshot\r\n * consistency requires.\r\n */\r\nexport async function acquireSqliteConnection(\r\n input: SqliteConnectionInput,\r\n signal?: AbortSignal,\r\n): Promise<AcquiredSqliteConnection> {\r\n if (isSqliteConnectionSource(input)) {\r\n return input.acquire(signal);\r\n }\r\n return {\r\n connection: input as SqliteConnection,\r\n dedicated: false,\r\n release: async () => {},\r\n };\r\n}\r\n\r\n/** Runs one statement through `execute()` when the adapter has it, else through `query()`. */\r\nexport async function executeStatement(\r\n connection: SqliteConnection,\r\n sql: string,\r\n signal?: AbortSignal,\r\n): Promise<SqliteExecResult> {\r\n if (connection.execute) {\r\n return connection.execute(sql, signal);\r\n }\r\n await connection.query({ sql }, signal);\r\n return { changes: 0 };\r\n}\r\n\r\n/**\r\n * Coerces an integer-valued catalog cell to a JavaScript number.\r\n *\r\n * Adapters may return SQLite `INTEGER`s as `number` or `bigint`; catalog\r\n * values (column positions, flags, `user_version`) always fit in a double,\r\n * so either shape is accepted here.\r\n */\r\nexport function toNumber(value: unknown, fallback = 0): number {\r\n if (typeof value === 'number') {\r\n return value;\r\n }\r\n if (typeof value === 'bigint') {\r\n return Number(value);\r\n }\r\n if (typeof value === 'string' && value.trim() !== '' && Number.isFinite(Number(value))) {\r\n return Number(value);\r\n }\r\n return fallback;\r\n}\r\n\r\n/** Coerces a text-valued catalog cell to a string, or `null` for SQL `NULL`. */\r\nexport function toText(value: unknown): string | null {\r\n if (value === null || value === undefined) {\r\n return null;\r\n }\r\n if (typeof value === 'string') {\r\n return value;\r\n }\r\n if (value instanceof Uint8Array) {\r\n return Buffer.from(value).toString('utf8');\r\n }\r\n return String(value);\r\n}\r\n","import { executeStatement } from './acquire.js';\r\nimport type { SqliteConnection } from './types.js';\r\n\r\n/**\r\n * How a dump obtains a consistent view of the database.\r\n *\r\n * - `'snapshot'` (default) — opens a read transaction (as a `SAVEPOINT`, see\r\n * below) and performs one read inside it before anything else, so every\r\n * table is read from the same state of the file. In WAL mode that is a\r\n * true snapshot and writers carry on unblocked; in rollback-journal mode\r\n * the transaction holds a `SHARED` lock, which keeps writers out until the\r\n * dump finishes. Either way the result is consistent — it is the same\r\n * mechanism the native `.dump` uses (`SAVEPOINT dump`).\r\n * - `'none'` — no transaction; each statement reads whatever is committed\r\n * when it runs. Only safe when nothing else writes to the database.\r\n */\r\nexport type SqliteConsistencyMode = 'snapshot' | 'none';\r\n\r\nexport interface SqliteDumpSessionOptions {\r\n readonly consistency?: SqliteConsistencyMode;\r\n}\r\n\r\nexport interface SqliteDumpSession {\r\n readonly consistency: SqliteConsistencyMode;\r\n /**\r\n * `true` when the handle was already inside a transaction the caller\r\n * opened, so the dump reads within *their* transaction and sees their\r\n * uncommitted changes. Reported so a caller can tell.\r\n */\r\n readonly joinedExistingTransaction: boolean;\r\n /**\r\n * Ends the read transaction. Idempotent. Never throws for a handle that is\r\n * already closed — cleanup must not mask the error that caused it.\r\n */\r\n finish(): Promise<void>;\r\n}\r\n\r\n/**\r\n * Savepoint name used for the dump's read transaction. Distinct from the\r\n * native shell's `dump` so a dump taken from inside a caller's own savepoint\r\n * named `dump` cannot release theirs by accident.\r\n */\r\nconst DUMP_SAVEPOINT = 'dbgate_sqlite_dump';\r\n\r\n/**\r\n * Opens the dump's read session.\r\n *\r\n * A `SAVEPOINT` rather than `BEGIN`: outside a transaction the two are the\r\n * same (a savepoint then starts a deferred transaction), but inside one a\r\n * `BEGIN` fails while a savepoint nests. A caller who is already in a\r\n * transaction therefore gets a dump of what *they* see instead of an error.\r\n *\r\n * A deferred transaction does not take its read lock until the first read,\r\n * so the session performs one immediately — otherwise the snapshot would be\r\n * taken lazily by whichever catalog query happened to come first, which is\r\n * the same thing but leaves the guarantee to an accident of ordering.\r\n */\r\nexport async function beginSqliteDumpSession(\r\n connection: SqliteConnection,\r\n options?: SqliteDumpSessionOptions,\r\n signal?: AbortSignal,\r\n): Promise<SqliteDumpSession> {\r\n const consistency = options?.consistency ?? 'snapshot';\r\n const joinedExistingTransaction = connection.isInTransaction?.() ?? false;\r\n\r\n if (consistency === 'none') {\r\n return { consistency, joinedExistingTransaction, finish: async () => {} };\r\n }\r\n\r\n await executeStatement(connection, `SAVEPOINT ${DUMP_SAVEPOINT}`, signal);\r\n let finished = false;\r\n const finish = async (): Promise<void> => {\r\n if (finished) {\r\n return;\r\n }\r\n finished = true;\r\n // Deliberately *without* the caller's signal: if the dump was cancelled\r\n // that signal is already aborted, and reusing it would skip the release\r\n // and leave a read transaction (and on rollback-journal databases, a\r\n // SHARED lock) open on a handle the caller may keep using.\r\n await executeStatement(connection, `RELEASE ${DUMP_SAVEPOINT}`).catch(() => {});\r\n };\r\n\r\n try {\r\n await connection.query({ sql: 'SELECT count(*) AS n FROM sqlite_master' }, signal);\r\n } catch (error) {\r\n await finish();\r\n throw error;\r\n }\r\n\r\n return { consistency, joinedExistingTransaction, finish };\r\n}\r\n","/** Normalized SQLite library version. */\r\nexport interface SqliteVersion {\r\n /** Raw `sqlite_version()` string, e.g. `\"3.45.1\"`. */\r\n readonly versionString: string;\r\n readonly majorVersion: number;\r\n readonly minorVersion: number;\r\n readonly patchVersion: number;\r\n /**\r\n * The numeric form SQLite itself uses for `SQLITE_VERSION_NUMBER`:\r\n * `major * 1000000 + minor * 1000 + patch`. `3045001` for 3.45.1.\r\n */\r\n readonly versionNumber: number;\r\n /** `sqlite_source_id()`, identifying the exact check-in, when available. */\r\n readonly sourceId?: string;\r\n}\r\n\r\n/**\r\n * Capabilities derived once from {@link SqliteVersion}. These describe what\r\n * the SQLite library behind a handle understands; they are used both for the\r\n * source (which catalog pragmas introspection may use) and, through\r\n * `compatibility/`, for a restore target (what DDL it can accept).\r\n */\r\nexport interface SqliteCapabilities {\r\n /** `WITHOUT ROWID` tables; 3.8.2+. */\r\n readonly supportsWithoutRowid: boolean;\r\n /** Multi-row `INSERT ... VALUES (...), (...)`; 3.7.11+. */\r\n readonly supportsMultiRowValues: boolean;\r\n /** Table-valued pragma functions (`pragma_table_info(...)`); 3.16.0+. */\r\n readonly supportsPragmaFunctions: boolean;\r\n /** `PRAGMA table_xinfo`, which reports hidden and generated columns; 3.26.0+. */\r\n readonly supportsTableXinfo: boolean;\r\n /** Generated (`GENERATED ALWAYS AS`) columns; 3.31.0+. */\r\n readonly supportsGeneratedColumns: boolean;\r\n /** The `sqlite_schema` alias for `sqlite_master`; 3.33.0+. */\r\n readonly supportsSqliteSchemaAlias: boolean;\r\n /** `PRAGMA writable_schema=RESET`; 3.35.0+. */\r\n readonly supportsWritableSchemaReset: boolean;\r\n /** `STRICT` tables; 3.37.0+. */\r\n readonly supportsStrictTables: boolean;\r\n /** `PRAGMA table_list`, which reports `WITHOUT ROWID`, `STRICT` and shadow tables; 3.37.0+. */\r\n readonly supportsTableList: boolean;\r\n}\r\n\r\n/**\r\n * Parses a `sqlite_version()` string. Only the leading `major.minor.patch`\r\n * is interpreted; anything after it is kept verbatim for reporting.\r\n */\r\nexport function parseSqliteVersion(versionString: string): {\r\n majorVersion: number;\r\n minorVersion: number;\r\n patchVersion: number;\r\n versionNumber: number;\r\n} {\r\n const match = /^(\\d+)\\.(\\d+)(?:\\.(\\d+))?/.exec(versionString.trim());\r\n if (!match) {\r\n throw new Error(`Cannot parse SQLite version string: ${JSON.stringify(versionString)}`);\r\n }\r\n const majorVersion = Number(match[1]);\r\n const minorVersion = Number(match[2]);\r\n const patchVersion = match[3] === undefined ? 0 : Number(match[3]);\r\n return {\r\n majorVersion,\r\n minorVersion,\r\n patchVersion,\r\n versionNumber: majorVersion * 1_000_000 + minorVersion * 1000 + patchVersion,\r\n };\r\n}\r\n","import { toText } from '../connection/acquire.js';\r\nimport type { SqliteConnection, SqliteRow } from '../connection/types.js';\r\nimport { parseSqliteVersion } from './types.js';\r\nimport type { SqliteVersion } from './types.js';\r\n\r\n/**\r\n * Detects the SQLite library version behind a handle.\r\n *\r\n * This is the version of the library the *driver* links, which is not\r\n * necessarily the version of the `sqlite3` command-line shell installed on\r\n * the same machine — `better-sqlite3`, for instance, bundles its own. The\r\n * difference matters for one thing in a dump: `REAL` values are rendered by\r\n * SQLite's own `printf`, whose digit generation changed between releases.\r\n */\r\nexport async function detectSqliteVersion(\r\n connection: SqliteConnection,\r\n signal?: AbortSignal,\r\n): Promise<SqliteVersion> {\r\n const result = await connection.query<SqliteRow>(\r\n { sql: 'SELECT sqlite_version() AS versionString' },\r\n signal,\r\n );\r\n const versionString = toText(result.rows[0]?.versionString);\r\n if (!versionString) {\r\n throw new Error('Unable to detect SQLite version: sqlite_version() returned no data');\r\n }\r\n\r\n let sourceId: string | undefined;\r\n try {\r\n const source = await connection.query<SqliteRow>(\r\n { sql: 'SELECT sqlite_source_id() AS sourceId' },\r\n signal,\r\n );\r\n sourceId = toText(source.rows[0]?.sourceId) ?? undefined;\r\n } catch {\r\n // Optional detail only: a build with the function omitted is still usable.\r\n }\r\n\r\n return {\r\n versionString,\r\n ...parseSqliteVersion(versionString),\r\n ...(sourceId === undefined ? {} : { sourceId }),\r\n };\r\n}\r\n","import type { SqliteCapabilities, SqliteVersion } from './types.js';\r\n\r\n/**\r\n * Derives {@link SqliteCapabilities} from a detected {@link SqliteVersion}.\r\n *\r\n * Gating is by `versionNumber` (`major*1000000 + minor*1000 + patch`), so a\r\n * capability is gated at the exact release that shipped it. Each gate is the\r\n * release named in SQLite's own change log for that feature.\r\n */\r\nexport function detectSqliteCapabilities(version: SqliteVersion): SqliteCapabilities {\r\n const atLeast = (target: number): boolean => version.versionNumber >= target;\r\n return {\r\n supportsWithoutRowid: atLeast(3_008_002),\r\n supportsMultiRowValues: atLeast(3_007_011),\r\n supportsPragmaFunctions: atLeast(3_016_000),\r\n supportsTableXinfo: atLeast(3_026_000),\r\n supportsGeneratedColumns: atLeast(3_031_000),\r\n supportsSqliteSchemaAlias: atLeast(3_033_000),\r\n supportsWritableSchemaReset: atLeast(3_035_000),\r\n supportsStrictTables: atLeast(3_037_000),\r\n supportsTableList: atLeast(3_037_000),\r\n };\r\n}\r\n","/**\r\n * SQLite's keywords, as `sqlite3_keyword_check()` reports them in a default\r\n * build (the 147 listed at https://sqlite.org/lang_keywords.html).\r\n *\r\n * The native `.dump` quotes a table or column name only when it has to —\r\n * when it is not a plain `[A-Za-z_][A-Za-z0-9_]*` identifier, or when it is\r\n * one of these words — and reproducing its output byte for byte means\r\n * making exactly the same decision.\r\n */\r\nconst SQLITE_KEYWORDS: ReadonlySet<string> = new Set(\r\n `ABORT ACTION ADD AFTER ALL ALTER ALWAYS ANALYZE AND AS ASC ATTACH AUTOINCREMENT BEFORE BEGIN\r\n BETWEEN BY CASCADE CASE CAST CHECK COLLATE COLUMN COMMIT CONFLICT CONSTRAINT CREATE CROSS\r\n CURRENT CURRENT_DATE CURRENT_TIME CURRENT_TIMESTAMP DATABASE DEFAULT DEFERRABLE DEFERRED DELETE\r\n DESC DETACH DISTINCT DO DROP EACH ELSE END ESCAPE EXCEPT EXCLUDE EXCLUSIVE EXISTS EXPLAIN FAIL\r\n FILTER FIRST FOLLOWING FOR FOREIGN FROM FULL GENERATED GLOB GROUP GROUPS HAVING IF IGNORE\r\n IMMEDIATE IN INDEX INDEXED INITIALLY INNER INSERT INSTEAD INTERSECT INTO IS ISNULL JOIN KEY LAST\r\n LEFT LIKE LIMIT MATCH MATERIALIZED NATURAL NO NOT NOTHING NOTNULL NULL NULLS OF OFFSET ON OR\r\n ORDER OTHERS OUTER OVER PARTITION PLAN PRAGMA PRECEDING PRIMARY QUERY RAISE RANGE RECURSIVE\r\n REFERENCES REGEXP REINDEX RELEASE RENAME REPLACE RESTRICT RETURNING RIGHT ROLLBACK ROW ROWS\r\n SAVEPOINT SELECT SET TABLE TEMP TEMPORARY THEN TIES TO TRANSACTION TRIGGER UNBOUNDED UNION\r\n UNIQUE UPDATE USING VACUUM VALUES VIEW VIRTUAL WHEN WHERE WINDOW WITH WITHOUT`\r\n .split(/\\s+/)\r\n .filter(word => word !== ''),\r\n);\r\n\r\n/** True when `name` is an SQLite keyword, compared case-insensitively as SQLite does. */\r\nexport function isSqliteKeyword(name: string): boolean {\r\n return SQLITE_KEYWORDS.has(toAsciiUpperCase(name));\r\n}\r\n\r\n/** The number of keywords known to {@link isSqliteKeyword}; exported for tests. */\r\nexport const SQLITE_KEYWORD_COUNT = SQLITE_KEYWORDS.size;\r\n\r\nfunction isAsciiAlpha(code: number): boolean {\r\n return (code >= 0x41 && code <= 0x5a) || (code >= 0x61 && code <= 0x7a);\r\n}\r\n\r\nfunction isAsciiDigit(code: number): boolean {\r\n return code >= 0x30 && code <= 0x39;\r\n}\r\n\r\n/**\r\n * Upper-cases ASCII letters only, which is how SQLite compares identifiers\r\n * and keywords: its case folding is ASCII-only (`sqlite3UpperToLower`), so\r\n * `ß` and `Dž` are never folded and a locale-aware `toUpperCase()` would\r\n * disagree with the engine.\r\n */\r\nexport function toAsciiUpperCase(value: string): string {\r\n return value.replace(/[a-z]+/g, run => run.toUpperCase());\r\n}\r\n\r\n/** Lower-cases ASCII letters only; see {@link toAsciiUpperCase}. */\r\nexport function toAsciiLowerCase(value: string): string {\r\n return value.replace(/[A-Z]+/g, run => run.toLowerCase());\r\n}\r\n\r\n/**\r\n * Whether the native shell would quote `name`, and with what — a port of\r\n * `quoteChar()` from SQLite's `shell.c`:\r\n *\r\n * ```c\r\n * if( !IsAlpha(zName[0]) && zName[0]!='_' ) return '\"';\r\n * for(i=0; zName[i]; i++){\r\n * if( !IsAlnum(zName[i]) && zName[i]!='_' ) return '\"';\r\n * }\r\n * return sqlite3_keyword_check(zName, i) ? '\"' : 0;\r\n * ```\r\n *\r\n * `IsAlpha`/`IsAlnum` are the C-locale classifications, so any non-ASCII\r\n * character forces quoting.\r\n */\r\nexport function needsIdentifierQuoting(name: string): boolean {\r\n if (name.length === 0) {\r\n return true;\r\n }\r\n const first = name.charCodeAt(0);\r\n if (!isAsciiAlpha(first) && first !== 0x5f) {\r\n return true;\r\n }\r\n for (let index = 0; index < name.length; index++) {\r\n const code = name.charCodeAt(index);\r\n if (!isAsciiAlpha(code) && !isAsciiDigit(code) && code !== 0x5f) {\r\n return true;\r\n }\r\n }\r\n return isSqliteKeyword(name);\r\n}\r\n\r\n/**\r\n * Double-quotes an identifier, doubling any embedded `\"`. Always quotes.\r\n *\r\n * Used for every query this package *runs*. Quoting unconditionally there\r\n * removes the whole question of which words are reserved in which SQLite\r\n * release; the output-shaping decision, where the native layout matters, is\r\n * {@link quoteIdentifierIfNeeded}.\r\n */\r\nexport function quoteIdentifier(name: string): string {\r\n return `\"${name.replace(/\"/g, '\"\"')}\"`;\r\n}\r\n\r\n/**\r\n * Quotes an identifier exactly when the native `.dump` would\r\n * ({@link needsIdentifierQuoting}), so `INSERT INTO t` stays unquoted while\r\n * `INSERT INTO \"order\"` and `INSERT INTO \"a b\"` are quoted.\r\n */\r\nexport function quoteIdentifierIfNeeded(name: string): string {\r\n return needsIdentifierQuoting(name) ? quoteIdentifier(name) : name;\r\n}\r\n\r\n/** `\"schema\".\"name\"`, for queries against an attached database. */\r\nexport function quoteQualifiedIdentifier(schemaName: string, name: string): string {\r\n return `${quoteIdentifier(schemaName)}.${quoteIdentifier(name)}`;\r\n}\r\n","import { toAsciiLowerCase } from '../security/identifiers.js';\r\nimport type { DumpSelection, NormalizedDumpSelection } from './types.js';\r\n\r\n/** Folds a name the way SQLite compares identifiers: ASCII letters only. */\r\nexport function foldSqliteName(name: string): string {\r\n return toAsciiLowerCase(name);\r\n}\r\n\r\nfunction toSet(names: readonly string[] | undefined): ReadonlySet<string> | undefined {\r\n return names ? new Set(names.map(foldSqliteName)) : undefined;\r\n}\r\n\r\nexport function normalizeDumpSelection(selection?: DumpSelection): NormalizedDumpSelection {\r\n const normalized = {\r\n tables: toSet(selection?.tables),\r\n excludeTables: new Set((selection?.excludeTables ?? []).map(foldSqliteName)),\r\n views: toSet(selection?.views),\r\n excludeViews: new Set((selection?.excludeViews ?? []).map(foldSqliteName)),\r\n triggers: toSet(selection?.triggers),\r\n excludeTriggers: new Set((selection?.excludeTriggers ?? []).map(foldSqliteName)),\r\n excludeIndexes: new Set((selection?.excludeIndexes ?? []).map(foldSqliteName)),\r\n dataExcludedTables: new Set((selection?.dataExcludedTables ?? []).map(foldSqliteName)),\r\n };\r\n const isPartial =\r\n normalized.tables !== undefined ||\r\n normalized.views !== undefined ||\r\n normalized.triggers !== undefined ||\r\n normalized.excludeTables.size > 0 ||\r\n normalized.excludeViews.size > 0 ||\r\n normalized.excludeTriggers.size > 0 ||\r\n normalized.excludeIndexes.size > 0;\r\n return { ...normalized, isPartial };\r\n}\r\n\r\nfunction isSelected(\r\n name: string,\r\n include: ReadonlySet<string> | undefined,\r\n exclude: ReadonlySet<string>,\r\n): boolean {\r\n const key = foldSqliteName(name);\r\n if (exclude.has(key)) {\r\n return false;\r\n }\r\n return include ? include.has(key) : true;\r\n}\r\n\r\nexport function isTableSelected(name: string, selection: NormalizedDumpSelection): boolean {\r\n return isSelected(name, selection.tables, selection.excludeTables);\r\n}\r\n\r\nexport function isViewSelected(name: string, selection: NormalizedDumpSelection): boolean {\r\n return isSelected(name, selection.views, selection.excludeViews);\r\n}\r\n\r\nexport function isTriggerSelected(name: string, selection: NormalizedDumpSelection): boolean {\r\n return isSelected(name, selection.triggers, selection.excludeTriggers);\r\n}\r\n\r\nexport function isIndexSelected(name: string, selection: NormalizedDumpSelection): boolean {\r\n return !selection.excludeIndexes.has(foldSqliteName(name));\r\n}\r\n\r\n/** True when the table's *rows* should be skipped while its structure is still dumped. */\r\nexport function isTableDataExcluded(name: string, selection: NormalizedDumpSelection): boolean {\r\n return selection.dataExcludedTables.has(foldSqliteName(name));\r\n}\r\n","/**\r\n * SQL literal rendering, ported from the functions SQLite's own shell uses\r\n * for `.dump` (`shell.c`), so a value renders exactly as `sqlite3` renders\r\n * it.\r\n *\r\n * SQLite string literals have exactly one escape: a `'` inside the literal\r\n * is doubled. There are **no** backslash escapes — `'\\n'` is a backslash\r\n * followed by the letter `n` — which is why the shell cannot write a newline\r\n * as `\\n` and instead wraps the literal in a `replace()` call (see\r\n * {@link renderEscapedStringLiteral}).\r\n *\r\n * Every function here works on a JavaScript string in which each code unit\r\n * may be either a real character or — for text that is not valid UTF-8 — one\r\n * byte (a `latin1` \"byte string\"). The characters the escaping reacts to\r\n * (`'`, `\\n`, `\\r`) are ASCII, and no byte of a multi-byte UTF-8 sequence can\r\n * be mistaken for one, so the same code is correct for both representations.\r\n */\r\n\r\n/**\r\n * `unused_string()` from `shell.c`: returns the first of `a`, `b`, `(a0)`,\r\n * `(a1)`, ... that does not occur anywhere in `text`, to stand in for a\r\n * character inside a `replace()`d literal without colliding with the text.\r\n */\r\nfunction unusedString(text: string, a: string, b: string): string {\r\n if (!text.includes(a)) {\r\n return a;\r\n }\r\n if (!text.includes(b)) {\r\n return b;\r\n }\r\n for (let counter = 0; ; counter++) {\r\n const candidate = `(${a}${counter})`;\r\n if (!text.includes(candidate)) {\r\n return candidate;\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * `output_quoted_string()`: `'...'` with every `'` doubled, newlines and\r\n * carriage returns written raw. The shell uses this form under\r\n * `.dump --newlines`.\r\n */\r\nexport function renderQuotedStringLiteral(text: string): string {\r\n return `'${text.replace(/'/g, \"''\")}'`;\r\n}\r\n\r\n/**\r\n * `output_quoted_escaped_string()`: the form the native `.dump` uses by\r\n * default.\r\n *\r\n * A literal containing neither `\\n` nor `\\r` is written as a plain quoted\r\n * string. Otherwise each newline is replaced by a placeholder that does not\r\n * otherwise occur in the text (`\\n`, else `\\012`, else `(\\n0)`, ...) and the\r\n * literal is wrapped in `replace(..., '<placeholder>', char(10))` — and the\r\n * same for carriage returns with `char(13)` — so that the dump keeps one\r\n * statement per line and survives any tool that normalizes line endings.\r\n *\r\n * ```sql\r\n * replace('line one\\nline two','\\n',char(10))\r\n * replace(replace('a\\r\\nb','\\r',char(13)),'\\n',char(10))\r\n * ```\r\n */\r\nexport function renderEscapedStringLiteral(text: string): string {\r\n if (!text.includes('\\n') && !text.includes('\\r')) {\r\n return renderQuotedStringLiteral(text);\r\n }\r\n const hasNewline = text.includes('\\n');\r\n const hasCarriageReturn = text.includes('\\r');\r\n const newlinePlaceholder = hasNewline ? unusedString(text, '\\\\n', '\\\\012') : '';\r\n const carriageReturnPlaceholder = hasCarriageReturn ? unusedString(text, '\\\\r', '\\\\015') : '';\r\n\r\n let body = '';\r\n for (let index = 0; index < text.length; index++) {\r\n const character = text[index] as string;\r\n if (character === \"'\") {\r\n body += \"''\";\r\n } else if (character === '\\n') {\r\n body += newlinePlaceholder;\r\n } else if (character === '\\r') {\r\n body += carriageReturnPlaceholder;\r\n } else {\r\n body += character;\r\n }\r\n }\r\n\r\n // The opening `replace(`s are written newline-first, the closing\r\n // arguments carriage-return-first, exactly as the shell nests them.\r\n let literal = `${hasNewline ? 'replace(' : ''}${hasCarriageReturn ? 'replace(' : ''}'${body}'`;\r\n if (hasCarriageReturn) {\r\n literal += `,'${carriageReturnPlaceholder}',char(13))`;\r\n }\r\n if (hasNewline) {\r\n literal += `,'${newlinePlaceholder}',char(10))`;\r\n }\r\n return literal;\r\n}\r\n\r\nexport type TextLiteralStyle = 'escaped' | 'raw-newlines';\r\n\r\n/**\r\n * Renders a `TEXT` value as a SQL expression.\r\n *\r\n * SQLite text may contain `NUL` characters, which the native shell cannot\r\n * represent at all: it handles values as C strings, so everything after the\r\n * first `NUL` is silently dropped from the dump. This package keeps them,\r\n * joining the pieces with `||char(0)||` — an expression that evaluates to\r\n * the identical value in a database of any text encoding. Text with no\r\n * `NUL`, which is all text in practice, renders exactly as the shell renders\r\n * it.\r\n */\r\nexport function renderTextLiteral(text: string, style: TextLiteralStyle = 'escaped'): string {\r\n const render = style === 'escaped' ? renderEscapedStringLiteral : renderQuotedStringLiteral;\r\n if (!text.includes('\\u0000')) {\r\n return render(text);\r\n }\r\n return text.split('\\u0000').map(render).join('||char(0)||');\r\n}\r\n\r\n/**\r\n * `output_hex_blob()`: `X'...'` in lower-case hexadecimal, which is how the\r\n * native `.dump` writes every `BLOB`. An empty blob is `X''`.\r\n */\r\nexport function renderBlobLiteral(value: Uint8Array): string {\r\n return `X'${Buffer.from(value.buffer, value.byteOffset, value.byteLength).toString('hex')}'`;\r\n}\r\n\r\n/**\r\n * Renders a string as a plain single-quoted SQL literal, for text this\r\n * package composes itself (table names in `INSERT INTO sqlite_schema ...`,\r\n * `sqlite_sequence` filters).\r\n */\r\nexport function quoteStringLiteral(text: string): string {\r\n return renderQuotedStringLiteral(text);\r\n}\r\n","/**\r\n * Redacts the value side of the credential-carrying statements that exist\r\n * in the SQLite world, so a failing statement never echoes an actual secret\r\n * into a preview, a diagnostic, or an error message.\r\n *\r\n * Plain SQLite has no credentials, but the encryption extensions most\r\n * applications use — SQLCipher and the SQLite Encryption Extension — take\r\n * their key through SQL: `PRAGMA key = '...'`, `PRAGMA rekey`,\r\n * `PRAGMA hexkey`/`hexrekey`, `PRAGMA textkey`, and `ATTACH ... KEY '...'`.\r\n * A script that opens an encrypted database starts with exactly such a\r\n * statement.\r\n *\r\n * Deliberately narrow and pattern-based rather than a parser: it covers the\r\n * specific syntax those extensions use, not arbitrary \"looks sensitive\" text.\r\n */\r\nconst SQL_SECRET_PATTERNS: readonly RegExp[] = [\r\n // PRAGMA [schema.]key = 'secret' / PRAGMA key('secret'), and the rekey/hexkey/textkey forms\r\n /(\\bPRAGMA\\s+(?:[\\w\"`[\\]]+\\s*\\.\\s*)?(?:hex|text)?(?:re)?key\\s*(?:=\\s*|\\(\\s*))(?:'(?:[^']|'')*'|\"(?:[^\"]|\"\")*\"|[^\\s;)]+)/gi,\r\n // ATTACH DATABASE 'file' AS name KEY 'secret'\r\n /(\\bATTACH\\b[\\s\\S]*?\\bKEY\\s+)(?:'(?:[^']|'')*'|\"(?:[^\"]|\"\")*\"|X'[0-9A-Fa-f]*'|[^\\s;)]+)/gi,\r\n];\r\n\r\nexport function redactSecrets(text: string): string {\r\n return SQL_SECRET_PATTERNS.reduce(\r\n (result, pattern) =>\r\n result.replace(pattern, (_match, prefix: string) => `${prefix}'***REDACTED***'`),\r\n text,\r\n );\r\n}\r\n","import type { Writable } from 'node:stream';\r\nimport type { DumpWriter } from './types.js';\r\n\r\nfunction throwIfAborted(signal: AbortSignal | undefined): void {\r\n if (signal?.aborted) {\r\n throw new DOMException('The operation was aborted.', 'AbortError');\r\n }\r\n}\r\n\r\n/**\r\n * Writes incrementally to a caller-owned `Writable`, honoring backpressure\r\n * (awaiting the stream's own `drain` when `write()` returns `false`) and\r\n * `AbortSignal` cancellation. Never calls `end()`/`close()` on the stream.\r\n *\r\n * `Buffer` chunks are written verbatim; `string` chunks are encoded as\r\n * UTF-8. See {@link DumpWriter} for why both shapes exist.\r\n */\r\nexport class StreamDumpWriter implements DumpWriter {\r\n private readonly stream: Writable;\r\n private bytes = 0;\r\n private writeError: Error | null = null;\r\n\r\n constructor(stream: Writable) {\r\n this.stream = stream;\r\n }\r\n\r\n get bytesWritten(): number {\r\n return this.bytes;\r\n }\r\n\r\n async write(chunk: string | Buffer, signal?: AbortSignal): Promise<void> {\r\n if (chunk.length === 0) {\r\n return;\r\n }\r\n if (this.writeError) {\r\n throw this.writeError;\r\n }\r\n throwIfAborted(signal);\r\n\r\n const isBuffer = Buffer.isBuffer(chunk);\r\n this.bytes += isBuffer ? chunk.length : Buffer.byteLength(chunk, 'utf8');\r\n\r\n const onWritten = (error?: Error | null): void => {\r\n if (error && !this.writeError) {\r\n this.writeError = error;\r\n }\r\n };\r\n\r\n // Backpressure is gated on `write()`'s return value, with the `drain`\r\n // listener attached in this same tick. Awaiting the completion callback\r\n // first would be wrong: Node emits `drain` *before* running the callbacks\r\n // of the writes that emptied the buffer, so subscribing afterwards waits\r\n // for an event that has already fired and never fires again.\r\n const canWriteMore = isBuffer\r\n ? this.stream.write(chunk, onWritten)\r\n : this.stream.write(chunk, 'utf8', onWritten);\r\n\r\n if (canWriteMore === false) {\r\n await new Promise<void>((resolve, reject) => {\r\n const cleanup = (): void => {\r\n this.stream.removeListener('drain', onDrain);\r\n this.stream.removeListener('error', onError);\r\n signal?.removeEventListener('abort', onAbort);\r\n };\r\n const onDrain = (): void => {\r\n cleanup();\r\n resolve();\r\n };\r\n const onError = (error: Error): void => {\r\n cleanup();\r\n reject(error);\r\n };\r\n // A consumer that stopped reading never emits `drain`, so this await is\r\n // exactly where a cancelled dump would otherwise stall indefinitely.\r\n const onAbort = (): void => {\r\n cleanup();\r\n reject(new DOMException('The operation was aborted.', 'AbortError'));\r\n };\r\n this.stream.once('drain', onDrain);\r\n this.stream.once('error', onError);\r\n signal?.addEventListener('abort', onAbort, { once: true });\r\n });\r\n }\r\n\r\n if (this.writeError) {\r\n throw this.writeError;\r\n }\r\n throwIfAborted(signal);\r\n }\r\n}\r\n","import type { DumpWriter } from './types.js';\r\n\r\n/**\r\n * In-memory {@link DumpWriter}, for tests and bounded previews. Not for\r\n * production dump sizes.\r\n *\r\n * Accumulates `Buffer`s rather than strings so a dump containing text that\r\n * is not valid UTF-8 round-trips byte-exactly; {@link toString} is a\r\n * convenience for the common all-text case and will replace invalid UTF-8\r\n * with U+FFFD, so use {@link toBuffer} when binary fidelity matters.\r\n */\r\nexport class BufferDumpWriter implements DumpWriter {\r\n private readonly chunks: Buffer[] = [];\r\n private bytes = 0;\r\n\r\n get bytesWritten(): number {\r\n return this.bytes;\r\n }\r\n\r\n async write(chunk: string | Buffer, signal?: AbortSignal): Promise<void> {\r\n if (signal?.aborted) {\r\n throw new DOMException('The operation was aborted.', 'AbortError');\r\n }\r\n const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, 'utf8');\r\n this.chunks.push(buffer);\r\n this.bytes += buffer.length;\r\n }\r\n\r\n toBuffer(): Buffer {\r\n return Buffer.concat(this.chunks);\r\n }\r\n\r\n toString(): string {\r\n return this.toBuffer().toString('utf8');\r\n }\r\n}\r\n","import type { ArchiveObjectType, DumpSection } from './types.js';\r\n\r\nconst SECTION_BY_OBJECT_TYPE: Record<ArchiveObjectType, DumpSection> = {\r\n table: 'tables',\r\n tableData: 'tables',\r\n virtualTable: 'tables',\r\n index: 'schema',\r\n trigger: 'schema',\r\n view: 'schema',\r\n};\r\n\r\nconst SECTION_PRIORITY: Record<DumpSection, number> = {\r\n tables: 0,\r\n schema: 1,\r\n};\r\n\r\n/**\r\n * Ordering *within* one table's group in the `tables` section: structure,\r\n * then rows — the native `.dump` writes each table's `INSERT`s directly\r\n * after its `CREATE TABLE`.\r\n */\r\nconst TABLE_GROUP_PRIORITY: Record<ArchiveObjectType, number> = {\r\n table: 0,\r\n virtualTable: 0,\r\n tableData: 1,\r\n index: 0,\r\n trigger: 0,\r\n view: 0,\r\n};\r\n\r\nexport function assignDumpSection(objectType: ArchiveObjectType): DumpSection {\r\n return SECTION_BY_OBJECT_TYPE[objectType];\r\n}\r\n\r\nexport function dumpSectionPriority(section: DumpSection): number {\r\n return SECTION_PRIORITY[section];\r\n}\r\n\r\nexport function tableGroupPriority(objectType: ArchiveObjectType): number {\r\n return TABLE_GROUP_PRIORITY[objectType];\r\n}\r\n","import { createHash } from 'node:crypto';\r\n\r\n/**\r\n * Builds a collision-resistant identity string from ordered parts.\r\n *\r\n * Parts are length-prefixed rather than joined with a separator, because\r\n * SQLite identifiers may contain any character at all — including\r\n * whatever separator would otherwise be chosen. Without the prefix,\r\n * `[\"a.b\", \"c\"]` and `[\"a\", \"b.c\"]` would produce the same identity.\r\n */\r\nexport function createCanonicalIdentity(parts: readonly string[]): string {\r\n return parts.map(part => `${part.length}:${part}`).join('|');\r\n}\r\n\r\n/** Stable short hash of a canonical identity, used as an archive entry's `dumpId`. */\r\nexport function createDumpId(identity: string): string {\r\n return createHash('sha1').update(identity, 'utf8').digest('hex').slice(0, 16);\r\n}\r\n","import { createCanonicalIdentity } from '../utils/hash.js';\r\nimport type { ArchiveObjectType } from './types.js';\r\n\r\nexport interface ArchiveIdentityInput {\r\n readonly objectType: ArchiveObjectType;\r\n readonly schemaName: string;\r\n readonly name: string;\r\n readonly parentName?: string;\r\n}\r\n\r\nexport function createArchiveIdentity(input: ArchiveIdentityInput): string {\r\n return createCanonicalIdentity([\r\n input.objectType,\r\n input.schemaName,\r\n input.name,\r\n input.parentName ?? '',\r\n ]);\r\n}\r\n","import type { SqliteDatabase, SqliteTable } from '../model/database.js';\r\nimport type { SqliteDiagnostic } from '../model/diagnostics.js';\r\nimport {\r\n foldSqliteName,\r\n isIndexSelected,\r\n isTableDataExcluded,\r\n isTableSelected,\r\n isTriggerSelected,\r\n isViewSelected,\r\n normalizeDumpSelection,\r\n} from '../selection/normalize.js';\r\nimport type { DumpObjectKinds, NormalizedDumpSelection } from '../selection/types.js';\r\nimport { createDumpId } from '../utils/hash.js';\r\nimport { createArchiveIdentity } from './identity.js';\r\nimport { assignDumpSection } from './sectionRules.js';\r\nimport type {\r\n ArchiveCycle,\r\n ArchiveDependency,\r\n ArchiveEntry,\r\n ArchiveObjectType,\r\n DumpArchiveInspection,\r\n DumpMode,\r\n UnsatisfiedDependency,\r\n} from './types.js';\r\n\r\nexport interface InspectDumpArchiveOptions {\r\n readonly mode?: DumpMode;\r\n readonly selection?: NormalizedDumpSelection;\r\n readonly objectKinds?: DumpObjectKinds;\r\n}\r\n\r\ninterface MutableEntry {\r\n dumpId: string;\r\n identity: string;\r\n objectType: ArchiveObjectType;\r\n name: string;\r\n parentName?: string;\r\n tableKind?: SqliteTable['kind'];\r\n systemRowFilter?: readonly string[];\r\n dependsOn: ArchiveDependency[];\r\n}\r\n\r\n/** `sqlite3_strglob(\"sqlite_stat?\", name)` — the tables `ANALYZE` maintains. */\r\nexport function isStatisticsTableName(name: string): boolean {\r\n return /^sqlite_stat[\\s\\S]$/.test(name);\r\n}\r\n\r\n/** The native shell compares this name with `strcmp`, so case-sensitively. */\r\nexport const SEQUENCE_TABLE_NAME = 'sqlite_sequence';\r\n\r\n/**\r\n * Converts a normalized {@link SqliteDatabase} into an ordered,\r\n * dependency-validated set of {@link ArchiveEntry} objects.\r\n *\r\n * Independent of SQL text, output streams and connections: it decides only\r\n * *what* is dumped and in *what order*. The order is the native `.dump`'s —\r\n * see {@link DumpSection} — which is creation order (`sqlite_schema` rowid)\r\n * rather than a topological sort. Creation order is itself a valid\r\n * dependency order for everything SQLite checks at `CREATE` time, and the\r\n * dump's `PRAGMA foreign_keys=OFF` covers the rest. Dependencies are still\r\n * recorded and then *verified* against that order, so a model or planning\r\n * bug surfaces as `valid: false` rather than as an unrestorable dump.\r\n */\r\nexport function inspectDumpArchive(\r\n database: SqliteDatabase,\r\n options: InspectDumpArchiveOptions = {},\r\n): DumpArchiveInspection {\r\n const mode = options.mode ?? 'full';\r\n const selection = options.selection ?? normalizeDumpSelection();\r\n const kinds = options.objectKinds ?? {};\r\n const includeTables = kinds.includeTables ?? true;\r\n const includeViews = kinds.includeViews ?? true;\r\n const includeIndexes = kinds.includeIndexes ?? true;\r\n const includeTriggers = kinds.includeTriggers ?? true;\r\n const includeVirtualTables = kinds.includeVirtualTables ?? true;\r\n const includeSystemTables = kinds.includeSystemTables ?? true;\r\n\r\n const wantsSchema = mode !== 'data-only';\r\n const wantsData = mode !== 'schema-only';\r\n const schemaName = database.schemaName;\r\n\r\n const diagnostics: SqliteDiagnostic[] = [];\r\n const entries: MutableEntry[] = [];\r\n const byDumpId = new Map<string, MutableEntry>();\r\n\r\n function addEntry(\r\n objectType: ArchiveObjectType,\r\n name: string,\r\n extra: Partial<Pick<MutableEntry, 'parentName' | 'tableKind' | 'systemRowFilter'>> = {},\r\n ): string {\r\n const identity = createArchiveIdentity({\r\n objectType,\r\n schemaName,\r\n name,\r\n ...(extra.parentName === undefined ? {} : { parentName: extra.parentName }),\r\n });\r\n const dumpId = createDumpId(identity);\r\n if (byDumpId.has(dumpId)) {\r\n diagnostics.push({\r\n severity: 'error',\r\n code: 'duplicate-archive-identity',\r\n message: `Duplicate archive identity for ${objectType} \"${name}\" in schema \"${schemaName}\"`,\r\n objectReference: { kind: 'table', schemaName, name },\r\n });\r\n return dumpId;\r\n }\r\n const entry: MutableEntry = { dumpId, identity, objectType, name, ...extra, dependsOn: [] };\r\n entries.push(entry);\r\n byDumpId.set(dumpId, entry);\r\n return dumpId;\r\n }\r\n\r\n function addDependency(\r\n fromDumpId: string,\r\n toDumpId: string | undefined,\r\n strength: ArchiveDependency['strength'],\r\n ): void {\r\n if (!toDumpId || fromDumpId === toDumpId) {\r\n return;\r\n }\r\n const entry = byDumpId.get(fromDumpId);\r\n if (!entry) {\r\n return;\r\n }\r\n const existing = entry.dependsOn.find(dependency => dependency.targetDumpId === toDumpId);\r\n if (existing) {\r\n if (strength === 'hard' && existing.strength === 'preference') {\r\n entry.dependsOn = entry.dependsOn.filter(\r\n dependency => dependency.targetDumpId !== toDumpId,\r\n );\r\n entry.dependsOn.push({ targetDumpId: toDumpId, strength: 'hard' });\r\n }\r\n return;\r\n }\r\n entry.dependsOn.push({ targetDumpId: toDumpId, strength });\r\n }\r\n\r\n const tablesByName = new Map(database.tables.map(table => [foldSqliteName(table.name), table]));\r\n\r\n const isUserTableSelected = (table: SqliteTable): boolean => {\r\n switch (table.kind) {\r\n case 'table':\r\n return includeTables && isTableSelected(table.name, selection);\r\n case 'virtual':\r\n return includeVirtualTables && isTableSelected(table.name, selection);\r\n case 'shadow': {\r\n // A shadow table belongs to its virtual table and follows it: it is\r\n // the virtual table's data. Selecting `ft` selects `ft_data`,\r\n // `ft_idx`, ... too, just as the native `.dump ft` does.\r\n const owner =\r\n table.ownerVirtualTable === undefined\r\n ? undefined\r\n : tablesByName.get(foldSqliteName(table.ownerVirtualTable));\r\n if (!owner) {\r\n return includeTables && isTableSelected(table.name, selection);\r\n }\r\n return includeVirtualTables && isTableSelected(owner.name, selection);\r\n }\r\n case 'system':\r\n return false;\r\n }\r\n };\r\n\r\n const selectedUserTables = database.tables.filter(isUserTableSelected);\r\n const selectedTableNames = selectedUserTables.map(table => table.name);\r\n\r\n const tableDumpId = new Map<string, string>();\r\n const tableDataDumpId = new Map<string, string>();\r\n\r\n // Pass 1 — tables, in creation order, with sqlite_sequence last. This is\r\n // `ORDER BY tbl_name='sqlite_sequence', rowid`, the native query.\r\n const orderedTables = [...database.tables].sort((a, b) => {\r\n const aLast = a.name === SEQUENCE_TABLE_NAME ? 1 : 0;\r\n const bLast = b.name === SEQUENCE_TABLE_NAME ? 1 : 0;\r\n return aLast - bLast || a.schemaRowid - b.schemaRowid;\r\n });\r\n\r\n for (const table of orderedTables) {\r\n const key = foldSqliteName(table.name);\r\n\r\n if (table.kind === 'system') {\r\n const isSequence = table.name === SEQUENCE_TABLE_NAME;\r\n if (!includeSystemTables || (!isSequence && !isStatisticsTableName(table.name))) {\r\n // Any other `sqlite_` table is internal and never dumped natively either.\r\n continue;\r\n }\r\n const systemRowFilter = selection.isPartial ? selectedTableNames : undefined;\r\n if (systemRowFilter && systemRowFilter.length === 0) {\r\n continue;\r\n }\r\n const extra = {\r\n tableKind: table.kind,\r\n ...(systemRowFilter === undefined ? {} : { systemRowFilter }),\r\n };\r\n let structureId: string | undefined;\r\n if (wantsSchema && wantsData) {\r\n // `DELETE FROM sqlite_sequence;` / `ANALYZE sqlite_schema;` only make\r\n // sense together with the rows that follow them; a schema-only dump\r\n // carries neither counters nor statistics.\r\n structureId = addEntry('table', table.name, extra);\r\n tableDumpId.set(key, structureId);\r\n }\r\n if (wantsData) {\r\n const dataId = addEntry('tableData', table.name, { ...extra, parentName: table.name });\r\n tableDataDumpId.set(key, dataId);\r\n addDependency(dataId, structureId, 'hard');\r\n if (!wantsSchema) {\r\n diagnostics.push({\r\n severity: 'warning',\r\n code: 'data-only-system-table',\r\n message: isSequence\r\n ? 'A data-only dump inserts the sqlite_sequence rows without first clearing the table, exactly as the native .dump --data-only does; restoring it into a database whose tables already advanced their AUTOINCREMENT counters leaves duplicate counter rows. Set objectKinds.includeSystemTables to false to leave the counters to the inserts themselves.'\r\n : `A data-only dump inserts into ${table.name} without creating it first, exactly as the native .dump --data-only does; restoring it into a database that has never been analyzed fails with \"no such table\". Set objectKinds.includeSystemTables to false to leave statistics out.`,\r\n objectReference: { kind: 'table', schemaName, name: table.name },\r\n });\r\n }\r\n }\r\n continue;\r\n }\r\n\r\n if (!isUserTableSelected(table)) {\r\n continue;\r\n }\r\n\r\n if (table.kind === 'virtual') {\r\n if (wantsSchema) {\r\n tableDumpId.set(key, addEntry('virtualTable', table.name, { tableKind: table.kind }));\r\n } else if (!isTableDataExcluded(table.name, selection)) {\r\n // A native quirk reproduced on purpose: `.dump --data-only` checks\r\n // for data-only *before* it checks for a virtual table, so it selects\r\n // the virtual table's rows through the module — in addition to the\r\n // shadow tables' rows, which hold the same data.\r\n tableDataDumpId.set(\r\n key,\r\n addEntry('tableData', table.name, { tableKind: table.kind, parentName: table.name }),\r\n );\r\n diagnostics.push({\r\n severity: 'warning',\r\n code: 'data-only-virtual-table',\r\n message: `A data-only dump carries the rows of virtual table \"${table.name}\" twice — through the table itself and in its shadow tables — exactly as the native .dump --data-only does. Restoring it into a database where \"${table.name}\" already exists conflicts with that table's own shadow rows; exclude the shadow tables through selection.dataExcludedTables to load the rows through the virtual table only.`,\r\n objectReference: { kind: 'virtualTable', schemaName, name: table.name },\r\n });\r\n }\r\n continue;\r\n }\r\n\r\n if (table.kind === 'shadow' && !wantsData && table.ownerVirtualTable !== undefined) {\r\n // A schema-only dump creates each virtual table through its module,\r\n // whose constructor creates the shadow tables itself (see the\r\n // renderer); defensive mode would refuse them as statements anyway.\r\n continue;\r\n }\r\n\r\n let structureId: string | undefined;\r\n if (wantsSchema) {\r\n structureId = addEntry('table', table.name, { tableKind: table.kind });\r\n tableDumpId.set(key, structureId);\r\n if (table.kind === 'shadow' && table.ownerVirtualTable !== undefined) {\r\n addDependency(\r\n structureId,\r\n tableDumpId.get(foldSqliteName(table.ownerVirtualTable)),\r\n 'preference',\r\n );\r\n }\r\n }\r\n if (wantsData && !isTableDataExcluded(table.name, selection)) {\r\n const dataId = addEntry('tableData', table.name, {\r\n tableKind: table.kind,\r\n parentName: table.name,\r\n });\r\n tableDataDumpId.set(key, dataId);\r\n addDependency(dataId, structureId, 'hard');\r\n }\r\n }\r\n\r\n // Foreign keys are recorded as *preferences* only: the dump's\r\n // `PRAGMA foreign_keys=OFF` makes any table order restorable, which is\r\n // precisely what makes circular foreign keys work.\r\n for (const foreignKey of database.foreignKeys) {\r\n const from = tableDumpId.get(foldSqliteName(foreignKey.tableName));\r\n const to = tableDumpId.get(foldSqliteName(foreignKey.referencedTableName));\r\n if (from && to) {\r\n addDependency(from, to, 'preference');\r\n }\r\n }\r\n\r\n // Pass 2 — indexes, triggers and views, in creation order.\r\n if (wantsSchema) {\r\n const selectedViewNames = new Set(\r\n includeViews\r\n ? database.views\r\n .filter(view => isViewSelected(view.name, selection))\r\n .map(view => foldSqliteName(view.name))\r\n : [],\r\n );\r\n const viewDumpId = new Map<string, string>();\r\n\r\n type SchemaObject =\r\n | { kind: 'index'; schemaRowid: number; index: SqliteDatabase['indexes'][number] }\r\n | { kind: 'trigger'; schemaRowid: number; trigger: SqliteDatabase['triggers'][number] }\r\n | { kind: 'view'; schemaRowid: number; view: SqliteDatabase['views'][number] };\r\n\r\n const objects: SchemaObject[] = [\r\n ...database.indexes.map(index => ({\r\n kind: 'index' as const,\r\n schemaRowid: index.schemaRowid,\r\n index,\r\n })),\r\n ...database.triggers.map(trigger => ({\r\n kind: 'trigger' as const,\r\n schemaRowid: trigger.schemaRowid,\r\n trigger,\r\n })),\r\n ...database.views.map(view => ({\r\n kind: 'view' as const,\r\n schemaRowid: view.schemaRowid,\r\n view,\r\n })),\r\n ].sort((a, b) => a.schemaRowid - b.schemaRowid);\r\n\r\n for (const object of objects) {\r\n switch (object.kind) {\r\n case 'index': {\r\n const { index } = object;\r\n // An automatic index (UNIQUE / PRIMARY KEY) has no DDL of its own;\r\n // the table's CREATE TABLE recreates it.\r\n if (index.sql === null || !includeIndexes || !isIndexSelected(index.name, selection)) {\r\n continue;\r\n }\r\n const tableId = tableDumpId.get(foldSqliteName(index.tableName));\r\n if (!tableId) {\r\n continue;\r\n }\r\n const dumpId = addEntry('index', index.name, { parentName: index.tableName });\r\n addDependency(dumpId, tableId, 'hard');\r\n // Building an index after the rows are loaded is faster, but not required.\r\n addDependency(dumpId, tableDataDumpId.get(foldSqliteName(index.tableName)), 'preference');\r\n break;\r\n }\r\n case 'trigger': {\r\n const { trigger } = object;\r\n if (!includeTriggers || !isTriggerSelected(trigger.name, selection)) {\r\n continue;\r\n }\r\n const parentKey = foldSqliteName(trigger.tableName);\r\n const parentId = tableDumpId.get(parentKey) ?? viewDumpId.get(parentKey);\r\n if (!parentId) {\r\n // Dropped rather than orphaned: a trigger cannot be created on a\r\n // table the dump will not create.\r\n diagnostics.push({\r\n severity: 'info',\r\n code: 'trigger-table-not-selected',\r\n message: `Trigger \"${trigger.name}\" is not dumped because its table \"${trigger.tableName}\" is not part of the dump`,\r\n objectReference: {\r\n kind: 'trigger',\r\n schemaName,\r\n name: trigger.name,\r\n parentName: trigger.tableName,\r\n },\r\n });\r\n continue;\r\n }\r\n const dumpId = addEntry('trigger', trigger.name, { parentName: trigger.tableName });\r\n addDependency(dumpId, parentId, 'hard');\r\n // Hard, not cosmetic: a trigger created before its table's rows are\r\n // loaded fires once per inserted row, fabricating side effects the\r\n // source database never had.\r\n addDependency(dumpId, tableDataDumpId.get(parentKey), 'hard');\r\n break;\r\n }\r\n case 'view': {\r\n const { view } = object;\r\n const key = foldSqliteName(view.name);\r\n if (!selectedViewNames.has(key)) {\r\n continue;\r\n }\r\n const dumpId = addEntry('view', view.name);\r\n viewDumpId.set(key, dumpId);\r\n // SQLite resolves a view's body when the view is used, not when it\r\n // is created, so tables and other views are only a preference.\r\n for (const tableId of tableDumpId.values()) {\r\n addDependency(dumpId, tableId, 'preference');\r\n }\r\n break;\r\n }\r\n }\r\n }\r\n }\r\n\r\n const { cycles, unsatisfiedDependencies } = validateOrder(entries);\r\n const valid =\r\n cycles.length === 0 &&\r\n unsatisfiedDependencies.length === 0 &&\r\n !diagnostics.some(diagnostic => diagnostic.severity === 'error');\r\n\r\n for (const cycle of cycles) {\r\n diagnostics.push({\r\n severity: 'error',\r\n code: 'archive-dependency-cycle',\r\n message: `Hard dependency cycle between archive entries: ${cycle.memberDumpIds.join(', ')}`,\r\n });\r\n }\r\n for (const violation of unsatisfiedDependencies) {\r\n diagnostics.push({\r\n severity: 'error',\r\n code: 'archive-order-violation',\r\n message: `Archive entry ${violation.fromDumpId} is emitted before its hard dependency ${violation.toDumpId}`,\r\n });\r\n }\r\n\r\n return {\r\n valid,\r\n entries: entries.map((entry, index) =>\r\n toArchiveEntry(entry, schemaName, valid ? index : undefined),\r\n ),\r\n diagnostics,\r\n cycles,\r\n unsatisfiedDependencies,\r\n };\r\n}\r\n\r\nfunction toArchiveEntry(\r\n entry: MutableEntry,\r\n schemaName: string,\r\n sequenceNumber: number | undefined,\r\n): ArchiveEntry {\r\n return {\r\n dumpId: entry.dumpId,\r\n identity: entry.identity,\r\n objectType: entry.objectType,\r\n section: assignDumpSection(entry.objectType),\r\n schemaName,\r\n name: entry.name,\r\n ...(entry.parentName === undefined ? {} : { parentName: entry.parentName }),\r\n ...(entry.tableKind === undefined ? {} : { tableKind: entry.tableKind }),\r\n ...(entry.systemRowFilter === undefined ? {} : { systemRowFilter: entry.systemRowFilter }),\r\n dependsOn: entry.dependsOn,\r\n ...(sequenceNumber === undefined ? {} : { sequenceNumber }),\r\n };\r\n}\r\n\r\n/**\r\n * Verifies the fixed emission order against the recorded hard dependencies,\r\n * and separately reports any hard cycle.\r\n *\r\n * This is a *check*, not a sort. The order is dictated by native\r\n * compatibility, so if a hard dependency points backwards the right answer\r\n * is to surface it rather than to reorder and hide the cause.\r\n */\r\nfunction validateOrder(ordered: readonly MutableEntry[]): {\r\n cycles: ArchiveCycle[];\r\n unsatisfiedDependencies: UnsatisfiedDependency[];\r\n} {\r\n const positionByDumpId = new Map(ordered.map((entry, index) => [entry.dumpId, index]));\r\n const unsatisfiedDependencies: UnsatisfiedDependency[] = [];\r\n\r\n for (const entry of ordered) {\r\n const fromPosition = positionByDumpId.get(entry.dumpId) as number;\r\n for (const dependency of entry.dependsOn) {\r\n if (dependency.strength !== 'hard') {\r\n continue;\r\n }\r\n const toPosition = positionByDumpId.get(dependency.targetDumpId);\r\n if (toPosition !== undefined && toPosition > fromPosition) {\r\n unsatisfiedDependencies.push({\r\n fromDumpId: entry.dumpId,\r\n toDumpId: dependency.targetDumpId,\r\n });\r\n }\r\n }\r\n }\r\n\r\n return { cycles: findHardCycles(ordered), unsatisfiedDependencies };\r\n}\r\n\r\nfunction byCodepoint(a: string, b: string): number {\r\n return a < b ? -1 : a > b ? 1 : 0;\r\n}\r\n\r\n/** Tarjan's strongly-connected components over hard edges only; any component of size > 1 is a cycle. */\r\nfunction findHardCycles(entries: readonly MutableEntry[]): ArchiveCycle[] {\r\n const indexByDumpId = new Map<string, number>();\r\n const lowLink = new Map<string, number>();\r\n const onStack = new Set<string>();\r\n const stack: string[] = [];\r\n const byDumpId = new Map(entries.map(entry => [entry.dumpId, entry]));\r\n const cycles: ArchiveCycle[] = [];\r\n let nextIndex = 0;\r\n\r\n const strongConnect = (dumpId: string): void => {\r\n indexByDumpId.set(dumpId, nextIndex);\r\n lowLink.set(dumpId, nextIndex);\r\n nextIndex++;\r\n stack.push(dumpId);\r\n onStack.add(dumpId);\r\n\r\n for (const dependency of byDumpId.get(dumpId)?.dependsOn ?? []) {\r\n if (dependency.strength !== 'hard' || !byDumpId.has(dependency.targetDumpId)) {\r\n continue;\r\n }\r\n const target = dependency.targetDumpId;\r\n if (!indexByDumpId.has(target)) {\r\n strongConnect(target);\r\n lowLink.set(dumpId, Math.min(lowLink.get(dumpId) as number, lowLink.get(target) as number));\r\n } else if (onStack.has(target)) {\r\n lowLink.set(\r\n dumpId,\r\n Math.min(lowLink.get(dumpId) as number, indexByDumpId.get(target) as number),\r\n );\r\n }\r\n }\r\n\r\n if (lowLink.get(dumpId) === indexByDumpId.get(dumpId)) {\r\n const component: string[] = [];\r\n for (;;) {\r\n const member = stack.pop() as string;\r\n onStack.delete(member);\r\n component.push(member);\r\n if (member === dumpId) {\r\n break;\r\n }\r\n }\r\n if (component.length > 1) {\r\n cycles.push({ memberDumpIds: component.sort(byCodepoint) });\r\n }\r\n }\r\n };\r\n\r\n for (const entry of entries) {\r\n if (!indexByDumpId.has(entry.dumpId)) {\r\n strongConnect(entry.dumpId);\r\n }\r\n }\r\n return cycles;\r\n}\r\n","/** Base class for every error this package throws intentionally. */\r\nexport class SqliteDumperError extends Error {\r\n readonly code: string;\r\n\r\n constructor(code: string, message: string, options?: { cause?: unknown }) {\r\n super(message, options);\r\n this.name = 'SqliteDumperError';\r\n this.code = code;\r\n }\r\n}\r\n\r\n/** Thrown when an operation stops because its `AbortSignal` was triggered. */\r\nexport class OperationCancelledError extends SqliteDumperError {\r\n constructor(message = 'The operation was cancelled') {\r\n super('operation-cancelled', message);\r\n this.name = 'OperationCancelledError';\r\n }\r\n}\r\n\r\nexport function throwIfAborted(signal: AbortSignal | undefined): void {\r\n if (signal?.aborted) {\r\n throw new OperationCancelledError();\r\n }\r\n}\r\n\r\n/**\r\n * True for both cancellation shapes this package can observe: its own\r\n * {@link OperationCancelledError} and the `DOMException` an `AbortSignal`\r\n * (or a Node stream aborted through one) raises.\r\n */\r\nexport function isAbortError(error: unknown): boolean {\r\n return (\r\n (error instanceof DOMException && error.name === 'AbortError') ||\r\n (error instanceof Error && error.name === 'OperationCancelledError')\r\n );\r\n}\r\n","/**\r\n * Small, deliberately conservative helpers for reading facts out of the\r\n * verbatim DDL SQLite keeps in `sqlite_schema.sql`, for the few facts no\r\n * catalog pragma reports on every supported version.\r\n */\r\n\r\n/**\r\n * Blanks out string literals, quoted identifiers and comments (keeping\r\n * their length), so a keyword search cannot match text *inside* them —\r\n * `DEFAULT 'AUTOINCREMENT'` is not an autoincrement column.\r\n */\r\nexport function maskSqlLiterals(sql: string): string {\r\n let output = '';\r\n let index = 0;\r\n while (index < sql.length) {\r\n const character = sql[index] as string;\r\n if (character === \"'\" || character === '\"' || character === '`' || character === '[') {\r\n const close = character === '[' ? ']' : character;\r\n let end = sql.indexOf(close, index + 1);\r\n end = end === -1 ? sql.length : end + 1;\r\n output += ' '.repeat(end - index);\r\n index = end;\r\n continue;\r\n }\r\n if (character === '-' && sql[index + 1] === '-') {\r\n let end = sql.indexOf('\\n', index);\r\n end = end === -1 ? sql.length : end;\r\n output += ' '.repeat(end - index);\r\n index = end;\r\n continue;\r\n }\r\n if (character === '/' && sql[index + 1] === '*') {\r\n let end = sql.indexOf('*/', index + 2);\r\n end = end === -1 ? sql.length : end + 2;\r\n output += ' '.repeat(end - index);\r\n index = end;\r\n continue;\r\n }\r\n output += character;\r\n index++;\r\n }\r\n return output;\r\n}\r\n\r\n/** `true` when the `CREATE TABLE` text declares an `AUTOINCREMENT` column. */\r\nexport function declaresAutoincrement(sql: string): boolean {\r\n return /\\bAUTOINCREMENT\\b/i.test(maskSqlLiterals(sql));\r\n}\r\n\r\n/**\r\n * Table options after the closing parenthesis of a `CREATE TABLE`\r\n * (`WITHOUT ROWID`, `STRICT`, in any combination). Used only when the\r\n * library is too old for `PRAGMA table_list`, which reports both directly.\r\n */\r\nexport function parseTableOptions(sql: string): { withoutRowid: boolean; strict: boolean } {\r\n const masked = maskSqlLiterals(sql);\r\n const close = masked.lastIndexOf(')');\r\n const tail = close === -1 ? '' : masked.slice(close + 1);\r\n return {\r\n withoutRowid: /\\bWITHOUT\\s+ROWID\\b/i.test(tail),\r\n strict: /\\bSTRICT\\b/i.test(tail),\r\n };\r\n}\r\n\r\n/** The module named in `CREATE VIRTUAL TABLE name USING module(...)`. */\r\nexport function parseVirtualTableModule(sql: string): string | undefined {\r\n const masked = maskSqlLiterals(sql);\r\n const match = /\\bUSING\\s+([A-Za-z0-9_$\\u0080-\\uffff]+)/i.exec(masked);\r\n return match\r\n ? sql.slice(match.index, match.index + match[0].length).replace(/^USING\\s+/i, '')\r\n : undefined;\r\n}\r\n","import { toNumber, toText } from '../connection/acquire.js';\r\nimport type { SqliteConnection, SqliteRow } from '../connection/types.js';\r\nimport type {\r\n SqliteColumn,\r\n SqliteColumnHidden,\r\n SqliteDatabase,\r\n SqliteForeignKey,\r\n SqliteIndex,\r\n SqliteIndexColumn,\r\n SqliteSequence,\r\n SqliteTable,\r\n SqliteTableKind,\r\n SqliteTrigger,\r\n SqliteView,\r\n} from '../model/database.js';\r\nimport type { SqliteDiagnostic } from '../model/diagnostics.js';\r\nimport { quoteIdentifier, toAsciiLowerCase, toAsciiUpperCase } from '../security/identifiers.js';\r\nimport { quoteStringLiteral } from '../security/literals.js';\r\nimport { isAbortError, SqliteDumperError, throwIfAborted } from '../utils/errors.js';\r\nimport { detectSqliteCapabilities } from '../version/capabilities.js';\r\nimport { detectSqliteVersion } from '../version/detect.js';\r\nimport type { SqliteCapabilities, SqliteVersion } from '../version/types.js';\r\nimport { declaresAutoincrement, parseTableOptions, parseVirtualTableModule } from './sqlText.js';\r\n\r\nexport interface IntrospectSqliteOptions {\r\n /**\r\n * Schema to introspect: `main` (default), `temp`, or the name of an\r\n * attached database.\r\n */\r\n readonly schemaName?: string;\r\n}\r\n\r\nexport interface SqliteIntrospectionResult {\r\n readonly database: SqliteDatabase;\r\n readonly version: SqliteVersion;\r\n readonly capabilities: SqliteCapabilities;\r\n readonly diagnostics: readonly SqliteDiagnostic[];\r\n}\r\n\r\ninterface SchemaRow {\r\n readonly schemaRowid: number;\r\n readonly type: string;\r\n readonly name: string;\r\n readonly tableName: string;\r\n readonly sql: string | null;\r\n}\r\n\r\n/**\r\n * Reads the complete schema of one SQLite database into a normalized\r\n * {@link SqliteDatabase}.\r\n *\r\n * Every object comes from `sqlite_schema` (read through its historical name\r\n * `sqlite_master`, which every release accepts), in rowid order — the order\r\n * the native `.dump` uses. Column, index and foreign-key detail comes from\r\n * the table-valued pragma functions where the library has them, falling back\r\n * to the plain `PRAGMA` statements otherwise.\r\n *\r\n * Runs entirely on the one handle it is given, in sequence, and never writes.\r\n */\r\nexport async function introspectSqlite(\r\n connection: SqliteConnection,\r\n options?: IntrospectSqliteOptions,\r\n signal?: AbortSignal,\r\n): Promise<SqliteIntrospectionResult> {\r\n const schemaName = options?.schemaName ?? 'main';\r\n const version = await detectSqliteVersion(connection, signal);\r\n const capabilities = detectSqliteCapabilities(version);\r\n const diagnostics: SqliteDiagnostic[] = [];\r\n const catalog = new CatalogReader(connection, schemaName, capabilities, signal);\r\n\r\n const schemaRows = await catalog.schemaRows();\r\n if (schemaRows === null) {\r\n throw new SqliteDumperError(\r\n 'schema-not-found',\r\n `No database named ${JSON.stringify(schemaName)} is attached to this connection`,\r\n );\r\n }\r\n\r\n const tableList = await catalog.tableList();\r\n const virtualTableNames = schemaRows\r\n .filter(row => row.type === 'table' && isVirtualTableSql(row.sql))\r\n .map(row => row.name);\r\n\r\n const tables: SqliteTable[] = [];\r\n const indexes: SqliteIndex[] = [];\r\n const foreignKeys: SqliteForeignKey[] = [];\r\n const indexRowsByName = new Map(\r\n schemaRows.filter(row => row.type === 'index').map(row => [toAsciiLowerCase(row.name), row]),\r\n );\r\n\r\n for (const row of schemaRows) {\r\n throwIfAborted(signal);\r\n if (row.type !== 'table' || row.sql === null) {\r\n continue;\r\n }\r\n const listed = tableList?.get(toAsciiLowerCase(row.name));\r\n const kind = classifyTable(row, listed?.type, virtualTableNames);\r\n\r\n let columns: SqliteColumn[] = [];\r\n try {\r\n columns = await catalog.columns(row.name);\r\n } catch (error) {\r\n if (isAbortError(error)) throw error;\r\n diagnostics.push({\r\n severity: kind === 'virtual' ? 'warning' : 'error',\r\n code: kind === 'virtual' ? 'virtual-table-module-unavailable' : 'table-columns-unreadable',\r\n message:\r\n kind === 'virtual'\r\n ? `The columns of virtual table \"${row.name}\" cannot be read, most likely because its module is not available in this SQLite build (${errorMessage(error)}). Its definition and its shadow tables are still dumped, which is all a restore needs.`\r\n : `The columns of table \"${row.name}\" cannot be read: ${errorMessage(error)}`,\r\n objectReference: {\r\n kind: kind === 'virtual' ? 'virtualTable' : 'table',\r\n schemaName,\r\n name: row.name,\r\n },\r\n });\r\n }\r\n\r\n const parsedOptions = parseTableOptions(row.sql);\r\n const withoutRowid = listed\r\n ? listed.withoutRowid\r\n : kind === 'table' || kind === 'shadow'\r\n ? parsedOptions.withoutRowid\r\n : false;\r\n const strict = listed ? listed.strict : parsedOptions.strict;\r\n\r\n let tableIndexes: SqliteIndex[] = [];\r\n let tableForeignKeys: SqliteForeignKey[] = [];\r\n if (kind !== 'virtual') {\r\n tableIndexes = await catalog.indexes(row.name, indexRowsByName);\r\n tableForeignKeys = await catalog.foreignKeys(row.name);\r\n }\r\n indexes.push(...tableIndexes);\r\n foreignKeys.push(...tableForeignKeys);\r\n\r\n const virtualModule = kind === 'virtual' ? parseVirtualTableModule(row.sql) : undefined;\r\n const ownerVirtualTable =\r\n kind === 'shadow' ? findOwner(row.name, virtualTableNames) : undefined;\r\n\r\n tables.push({\r\n name: row.name,\r\n kind,\r\n schemaRowid: row.schemaRowid,\r\n sql: row.sql,\r\n withoutRowid,\r\n strict,\r\n hasAutoincrement: kind === 'table' && declaresAutoincrement(row.sql),\r\n ...(virtualModule === undefined ? {} : { virtualModule }),\r\n ...(ownerVirtualTable === undefined ? {} : { ownerVirtualTable }),\r\n rowidAliasColumn:\r\n kind === 'virtual' || withoutRowid ? null : findRowidAlias(columns, tableIndexes),\r\n columns,\r\n });\r\n }\r\n\r\n // Indexes are attached to their table through the pragmas above; any\r\n // `CREATE INDEX` row whose table could not be read is still carried, so the\r\n // dump does not silently lose it.\r\n const seenIndexes = new Set(indexes.map(index => toAsciiLowerCase(index.name)));\r\n for (const row of schemaRows) {\r\n if (row.type === 'index' && row.sql !== null && !seenIndexes.has(toAsciiLowerCase(row.name))) {\r\n indexes.push({\r\n name: row.name,\r\n tableName: row.tableName,\r\n schemaRowid: row.schemaRowid,\r\n sql: row.sql,\r\n isUnique: /^CREATE\\s+UNIQUE\\b/i.test(row.sql),\r\n origin: 'c',\r\n isPartial: false,\r\n columns: [],\r\n });\r\n }\r\n }\r\n indexes.sort((a, b) => a.schemaRowid - b.schemaRowid);\r\n\r\n const views: SqliteView[] = schemaRows\r\n .filter(row => row.type === 'view' && row.sql !== null)\r\n .map(row => ({ name: row.name, schemaRowid: row.schemaRowid, sql: row.sql as string }));\r\n const triggers: SqliteTrigger[] = schemaRows\r\n .filter(row => row.type === 'trigger' && row.sql !== null)\r\n .map(row => ({\r\n name: row.name,\r\n tableName: row.tableName,\r\n schemaRowid: row.schemaRowid,\r\n sql: row.sql as string,\r\n }));\r\n\r\n const sequences = tables.some(table => table.name === 'sqlite_sequence')\r\n ? await catalog.sequences()\r\n : [];\r\n\r\n const settings = await catalog.settings();\r\n\r\n return {\r\n database: {\r\n schemaName,\r\n ...settings,\r\n tables,\r\n indexes,\r\n views,\r\n triggers,\r\n foreignKeys,\r\n sequences,\r\n },\r\n version,\r\n capabilities,\r\n diagnostics,\r\n };\r\n}\r\n\r\nfunction errorMessage(error: unknown): string {\r\n return error instanceof Error ? error.message : String(error);\r\n}\r\n\r\nfunction isVirtualTableSql(sql: string | null): boolean {\r\n // The native shell tests exactly this prefix (`strncmp`, case-sensitive);\r\n // SQLite normalizes the start of every stored CREATE statement, so it is\r\n // reliable.\r\n return sql !== null && sql.startsWith('CREATE VIRTUAL TABLE');\r\n}\r\n\r\nfunction classifyTable(\r\n row: SchemaRow,\r\n listedType: string | undefined,\r\n virtualTableNames: readonly string[],\r\n): SqliteTableKind {\r\n if (row.name.startsWith('sqlite_')) {\r\n return 'system';\r\n }\r\n if (isVirtualTableSql(row.sql)) {\r\n return 'virtual';\r\n }\r\n if (listedType !== undefined) {\r\n return listedType === 'shadow' ? 'shadow' : 'table';\r\n }\r\n // Without `PRAGMA table_list`, recognize shadow tables the way the native\r\n // `.dump` does when it expands a table pattern: by the `<vtab>_` prefix.\r\n return findOwner(row.name, virtualTableNames) === undefined ? 'table' : 'shadow';\r\n}\r\n\r\n/** The virtual table whose `<name>_` prefix `tableName` carries — the longest, if several do. */\r\nfunction findOwner(tableName: string, virtualTableNames: readonly string[]): string | undefined {\r\n const lower = toAsciiLowerCase(tableName);\r\n let owner: string | undefined;\r\n for (const name of virtualTableNames) {\r\n const prefix = `${toAsciiLowerCase(name)}_`;\r\n if (lower.startsWith(prefix) && lower.length > prefix.length) {\r\n if (owner === undefined || name.length > owner.length) {\r\n owner = name;\r\n }\r\n }\r\n }\r\n return owner;\r\n}\r\n\r\n/**\r\n * The column that *is* the rowid: a lone `INTEGER PRIMARY KEY`. Declared\r\n * exactly `INTEGER` (not `INT`, not `BIGINT`), and not `PRIMARY KEY DESC` —\r\n * the one spelling SQLite implements as a separate unique index, which shows\r\n * up as an index with origin `pk`.\r\n */\r\nfunction findRowidAlias(\r\n columns: readonly SqliteColumn[],\r\n indexes: readonly SqliteIndex[],\r\n): string | null {\r\n const primaryKey = columns.filter(column => column.primaryKeyPosition > 0);\r\n if (primaryKey.length !== 1) {\r\n return null;\r\n }\r\n const column = primaryKey[0] as SqliteColumn;\r\n if (toAsciiUpperCase(column.declaredType) !== 'INTEGER') {\r\n return null;\r\n }\r\n if (indexes.some(index => index.origin === 'pk')) {\r\n return null;\r\n }\r\n return column.name;\r\n}\r\n\r\ninterface ListedTable {\r\n readonly type: string;\r\n readonly withoutRowid: boolean;\r\n readonly strict: boolean;\r\n}\r\n\r\n/** Catalog queries for one schema, using the pragma functions when available. */\r\nclass CatalogReader {\r\n private readonly qualifier: string;\r\n\r\n constructor(\r\n private readonly connection: SqliteConnection,\r\n private readonly schemaName: string,\r\n private readonly capabilities: SqliteCapabilities,\r\n private readonly signal?: AbortSignal,\r\n ) {\r\n this.qualifier = quoteIdentifier(schemaName);\r\n }\r\n\r\n private async rows(\r\n sql: string,\r\n parameters?: readonly (string | number)[],\r\n ): Promise<readonly SqliteRow[]> {\r\n const result = await this.connection.query<SqliteRow>(\r\n parameters === undefined ? { sql } : { sql, parameters },\r\n this.signal,\r\n );\r\n return result.rows;\r\n }\r\n\r\n /** Runs `PRAGMA schema.name(argument)`, as a table-valued function when the library has them. */\r\n private async pragma(\r\n name: string,\r\n argument: string,\r\n columns: string,\r\n ): Promise<readonly SqliteRow[]> {\r\n if (this.capabilities.supportsPragmaFunctions) {\r\n return this.rows(`SELECT ${columns} FROM pragma_${name}(?, ?)`, [argument, this.schemaName]);\r\n }\r\n return this.rows(`PRAGMA ${this.qualifier}.${name}(${quoteStringLiteral(argument)})`);\r\n }\r\n\r\n async schemaRows(): Promise<SchemaRow[] | null> {\r\n const databases = await this.rows('PRAGMA database_list');\r\n const known = databases.some(\r\n row => toAsciiLowerCase(toText(row.name) ?? '') === toAsciiLowerCase(this.schemaName),\r\n );\r\n if (!known) {\r\n return null;\r\n }\r\n const master =\r\n toAsciiLowerCase(this.schemaName) === 'temp' ? 'sqlite_temp_master' : 'sqlite_master';\r\n const rows = await this.rows(\r\n `SELECT rowid AS schemaRowid, type, name, tbl_name AS tableName, sql FROM ${this.qualifier}.${master} ORDER BY rowid`,\r\n );\r\n return rows.map(row => ({\r\n schemaRowid: toNumber(row.schemaRowid),\r\n type: toText(row.type) ?? '',\r\n name: toText(row.name) ?? '',\r\n tableName: toText(row.tableName) ?? '',\r\n sql: toText(row.sql),\r\n }));\r\n }\r\n\r\n async tableList(): Promise<Map<string, ListedTable> | undefined> {\r\n if (!this.capabilities.supportsTableList) {\r\n return undefined;\r\n }\r\n try {\r\n const rows = await this.rows(\r\n 'SELECT name, type, wr, strict FROM pragma_table_list WHERE schema = ?',\r\n [this.schemaName],\r\n );\r\n return new Map(\r\n rows.map(row => [\r\n toAsciiLowerCase(toText(row.name) ?? ''),\r\n {\r\n type: toText(row.type) ?? 'table',\r\n withoutRowid: toNumber(row.wr) !== 0,\r\n strict: toNumber(row.strict) !== 0,\r\n },\r\n ]),\r\n );\r\n } catch (error) {\r\n if (isAbortError(error)) throw error;\r\n // `PRAGMA table_list` prepares every view to count its columns, so one\r\n // broken view makes it fail as a whole. The DDL-parsing fallback\r\n // below does not depend on it.\r\n return undefined;\r\n }\r\n }\r\n\r\n async columns(tableName: string): Promise<SqliteColumn[]> {\r\n const withHidden = this.capabilities.supportsTableXinfo;\r\n const rows = await this.pragma(\r\n withHidden ? 'table_xinfo' : 'table_info',\r\n tableName,\r\n `cid, name, type, \"notnull\" AS isNotNull, dflt_value AS defaultValue, pk${withHidden ? ', hidden' : ''}`,\r\n );\r\n return rows.map(row => {\r\n const hidden = (withHidden ? toNumber(row.hidden) : 0) as SqliteColumnHidden;\r\n return {\r\n cid: toNumber(row.cid),\r\n name: toText(row.name) ?? '',\r\n declaredType: toText(row.type) ?? '',\r\n notNull: toNumber(row.isNotNull ?? row.notnull) !== 0,\r\n defaultValue: toText(row.defaultValue ?? row.dflt_value),\r\n primaryKeyPosition: toNumber(row.pk),\r\n hidden,\r\n generated: hidden === 2 ? 'virtual' : hidden === 3 ? 'stored' : 'none',\r\n };\r\n });\r\n }\r\n\r\n async indexes(\r\n tableName: string,\r\n schemaRows: ReadonlyMap<string, SchemaRow>,\r\n ): Promise<SqliteIndex[]> {\r\n const list = await this.pragma(\r\n 'index_list',\r\n tableName,\r\n 'seq, name, \"unique\" AS isUnique, origin, partial',\r\n );\r\n const result: SqliteIndex[] = [];\r\n for (const row of list) {\r\n const name = toText(row.name) ?? '';\r\n const schemaRow = schemaRows.get(toAsciiLowerCase(name));\r\n const origin = (toText(row.origin) ?? 'c') as SqliteIndex['origin'];\r\n let columns: SqliteIndexColumn[] = [];\r\n try {\r\n const keyRows = await this.pragma(\r\n 'index_xinfo',\r\n name,\r\n 'seqno, cid, name, \"desc\" AS isDesc, coll, \"key\" AS isKey',\r\n );\r\n columns = keyRows\r\n .filter(keyRow => toNumber(keyRow.isKey ?? keyRow.key) !== 0)\r\n .map(keyRow => ({\r\n name: toText(keyRow.name),\r\n cid: toNumber(keyRow.cid),\r\n descending: toNumber(keyRow.isDesc ?? keyRow.desc) !== 0,\r\n collation: toText(keyRow.coll),\r\n }));\r\n } catch (error) {\r\n if (isAbortError(error)) throw error;\r\n }\r\n result.push({\r\n name,\r\n tableName,\r\n // A WITHOUT ROWID table's primary-key index is the table itself and\r\n // has no sqlite_schema row; it sorts with its table.\r\n schemaRowid: schemaRow?.schemaRowid ?? 0,\r\n sql: schemaRow?.sql ?? null,\r\n isUnique: toNumber(row.isUnique ?? row.unique) !== 0,\r\n origin: origin === 'u' || origin === 'pk' ? origin : 'c',\r\n isPartial: toNumber(row.partial) !== 0,\r\n columns,\r\n });\r\n }\r\n return result;\r\n }\r\n\r\n async foreignKeys(tableName: string): Promise<SqliteForeignKey[]> {\r\n const rows = await this.pragma(\r\n 'foreign_key_list',\r\n tableName,\r\n 'id, seq, \"table\" AS referencedTable, \"from\" AS fromColumn, \"to\" AS toColumn, on_update AS onUpdate, on_delete AS onDelete, \"match\" AS matchMode',\r\n );\r\n const byId = new Map<\r\n number,\r\n SqliteForeignKey & { columns: { from: string; to: string | null }[] }\r\n >();\r\n const ordered = [...rows].sort(\r\n (a, b) => toNumber(a.id) - toNumber(b.id) || toNumber(a.seq) - toNumber(b.seq),\r\n );\r\n for (const row of ordered) {\r\n const id = toNumber(row.id);\r\n let foreignKey = byId.get(id);\r\n if (!foreignKey) {\r\n foreignKey = {\r\n tableName,\r\n id,\r\n referencedTableName: toText(row.referencedTable ?? row.table) ?? '',\r\n columns: [],\r\n onUpdate: toText(row.onUpdate ?? row.on_update) ?? 'NO ACTION',\r\n onDelete: toText(row.onDelete ?? row.on_delete) ?? 'NO ACTION',\r\n match: toText(row.matchMode ?? row.match) ?? 'NONE',\r\n };\r\n byId.set(id, foreignKey);\r\n }\r\n foreignKey.columns.push({\r\n from: toText(row.fromColumn ?? row.from) ?? '',\r\n to: toText(row.toColumn ?? row.to),\r\n });\r\n }\r\n return [...byId.values()];\r\n }\r\n\r\n async sequences(): Promise<SqliteSequence[]> {\r\n const rows = await this.rows(\r\n `SELECT name, CAST(seq AS TEXT) AS value FROM ${this.qualifier}.sqlite_sequence`,\r\n );\r\n return rows.map(row => ({\r\n tableName: toText(row.name) ?? '',\r\n value: toText(row.value) ?? '0',\r\n }));\r\n }\r\n\r\n async settings(): Promise<\r\n Pick<SqliteDatabase, 'encoding' | 'userVersion' | 'applicationId' | 'pageSize'>\r\n > {\r\n const read = async (pragma: string): Promise<unknown> => {\r\n try {\r\n const rows = await this.rows(`PRAGMA ${this.qualifier}.${pragma}`);\r\n const first = rows[0];\r\n return first === undefined ? undefined : Object.values(first)[0];\r\n } catch (error) {\r\n if (isAbortError(error)) throw error;\r\n return undefined;\r\n }\r\n };\r\n // `encoding` is a property of the main database; an attached database\r\n // always shares it.\r\n let encoding: unknown;\r\n try {\r\n const rows = await this.rows('PRAGMA encoding');\r\n encoding = rows[0] === undefined ? undefined : Object.values(rows[0])[0];\r\n } catch (error) {\r\n if (isAbortError(error)) throw error;\r\n }\r\n const pageSize = await read('page_size');\r\n return {\r\n encoding: toText(encoding) ?? 'UTF-8',\r\n userVersion: toNumber(await read('user_version')),\r\n applicationId: toNumber(await read('application_id')),\r\n ...(pageSize === undefined ? {} : { pageSize: toNumber(pageSize) }),\r\n };\r\n }\r\n}\r\n","import type { ArchiveEntry, DumpArchiveInspection, DumpMode } from '../archive/types.js';\r\nimport type { SqliteDatabase } from '../model/database.js';\r\nimport type { SqliteDiagnostic } from '../model/diagnostics.js';\r\nimport type { DumpProgressCallback } from '../utils/progress.js';\r\nimport type { SqliteVersion } from '../version/types.js';\r\nimport type { DumpWriter } from '../writer/types.js';\r\n\r\nexport interface PlainSqlRenderOptions {\r\n /**\r\n * Wrap the dump in `PRAGMA foreign_keys=OFF;` / `BEGIN TRANSACTION;` …\r\n * `COMMIT;`, exactly as the native `.dump` does. Defaults to `true`, and\r\n * turning it off produces a `session-guards-disabled` warning.\r\n *\r\n * These are not decoration. `foreign_keys=OFF` is what lets tables be\r\n * created and filled in creation order whatever references what —\r\n * circular foreign keys included — and the transaction is what makes the\r\n * restore both atomic and fast: without it every `INSERT` is its own\r\n * transaction, and its own disk sync. A data-only dump never carries them,\r\n * matching `.dump --data-only`.\r\n */\r\n readonly includeSessionGuards?: boolean;\r\n /**\r\n * Emit the `/* WARNING: Script requires that SQLITE_DBCONFIG_DEFENSIVE be\r\n * disabled *\\/` line the native `.dump` writes first when the dump\r\n * contains virtual tables. Defaults to `true`.\r\n */\r\n readonly includeHeaderComments?: boolean;\r\n /**\r\n * Emit `DROP ... IF EXISTS` before each object's `CREATE`, so the dump can\r\n * be restored over an existing copy. Defaults to `false`: the native\r\n * `.dump` has no such option, and a dump restored into a fresh database\r\n * does not need it.\r\n */\r\n readonly addDropStatements?: boolean;\r\n /**\r\n * Emit `PRAGMA user_version=…;` and `PRAGMA application_id=…;` before the\r\n * final `COMMIT`, when either is non-zero. Defaults to `false`, matching\r\n * the native `.dump` — which does not carry them, so an application that\r\n * versions its schema through `user_version` loses that version in a\r\n * native round trip. When they are not dumped, a non-zero value is\r\n * reported as a `user-version-not-dumped` / `application-id-not-dumped`\r\n * warning.\r\n */\r\n readonly includeDatabaseSettings?: boolean;\r\n /**\r\n * Write `sqlite_master` instead of `sqlite_schema` in the two places the\r\n * dump names the schema table (`ANALYZE sqlite_schema;` and the virtual\r\n * table `INSERT INTO sqlite_schema ...`). Defaults to `false`. The\r\n * `sqlite_schema` spelling needs SQLite 3.33.0 or later on the restoring\r\n * side; set this for a dump that must restore on something older.\r\n */\r\n readonly legacySchemaTableName?: boolean;\r\n /**\r\n * How to react to an archive entry that cannot be rendered. `'error'`\r\n * (default) fails the render; `'warn-omit'` skips the entry and records a\r\n * warning diagnostic.\r\n */\r\n readonly unsupportedFeaturePolicy?: 'error' | 'warn-omit';\r\n}\r\n\r\nexport interface ResolvedPlainSqlRenderOptions {\r\n readonly includeSessionGuards: boolean;\r\n readonly includeHeaderComments: boolean;\r\n readonly addDropStatements: boolean;\r\n readonly includeDatabaseSettings: boolean;\r\n readonly legacySchemaTableName: boolean;\r\n readonly unsupportedFeaturePolicy: 'error' | 'warn-omit';\r\n}\r\n\r\nexport function resolvePlainSqlRenderOptions(\r\n options?: PlainSqlRenderOptions,\r\n): ResolvedPlainSqlRenderOptions {\r\n return {\r\n includeSessionGuards: options?.includeSessionGuards ?? true,\r\n includeHeaderComments: options?.includeHeaderComments ?? true,\r\n addDropStatements: options?.addDropStatements ?? false,\r\n includeDatabaseSettings: options?.includeDatabaseSettings ?? false,\r\n legacySchemaTableName: options?.legacySchemaTableName ?? false,\r\n unsupportedFeaturePolicy: options?.unsupportedFeaturePolicy ?? 'error',\r\n };\r\n}\r\n\r\nexport interface PlainSqlRenderRequest {\r\n readonly database: SqliteDatabase;\r\n readonly archive: DumpArchiveInspection;\r\n readonly writer: DumpWriter;\r\n readonly options?: PlainSqlRenderOptions;\r\n readonly signal?: AbortSignal;\r\n readonly onProgress?: DumpProgressCallback;\r\n /** Source library version; informational. */\r\n readonly sourceVersion?: SqliteVersion;\r\n /** Which dump mode produced `archive`. Defaults to `'full'`. */\r\n readonly mode?: DumpMode;\r\n /**\r\n * Called for each `tableData` entry, for callers that can actually stream\r\n * the rows (see `dumpSqlite`, which supplies this backed by a live\r\n * connection). Resolve `true` once the rows have been written to\r\n * `writer`; resolve `false` to fall back to the default \"not rendered\"\r\n * warning for that entry.\r\n */\r\n readonly onTableData?: (entry: ArchiveEntry) => Promise<boolean>;\r\n}\r\n\r\nexport interface PlainSqlRenderResult {\r\n readonly bytesWritten: number;\r\n readonly renderedDumpIds: readonly string[];\r\n readonly skippedDumpIds: readonly string[];\r\n readonly warnings: readonly SqliteDiagnostic[];\r\n readonly cancelled: boolean;\r\n}\r\n","/**\r\n * A port of SQLite's `sqlite3_complete()` (`complete.c`) — the function the\r\n * `sqlite3` shell calls to decide whether the text it has accumulated so far\r\n * is one or more *complete* statements, and therefore ready to run.\r\n *\r\n * Splitting on `;` is not enough, and not in an edge-case way: a trigger\r\n * body is a list of statements, each ending in `;`, inside a single\r\n * `CREATE TRIGGER ... BEGIN ... END;`. `sqlite3_complete()` recognizes that\r\n * with a small state machine over eight token classes, and reproducing that\r\n * machine exactly is what makes this package split a script where the shell\r\n * does.\r\n */\r\n\r\n/** Token classes of the `sqlite3_complete()` state machine. */\r\nexport const CompleteToken = {\r\n Semi: 0,\r\n Whitespace: 1,\r\n Other: 2,\r\n Explain: 3,\r\n Create: 4,\r\n Temp: 5,\r\n Trigger: 6,\r\n End: 7,\r\n} as const;\r\n\r\nexport type CompleteToken = (typeof CompleteToken)[keyof typeof CompleteToken];\r\n\r\n/**\r\n * States of the machine:\r\n *\r\n * - `0` INVALID — nothing but whitespace/comments seen yet.\r\n * - `1` START — at the start of a statement, or just after a complete one.\r\n * - `2` NORMAL — inside an ordinary statement.\r\n * - `3` EXPLAIN — the statement began with `EXPLAIN`.\r\n * - `4` CREATE — the statement began with `CREATE` (or `EXPLAIN CREATE`).\r\n * - `5` TRIGGER — inside `CREATE [TEMP] TRIGGER ...`, before or within its body.\r\n * - `6` SEMI — just saw a `;` inside a trigger body.\r\n * - `7` END — saw `END` right after such a `;`; the next `;` completes the trigger.\r\n */\r\nexport const COMPLETE_TRANSITIONS: readonly (readonly number[])[] = [\r\n // SEMI WS OTHER EXPLAIN CREATE TEMP TRIGGER END\r\n /* 0 */ [1, 0, 2, 3, 4, 2, 2, 2],\r\n /* 1 */ [1, 1, 2, 3, 4, 2, 2, 2],\r\n /* 2 */ [1, 2, 2, 2, 2, 2, 2, 2],\r\n /* 3 */ [1, 3, 3, 2, 4, 2, 2, 2],\r\n /* 4 */ [1, 4, 2, 2, 2, 4, 5, 2],\r\n /* 5 */ [6, 5, 5, 5, 5, 5, 5, 5],\r\n /* 6 */ [6, 6, 5, 5, 5, 5, 5, 7],\r\n /* 7 */ [1, 7, 5, 5, 5, 5, 5, 5],\r\n];\r\n\r\n/** Applies one token to a state. */\r\nexport function completeTransition(state: number, token: CompleteToken): number {\r\n return (COMPLETE_TRANSITIONS[state] as readonly number[])[token] as number;\r\n}\r\n\r\n/**\r\n * `IdChar()` from `complete.c`: letters, digits, `_`, `$`, and every byte (or\r\n * code unit) at or above `0x80`, which is how SQLite admits non-ASCII\r\n * identifiers without decoding them.\r\n */\r\nexport function isIdentifierCharCode(code: number): boolean {\r\n return (\r\n (code >= 0x61 && code <= 0x7a) ||\r\n (code >= 0x41 && code <= 0x5a) ||\r\n (code >= 0x30 && code <= 0x39) ||\r\n code === 0x5f ||\r\n code === 0x24 ||\r\n code >= 0x80\r\n );\r\n}\r\n\r\n/** Classifies a complete identifier-like word the way `sqlite3_complete()` does. */\r\nexport function classifyWord(word: string): CompleteToken {\r\n switch (word.length) {\r\n case 3:\r\n return word.toLowerCase() === 'end' ? CompleteToken.End : CompleteToken.Other;\r\n case 4:\r\n return word.toLowerCase() === 'temp' ? CompleteToken.Temp : CompleteToken.Other;\r\n case 6:\r\n return word.toLowerCase() === 'create' ? CompleteToken.Create : CompleteToken.Other;\r\n case 7: {\r\n const lower = word.toLowerCase();\r\n if (lower === 'trigger') return CompleteToken.Trigger;\r\n if (lower === 'explain') return CompleteToken.Explain;\r\n return CompleteToken.Other;\r\n }\r\n case 9:\r\n return word.toLowerCase() === 'temporary' ? CompleteToken.Temp : CompleteToken.Other;\r\n default:\r\n return CompleteToken.Other;\r\n }\r\n}\r\n\r\nfunction isCompleteWhitespace(character: string): boolean {\r\n return (\r\n character === ' ' ||\r\n character === '\\r' ||\r\n character === '\\t' ||\r\n character === '\\n' ||\r\n character === '\\f'\r\n );\r\n}\r\n\r\n/**\r\n * `sqlite3_complete()`: `true` when `sql` ends with a complete statement —\r\n * a `;` that is not inside a string, identifier, comment or trigger body,\r\n * followed by nothing but whitespace and comments.\r\n *\r\n * Faithful to the C, including its quirks: an unterminated `/*` comment or\r\n * quoted token makes the text incomplete, while a trailing `--` comment\r\n * with no newline does not.\r\n */\r\nexport function isCompleteStatement(sql: string): boolean {\r\n let state = 0;\r\n let index = 0;\r\n const length = sql.length;\r\n\r\n while (index < length) {\r\n const character = sql[index] as string;\r\n let token: CompleteToken;\r\n\r\n if (character === ';') {\r\n token = CompleteToken.Semi;\r\n } else if (isCompleteWhitespace(character)) {\r\n token = CompleteToken.Whitespace;\r\n } else if (character === '/') {\r\n if (sql[index + 1] !== '*') {\r\n token = CompleteToken.Other;\r\n } else {\r\n index += 2;\r\n while (index < length && !(sql[index] === '*' && sql[index + 1] === '/')) {\r\n index++;\r\n }\r\n if (index >= length) {\r\n return false;\r\n }\r\n index++;\r\n token = CompleteToken.Whitespace;\r\n }\r\n } else if (character === '-') {\r\n if (sql[index + 1] !== '-') {\r\n token = CompleteToken.Other;\r\n } else {\r\n while (index < length && sql[index] !== '\\n') {\r\n index++;\r\n }\r\n if (index >= length) {\r\n return state === 1;\r\n }\r\n token = CompleteToken.Whitespace;\r\n }\r\n } else if (character === '[') {\r\n index++;\r\n while (index < length && sql[index] !== ']') {\r\n index++;\r\n }\r\n if (index >= length) {\r\n return false;\r\n }\r\n token = CompleteToken.Other;\r\n } else if (character === '`' || character === '\"' || character === \"'\") {\r\n index++;\r\n while (index < length && sql[index] !== character) {\r\n index++;\r\n }\r\n if (index >= length) {\r\n return false;\r\n }\r\n token = CompleteToken.Other;\r\n } else if (isIdentifierCharCode(sql.charCodeAt(index))) {\r\n let end = index + 1;\r\n while (end < length && isIdentifierCharCode(sql.charCodeAt(end))) {\r\n end++;\r\n }\r\n token = classifyWord(sql.slice(index, end));\r\n index = end - 1;\r\n } else {\r\n token = CompleteToken.Other;\r\n }\r\n\r\n state = completeTransition(state, token);\r\n index++;\r\n }\r\n return state === 1;\r\n}\r\n","import { isCompleteStatement } from '../restore/complete.js';\r\nimport { quoteIdentifierIfNeeded, toAsciiLowerCase } from '../security/identifiers.js';\r\nimport { quoteStringLiteral } from '../security/literals.js';\r\n\r\n/** The native `.dump` preamble: integrity checks off, then one transaction around everything. */\r\nexport const SESSION_GUARD_HEADER = 'PRAGMA foreign_keys=OFF;\\nBEGIN TRANSACTION;\\n';\r\n\r\nexport const SESSION_GUARD_FOOTER = 'COMMIT;\\n';\r\n\r\nexport const WRITABLE_SCHEMA_ON = 'PRAGMA writable_schema=ON;\\n';\r\n\r\nexport const WRITABLE_SCHEMA_OFF = 'PRAGMA writable_schema=OFF;\\n';\r\n\r\n/**\r\n * `printSchemaLine()` from `shell.c`: how the native `.dump` writes a\r\n * table's stored `CREATE TABLE` text.\r\n *\r\n * Two details are reproduced exactly, because both change the bytes:\r\n *\r\n * - **A trailing comment.** SQLite stores DDL verbatim, so it can end in a\r\n * `--` comment (which would swallow an appended `;`) or even an\r\n * unterminated `/*` comment (which SQLite accepts at end of input). When\r\n * the text contains either, the shell tries appending nothing, `*\\/` and a\r\n * newline, in that order, and keeps the first variant that\r\n * `sqlite3_complete()` accepts once `;` is added.\r\n * - **`IF NOT EXISTS` for quoted names.** A `CREATE TABLE` whose name is\r\n * written in single or double quotes becomes\r\n * `CREATE TABLE IF NOT EXISTS`. Virtual table modules create their shadow\r\n * tables with exactly that spelling (`CREATE TABLE 'ft_data'(...)`), and\r\n * by the time the dump reaches them on restore, a module may already have\r\n * created them.\r\n */\r\nexport function renderSchemaLine(sql: string, tail = ';\\n'): string {\r\n let text = sql;\r\n if (tail.startsWith(';') && (text.includes('/*') || text.includes('--'))) {\r\n for (const terminator of ['', '*/', '\\n']) {\r\n if (isCompleteStatement(`${text}${terminator};`)) {\r\n text = `${text}${terminator}`;\r\n break;\r\n }\r\n }\r\n }\r\n if (/^CREATE TABLE ['\"]/.test(text)) {\r\n return `CREATE TABLE IF NOT EXISTS ${text.slice(13)}${tail}`;\r\n }\r\n return `${text}${tail}`;\r\n}\r\n\r\n/**\r\n * How `run_table_dump_query()` in `shell.c` writes an index, trigger or view:\r\n * the stored text, then `;` — on a line of its own if the text contains\r\n * `--` anywhere, so a trailing line comment cannot swallow it. (The test is\r\n * a plain substring search, so a `--` inside a string literal triggers it\r\n * too, and does here.)\r\n */\r\nexport function renderSchemaObject(sql: string): string {\r\n return sql.includes('--') ? `${sql}\\n;\\n` : `${sql};\\n`;\r\n}\r\n\r\n/**\r\n * A virtual table, recreated the way the native `.dump` does it: by writing\r\n * its row into `sqlite_schema` directly (under `PRAGMA writable_schema=ON`)\r\n * instead of running `CREATE VIRTUAL TABLE`.\r\n *\r\n * Running the `CREATE` would invoke the module's constructor, which for most\r\n * modules creates and initializes the shadow tables — and the dump is about\r\n * to recreate those itself, with the source's exact contents. Writing the\r\n * schema row leaves the shadow tables to the dump, so an FTS index or R-tree\r\n * comes back byte-identical rather than rebuilt.\r\n */\r\nexport function renderVirtualTable(name: string, sql: string, schemaTableName: string): string {\r\n // `'%q'` in the shell's format string: single quotes doubled, nothing else.\r\n const quotedName = quoteStringLiteral(name);\r\n return `INSERT INTO ${schemaTableName}(type,name,tbl_name,rootpage,sql)VALUES('table',${quotedName},${quotedName},0,${quoteStringLiteral(sql)});\\n`;\r\n}\r\n\r\n/**\r\n * The statement that prepares a system table for its rows.\r\n *\r\n * - `sqlite_sequence` is emptied, so the `AUTOINCREMENT` counters that\r\n * follow replace — rather than duplicate — the counters the preceding\r\n * inserts advanced. A partial dump only resets the counters of the tables\r\n * it contains.\r\n * - `sqlite_stat1`/`sqlite_stat4` are created, if missing, by analyzing the\r\n * (trivial) schema table, which is how the native `.dump` guarantees they\r\n * exist before inserting into them.\r\n */\r\nexport function renderSystemTablePrelude(\r\n name: string,\r\n schemaTableName: string,\r\n systemRowFilter: readonly string[] | undefined,\r\n): string {\r\n if (name === 'sqlite_sequence') {\r\n if (systemRowFilter === undefined) {\r\n return 'DELETE FROM sqlite_sequence;\\n';\r\n }\r\n const names = [...new Set(systemRowFilter.map(toAsciiLowerCase))].map(quoteStringLiteral);\r\n return `DELETE FROM sqlite_sequence WHERE lower(name) IN (${names.join(',')});\\n`;\r\n }\r\n return `ANALYZE ${schemaTableName};\\n`;\r\n}\r\n\r\nexport type DroppableKind = 'TABLE' | 'INDEX' | 'TRIGGER' | 'VIEW';\r\n\r\n/** `DROP <kind> IF EXISTS <name>;`, for `addDropStatements`. */\r\nexport function renderDrop(kind: DroppableKind, name: string): string {\r\n return `DROP ${kind} IF EXISTS ${quoteIdentifierIfNeeded(name)};\\n`;\r\n}\r\n\r\n/** `PRAGMA user_version=…;` / `PRAGMA application_id=…;`, for `includeDatabaseSettings`. */\r\nexport function renderDatabaseSettings(userVersion: number, applicationId: number): string {\r\n let text = '';\r\n if (userVersion !== 0) {\r\n text += `PRAGMA user_version=${userVersion};\\n`;\r\n }\r\n if (applicationId !== 0) {\r\n text += `PRAGMA application_id=${applicationId};\\n`;\r\n }\r\n return text;\r\n}\r\n","import { redactSecrets } from '../security/redact.js';\r\n\r\n/**\r\n * Truncates SQL for inclusion in an error message or a progress event.\r\n *\r\n * Never a full statement — a single `INSERT` can carry a megabyte of blob —\r\n * and never a literal encryption key.\r\n */\r\nexport function safeSqlPreview(sql: string, maximumLength = 200): string {\r\n const normalized = redactSecrets(sql).trim().replace(/\\s+/g, ' ');\r\n if (normalized.length <= maximumLength) {\r\n return normalized;\r\n }\r\n let cut = normalized.slice(0, maximumLength);\r\n // Never split a surrogate pair: an emoji straddling the cut would leave a\r\n // lone high surrogate, making the preview ill-formed UTF-16 —\r\n // `JSON.stringify` would emit an unpaired `\\ud83d`, and writing it as UTF-8\r\n // would substitute U+FFFD.\r\n const lastUnit = cut.charCodeAt(cut.length - 1);\r\n if (lastUnit >= 0xd800 && lastUnit <= 0xdbff) {\r\n cut = cut.slice(0, -1);\r\n }\r\n return `${cut}…`;\r\n}\r\n\r\n/** The warning line the native `.dump` writes first when the dump contains virtual tables. */\r\nexport const DEFENSIVE_WARNING_COMMENT =\r\n '/* WARNING: Script requires that SQLITE_DBCONFIG_DEFENSIVE be disabled */';\r\n\r\n/**\r\n * Heuristically detects whether `sample` looks like a SQLite dump — whether\r\n * produced by the native `.dump` command or by this package, which write the\r\n * same thing.\r\n *\r\n * A full dump opens with `PRAGMA foreign_keys=OFF;` and\r\n * `BEGIN TRANSACTION;`, optionally preceded by the defensive-mode warning\r\n * comment; that opening is what is recognized. A `--data-only` dump has no\r\n * such preamble and is indistinguishable from any other script of\r\n * `INSERT`s, so it is only recognized when it carries the warning comment.\r\n *\r\n * Only the first few kilobytes need to be supplied; the check never reads\r\n * beyond what it is given, so a caller can pass the head of a large file.\r\n */\r\nexport function isSqliteDump(sample: string | Uint8Array): boolean {\r\n const text = typeof sample === 'string' ? sample : Buffer.from(sample).toString('utf8');\r\n const head = text\r\n .slice(0, 8192)\r\n .replace(/^\\uFEFF/, '')\r\n .replace(/\\r\\n/g, '\\n');\r\n let rest = head.trimStart();\r\n if (rest.startsWith(DEFENSIVE_WARNING_COMMENT)) {\r\n rest = rest.slice(DEFENSIVE_WARNING_COMMENT.length).trimStart();\r\n if (rest === '' || /^INSERT INTO /.test(rest) || rest.startsWith('PRAGMA foreign_keys=OFF;')) {\r\n return true;\r\n }\r\n }\r\n return /^PRAGMA foreign_keys=OFF;\\s*\\nBEGIN TRANSACTION;/.test(rest);\r\n}\r\n","import type { ArchiveEntry } from '../archive/types.js';\r\nimport type { SqliteIndex, SqliteTrigger, SqliteView } from '../model/database.js';\r\nimport type { SqliteDiagnostic } from '../model/diagnostics.js';\r\nimport { DEFENSIVE_WARNING_COMMENT } from '../restore/preview.js';\r\nimport { foldSqliteName } from '../selection/normalize.js';\r\nimport { isAbortError, SqliteDumperError, throwIfAborted } from '../utils/errors.js';\r\nimport type { DumpProgressSection } from '../utils/progress.js';\r\nimport {\r\n renderDatabaseSettings,\r\n renderDrop,\r\n renderSchemaLine,\r\n renderSchemaObject,\r\n renderSystemTablePrelude,\r\n renderVirtualTable,\r\n SESSION_GUARD_FOOTER,\r\n SESSION_GUARD_HEADER,\r\n WRITABLE_SCHEMA_OFF,\r\n WRITABLE_SCHEMA_ON,\r\n} from './objectRenderers.js';\r\nimport { resolvePlainSqlRenderOptions } from './types.js';\r\nimport type {\r\n PlainSqlRenderRequest,\r\n PlainSqlRenderResult,\r\n ResolvedPlainSqlRenderOptions,\r\n} from './types.js';\r\n\r\nconst SECTION_BY_ENTRY: Record<ArchiveEntry['objectType'], DumpProgressSection> = {\r\n table: 'table-structure',\r\n tableData: 'table-data',\r\n virtualTable: 'virtual-table',\r\n index: 'index',\r\n trigger: 'trigger',\r\n view: 'view',\r\n};\r\n\r\n/**\r\n * Renders a validated {@link DumpArchiveInspection} as plain SQL in the\r\n * native `.dump` layout — the same statements, in the same order, spelled\r\n * the same way.\r\n *\r\n * Purely a function of the static model and the archive plan: it never\r\n * queries the database, which is why row data has to arrive through the\r\n * `onTableData` hook (see `exportTableDataAsInserts` for the streaming\r\n * implementation `dumpSqlite` supplies).\r\n */\r\nexport async function renderPlainSql(\r\n request: PlainSqlRenderRequest,\r\n): Promise<PlainSqlRenderResult> {\r\n const options = resolvePlainSqlRenderOptions(request.options);\r\n const { database, archive, writer, signal, onProgress, onTableData } = request;\r\n const mode = request.mode ?? 'full';\r\n\r\n if (!archive.valid) {\r\n throw new SqliteDumperError(\r\n 'invalid-archive',\r\n 'Cannot render an archive inspection that failed validation; see archive.diagnostics, archive.cycles and archive.unsatisfiedDependencies',\r\n );\r\n }\r\n\r\n const warnings: SqliteDiagnostic[] = [];\r\n const renderedDumpIds: string[] = [];\r\n const skippedDumpIds: string[] = [];\r\n const schemaTableName = options.legacySchemaTableName ? 'sqlite_master' : 'sqlite_schema';\r\n\r\n const tables = new Map(database.tables.map(table => [foldSqliteName(table.name), table]));\r\n const indexes = new Map(database.indexes.map(index => [foldSqliteName(index.name), index]));\r\n const triggers = new Map(\r\n database.triggers.map(trigger => [foldSqliteName(trigger.name), trigger]),\r\n );\r\n const views = new Map(database.views.map(view => [foldSqliteName(view.name), view]));\r\n\r\n const emit = async (text: string): Promise<void> => {\r\n if (text !== '') {\r\n await writer.write(text, signal);\r\n }\r\n };\r\n\r\n const guards = options.includeSessionGuards && mode !== 'data-only';\r\n if (!options.includeSessionGuards && mode !== 'data-only') {\r\n warnings.push({\r\n severity: 'warning',\r\n code: 'session-guards-disabled',\r\n message:\r\n 'render.includeSessionGuards is false, so the dump omits PRAGMA foreign_keys=OFF and its BEGIN TRANSACTION / COMMIT. Tables that reference each other may fail to restore in the emitted order, and every INSERT runs as its own transaction, which makes restoring a large dump dramatically slower.',\r\n });\r\n }\r\n\r\n reportUnDumpedSettings(request, options, warnings);\r\n\r\n // The warning appears whenever the dump contains a virtual table, even in\r\n // a data-only dump — the native `.dump` decides it from the schema alone.\r\n const containsVirtualTables =\r\n mode !== 'schema-only' &&\r\n archive.entries.some(\r\n entry =>\r\n entry.objectType === 'virtualTable' ||\r\n entry.tableKind === 'virtual' ||\r\n (entry.tableKind === 'shadow' &&\r\n tables.get(foldSqliteName(entry.name))?.ownerVirtualTable !== undefined),\r\n );\r\n\r\n let writableSchema = false;\r\n\r\n try {\r\n if (options.includeHeaderComments && containsVirtualTables) {\r\n await emit(`${DEFENSIVE_WARNING_COMMENT}\\n`);\r\n }\r\n if (guards) {\r\n await emit(SESSION_GUARD_HEADER);\r\n }\r\n\r\n let processed = 0;\r\n const total = archive.entries.length;\r\n\r\n for (const entry of archive.entries) {\r\n throwIfAborted(signal);\r\n processed++;\r\n onProgress?.({\r\n phase: 'rendering-schema',\r\n section: SECTION_BY_ENTRY[entry.objectType],\r\n objectsProcessed: processed,\r\n objectsTotal: total,\r\n objectName: entry.name,\r\n schemaName: entry.schemaName,\r\n bytesWritten: writer.bytesWritten,\r\n });\r\n\r\n let handled: boolean;\r\n switch (entry.objectType) {\r\n case 'table': {\r\n const table = tables.get(foldSqliteName(entry.name));\r\n if (!table) {\r\n handled = missing(entry, 'table', warnings, options);\r\n break;\r\n }\r\n if (table.kind === 'system') {\r\n await emit(\r\n renderSystemTablePrelude(table.name, schemaTableName, entry.systemRowFilter),\r\n );\r\n } else {\r\n if (options.addDropStatements) {\r\n await emit(renderDrop('TABLE', table.name));\r\n }\r\n await emit(renderSchemaLine(table.sql));\r\n }\r\n handled = true;\r\n break;\r\n }\r\n\r\n case 'virtualTable': {\r\n const table = tables.get(foldSqliteName(entry.name));\r\n if (!table) {\r\n handled = missing(entry, 'virtual table', warnings, options);\r\n break;\r\n }\r\n if (options.addDropStatements) {\r\n await emit(renderDrop('TABLE', table.name));\r\n }\r\n if (mode === 'schema-only') {\r\n // No shadow-table rows follow in a schema-only dump, so the table\r\n // must be created by its module, which initializes them — as the\r\n // native `.schema` writes it. The shadow tables' own\r\n // `CREATE TABLE IF NOT EXISTS` lines then do nothing.\r\n await emit(renderSchemaLine(table.sql));\r\n } else {\r\n if (!writableSchema) {\r\n await emit(WRITABLE_SCHEMA_ON);\r\n writableSchema = true;\r\n }\r\n await emit(renderVirtualTable(table.name, table.sql, schemaTableName));\r\n }\r\n handled = true;\r\n break;\r\n }\r\n\r\n case 'tableData': {\r\n const table = tables.get(foldSqliteName(entry.name));\r\n if (!table) {\r\n handled = missing(entry, 'table', warnings, options);\r\n break;\r\n }\r\n if (onTableData) {\r\n handled = await onTableData(entry);\r\n } else {\r\n warnings.push({\r\n severity: 'warning',\r\n code: 'data-not-rendered',\r\n message: `Row data for table \"${entry.name}\" was selected, but renderPlainSql only renders schema objects; use dumpSqlite (or supply onTableData) with a live connection to stream rows.`,\r\n objectReference: { kind: 'table', schemaName: entry.schemaName, name: entry.name },\r\n });\r\n handled = true;\r\n }\r\n break;\r\n }\r\n\r\n case 'index':\r\n case 'trigger':\r\n case 'view': {\r\n const object = lookupSchemaObject(entry, indexes, triggers, views);\r\n if (!object || object.sql === null) {\r\n handled = missing(entry, entry.objectType, warnings, options);\r\n break;\r\n }\r\n if (options.addDropStatements) {\r\n await emit(\r\n renderDrop(\r\n entry.objectType === 'index'\r\n ? 'INDEX'\r\n : entry.objectType === 'trigger'\r\n ? 'TRIGGER'\r\n : 'VIEW',\r\n entry.name,\r\n ),\r\n );\r\n }\r\n await emit(renderSchemaObject(object.sql));\r\n handled = true;\r\n break;\r\n }\r\n\r\n default: {\r\n const unreachable: never = entry.objectType;\r\n throw new SqliteDumperError(\r\n 'unsupported-object',\r\n `Unhandled archive object type: ${String(unreachable)}`,\r\n );\r\n }\r\n }\r\n\r\n if (handled) {\r\n renderedDumpIds.push(entry.dumpId);\r\n } else {\r\n skippedDumpIds.push(entry.dumpId);\r\n }\r\n }\r\n\r\n if (writableSchema) {\r\n await emit(WRITABLE_SCHEMA_OFF);\r\n }\r\n if (options.includeDatabaseSettings) {\r\n await emit(renderDatabaseSettings(database.userVersion, database.applicationId));\r\n }\r\n if (guards) {\r\n await emit(SESSION_GUARD_FOOTER);\r\n }\r\n\r\n return {\r\n bytesWritten: writer.bytesWritten,\r\n renderedDumpIds,\r\n skippedDumpIds,\r\n warnings,\r\n cancelled: false,\r\n };\r\n } catch (error) {\r\n if (isAbortError(error)) {\r\n return {\r\n bytesWritten: writer.bytesWritten,\r\n renderedDumpIds,\r\n skippedDumpIds,\r\n warnings,\r\n cancelled: true,\r\n };\r\n }\r\n throw error;\r\n }\r\n}\r\n\r\nfunction lookupSchemaObject(\r\n entry: ArchiveEntry,\r\n indexes: ReadonlyMap<string, SqliteIndex>,\r\n triggers: ReadonlyMap<string, SqliteTrigger>,\r\n views: ReadonlyMap<string, SqliteView>,\r\n): { sql: string | null } | undefined {\r\n const key = foldSqliteName(entry.name);\r\n switch (entry.objectType) {\r\n case 'index':\r\n return indexes.get(key);\r\n case 'trigger':\r\n return triggers.get(key);\r\n default:\r\n return views.get(key);\r\n }\r\n}\r\n\r\n/**\r\n * `user_version` and `application_id` are database settings the native\r\n * `.dump` does not carry. An application that tracks its schema migrations\r\n * in `user_version` would restore into a database that looks unmigrated, so\r\n * a non-zero value that is not being dumped is reported rather than dropped\r\n * silently.\r\n */\r\nfunction reportUnDumpedSettings(\r\n request: PlainSqlRenderRequest,\r\n options: ResolvedPlainSqlRenderOptions,\r\n warnings: SqliteDiagnostic[],\r\n): void {\r\n if (options.includeDatabaseSettings) {\r\n return;\r\n }\r\n const { database } = request;\r\n if (database.userVersion !== 0) {\r\n warnings.push({\r\n severity: 'warning',\r\n code: 'user-version-not-dumped',\r\n message: `The database's PRAGMA user_version is ${database.userVersion}, which the dump does not carry (the native .dump does not either). Set render.includeDatabaseSettings to include it; applications often track schema migrations in it.`,\r\n objectReference: {\r\n kind: 'database',\r\n schemaName: database.schemaName,\r\n name: database.schemaName,\r\n },\r\n });\r\n }\r\n if (database.applicationId !== 0) {\r\n warnings.push({\r\n severity: 'warning',\r\n code: 'application-id-not-dumped',\r\n message: `The database's PRAGMA application_id is ${database.applicationId}, which the dump does not carry (the native .dump does not either). Set render.includeDatabaseSettings to include it.`,\r\n objectReference: {\r\n kind: 'database',\r\n schemaName: database.schemaName,\r\n name: database.schemaName,\r\n },\r\n });\r\n }\r\n}\r\n\r\nfunction missing(\r\n entry: ArchiveEntry,\r\n kind: string,\r\n warnings: SqliteDiagnostic[],\r\n options: ResolvedPlainSqlRenderOptions,\r\n): boolean {\r\n const message = `Archive entry references ${kind} \"${entry.name}\", which was not found in the introspected model`;\r\n if (options.unsupportedFeaturePolicy === 'warn-omit') {\r\n warnings.push({ severity: 'warning', code: 'model-object-missing', message });\r\n return false;\r\n }\r\n throw new SqliteDumperError('model-object-missing', message);\r\n}\r\n","/**\r\n * Accumulates SQL fragments that may be text *or* raw bytes.\r\n *\r\n * A `TEXT` value holding bytes that are not valid UTF-8 is written out raw,\r\n * exactly as the native `.dump` writes it, so a statement cannot always be\r\n * assembled as a JavaScript string. Joining through a string would replace\r\n * every invalid sequence with U+FFFD and corrupt the data silently.\r\n *\r\n * The all-text case — which is every row of every ordinary database — stays\r\n * on the fast path: parts are joined with `String.prototype.join` and no\r\n * `Buffer` is allocated at all. Only a builder that has actually been handed\r\n * bytes falls back to `Buffer.concat`.\r\n */\r\nexport class SqlChunkBuilder {\r\n private readonly parts: (string | Buffer)[] = [];\r\n private byteLength = 0;\r\n private hasBytes = false;\r\n\r\n /** UTF-8 byte length of everything appended so far. */\r\n get length(): number {\r\n return this.byteLength;\r\n }\r\n\r\n get isEmpty(): boolean {\r\n return this.parts.length === 0;\r\n }\r\n\r\n append(part: string | Buffer): this {\r\n if (typeof part === 'string') {\r\n if (part.length === 0) {\r\n return this;\r\n }\r\n this.parts.push(part);\r\n this.byteLength += Buffer.byteLength(part, 'utf8');\r\n return this;\r\n }\r\n if (part.length === 0) {\r\n return this;\r\n }\r\n this.parts.push(part);\r\n this.byteLength += part.length;\r\n this.hasBytes = true;\r\n return this;\r\n }\r\n\r\n /** Appends everything from `other`, leaving `other` untouched. */\r\n appendBuilder(other: SqlChunkBuilder): this {\r\n for (const part of other.parts) {\r\n this.append(part);\r\n }\r\n return this;\r\n }\r\n\r\n /** The accumulated content, as a `string` when it is all text and a `Buffer` otherwise. */\r\n build(): string | Buffer {\r\n if (!this.hasBytes) {\r\n return this.parts.join('');\r\n }\r\n return Buffer.concat(\r\n this.parts.map(part => (typeof part === 'string' ? Buffer.from(part, 'utf8') : part)),\r\n );\r\n }\r\n}\r\n","import type { SqliteColumnValue, SqliteRow } from '../connection/types.js';\r\nimport { isUtf8 } from 'node:buffer';\r\nimport { renderBlobLiteral, renderTextLiteral } from '../security/literals.js';\r\nimport type { TextLiteralStyle } from '../security/literals.js';\r\n\r\n/**\r\n * The SQL expression that renders a `REAL` exactly as the native `.dump`\r\n * renders it, evaluated by SQLite itself. `shell.c` does this:\r\n *\r\n * ```c\r\n * if( ur==0x7ff0000000000000LL ) oputz(\"9.0e+999\");\r\n * else if( ur==0xfff0000000000000LL ) oputz(\"-9.0e+999\");\r\n * else {\r\n * sqlite3_int64 ir = (sqlite3_int64)r;\r\n * if( r==(double)ir ) sqlite3_snprintf(50,z,\"%lld.0\", ir);\r\n * else sqlite3_snprintf(50,z,\"%!.20g\", r);\r\n * }\r\n * ```\r\n *\r\n * Doing it in SQL rather than in JavaScript is the point. The digits\r\n * `%!.20g` produces come from SQLite's own floating-point formatter, which\r\n * no JavaScript routine reproduces (and which changed between SQLite\r\n * releases); asking the database to format the value is the only way to\r\n * write the same digits the shell of the same SQLite version would. It also\r\n * means the value never passes through the driver as a JavaScript number.\r\n *\r\n * `9e999` is how SQLite spells infinity in SQL: it overflows to `Inf` on\r\n * parse, which is also why the dump writes it that way.\r\n */\r\nfunction realLiteralExpression(column: string): string {\r\n return (\r\n `CASE WHEN ${column} = 9e999 THEN '9.0e+999' ` +\r\n `WHEN ${column} = -9e999 THEN '-9.0e+999' ` +\r\n `WHEN ${column} >= -9223372036854775808.0 AND ${column} < 9223372036854775808.0 AND ${column} = CAST(${column} AS INTEGER) ` +\r\n `THEN CAST(CAST(${column} AS INTEGER) AS TEXT) || '.0' ` +\r\n `ELSE printf('%!.20g', ${column}) END`\r\n );\r\n}\r\n\r\n/**\r\n * The select-list for one column: its storage class, and a value shaped so\r\n * that only exact representations cross the driver boundary.\r\n *\r\n * - `INTEGER` → decimal text, so a 64-bit value is exact whatever the\r\n * driver would have done with it;\r\n * - `REAL` → the literal text, see {@link realLiteralExpression};\r\n * - `TEXT` → the stored bytes (`CAST(... AS BLOB)`), so text that is not\r\n * valid UTF-8 is not \"repaired\" by the driver's decoder on the way out.\r\n * In a UTF-16 database those bytes would be UTF-16, so there the value is\r\n * read as text instead and the driver's (lossless, for valid UTF-16)\r\n * conversion is used;\r\n * - `BLOB` → the bytes; `NULL` → `NULL`.\r\n */\r\nexport function columnValueSelect(column: string, index: number, utf8Database: boolean): string {\r\n const textBranch = utf8Database ? `CAST(${column} AS BLOB)` : column;\r\n return (\r\n `typeof(${column}) AS \"t${index}\", ` +\r\n `CASE typeof(${column}) ` +\r\n `WHEN 'integer' THEN CAST(${column} AS TEXT) ` +\r\n `WHEN 'real' THEN ${realLiteralExpression(column)} ` +\r\n `WHEN 'text' THEN ${textBranch} ` +\r\n `ELSE ${column} END AS \"v${index}\"`\r\n );\r\n}\r\n\r\nfunction asBytes(value: SqliteColumnValue): Buffer {\r\n if (Buffer.isBuffer(value)) {\r\n return value;\r\n }\r\n if (value instanceof Uint8Array) {\r\n return Buffer.from(value.buffer, value.byteOffset, value.byteLength);\r\n }\r\n return Buffer.from(String(value), 'utf8');\r\n}\r\n\r\n/**\r\n * Renders column `index` of a row produced by {@link columnValueSelect} as\r\n * the SQL literal the native `.dump` writes for it.\r\n *\r\n * Returns a `Buffer` only for text that is not valid UTF-8: the shell writes\r\n * such bytes out raw, and so does this package, so the dump reproduces the\r\n * stored value exactly (see `DumpWriter` for why that cannot go through a\r\n * string).\r\n */\r\nexport function renderColumnLiteral(\r\n row: SqliteRow,\r\n index: number,\r\n textStyle: TextLiteralStyle,\r\n): string | Buffer {\r\n const storageClass = row[`t${index}`];\r\n const value = row[`v${index}`] ?? null;\r\n switch (storageClass) {\r\n case 'integer':\r\n case 'real':\r\n return String(value);\r\n case 'text': {\r\n if (typeof value === 'string') {\r\n return renderTextLiteral(value, textStyle);\r\n }\r\n const bytes = asBytes(value);\r\n if (isUtf8(bytes)) {\r\n return renderTextLiteral(bytes.toString('utf8'), textStyle);\r\n }\r\n // Escape as a byte string (one code unit per byte) and hand the exact\r\n // bytes back; every character the escaping reacts to is ASCII.\r\n return Buffer.from(renderTextLiteral(bytes.toString('latin1'), textStyle), 'latin1');\r\n }\r\n case 'blob':\r\n return renderBlobLiteral(asBytes(value));\r\n default:\r\n return 'NULL';\r\n }\r\n}\r\n","import type { SqliteRow } from '../connection/types.js';\r\nimport type { SqliteColumn, SqliteTable } from '../model/database.js';\r\nimport type { SqliteDiagnostic } from '../model/diagnostics.js';\r\nimport {\r\n quoteIdentifier,\r\n quoteIdentifierIfNeeded,\r\n quoteQualifiedIdentifier,\r\n toAsciiLowerCase,\r\n} from '../security/identifiers.js';\r\nimport { quoteStringLiteral } from '../security/literals.js';\r\nimport { isAbortError, throwIfAborted } from '../utils/errors.js';\r\nimport { SqlChunkBuilder } from './chunkBuilder.js';\r\nimport type { TableDataExportRequest, TableDataExportResult } from './types.js';\r\nimport { columnValueSelect, renderColumnLiteral } from './valueQuery.js';\r\n\r\nconst DEFAULT_MAX_STATEMENT_BYTES = 1024 * 1024;\r\nconst DEFAULT_MAX_ROWS_PER_STATEMENT = 500;\r\n\r\n/**\r\n * Output is handed to the writer in chunks of about this size. A native dump\r\n * is one short `INSERT` per row, and awaiting the writer once per row would\r\n * cost more than rendering the row did.\r\n */\r\nconst OUTPUT_CHUNK_BYTES = 64 * 1024;\r\n\r\n/** Names the native shell tries, in order, for a rowid that is not a declared column. */\r\nconst ROWID_NAMES = ['rowid', '_rowid_', 'oid'] as const;\r\n\r\n/**\r\n * The columns the native `.dump` inserts: those `PRAGMA table_info` lists,\r\n * which excludes generated columns and the hidden columns of virtual tables.\r\n * Generated columns cannot be inserted into; SQLite recomputes them.\r\n */\r\nexport function insertableColumns(table: SqliteTable): SqliteColumn[] {\r\n return [...table.columns].sort((a, b) => a.cid - b.cid).filter(column => column.hidden === 0);\r\n}\r\n\r\n/**\r\n * The name under which `preserveRowids` can address a table's rowid, as\r\n * `tableColumnList()` in `shell.c` decides it: never for a `WITHOUT ROWID`\r\n * table or one whose rowid is already a declared `INTEGER PRIMARY KEY`, and\r\n * otherwise the first of `rowid`, `_rowid_`, `oid` that no column is named.\r\n */\r\nexport function preservableRowidName(table: SqliteTable): string | null {\r\n if (table.withoutRowid || table.rowidAliasColumn !== null || table.kind === 'virtual') {\r\n return null;\r\n }\r\n const names = new Set(insertableColumns(table).map(column => toAsciiLowerCase(column.name)));\r\n for (const candidate of ROWID_NAMES) {\r\n if (!names.has(candidate)) {\r\n return candidate;\r\n }\r\n }\r\n return null;\r\n}\r\n\r\n/**\r\n * Streams one table's rows as `INSERT` statements in the native `.dump`\r\n * layout.\r\n *\r\n * Requires a live connection; this is deliberately separate from\r\n * `renderPlainSql`, which renders schema objects from the static model and\r\n * never touches the database.\r\n *\r\n * Rows are read in the table's natural order — no `ORDER BY`, exactly like\r\n * the native `.dump`. For an ordinary table that is rowid order, and for a\r\n * `WITHOUT ROWID` table primary-key order, so two dumps of an unchanged\r\n * database are identical.\r\n *\r\n * Memory is bounded by one statement plus a small output buffer: rows are\r\n * consumed from a stream and written as they are rendered, so a table of any\r\n * size dumps in constant memory.\r\n */\r\nexport async function exportTableDataAsInserts(\r\n request: TableDataExportRequest,\r\n): Promise<TableDataExportResult> {\r\n const { connection, schemaName, table, writer, signal, onProgress } = request;\r\n const options = request.options ?? {};\r\n const extendedInsert = options.extendedInsert ?? false;\r\n const maxRowsPerStatement = extendedInsert\r\n ? Math.max(1, options.maxRowsPerStatement ?? DEFAULT_MAX_ROWS_PER_STATEMENT)\r\n : 1;\r\n const maxStatementBytes = Math.max(\r\n 1024,\r\n options.maxStatementBytes ?? DEFAULT_MAX_STATEMENT_BYTES,\r\n );\r\n const textStyle = options.rawNewlines ? 'raw-newlines' : 'escaped';\r\n const utf8Database = (request.encoding ?? 'UTF-8').toUpperCase() === 'UTF-8';\r\n\r\n const warnings: SqliteDiagnostic[] = [];\r\n const columns = insertableColumns(table);\r\n const rowidName = options.preserveRowids ? preservableRowidName(table) : null;\r\n\r\n for (const column of table.columns) {\r\n if (column.generated !== 'none') {\r\n warnings.push({\r\n severity: 'info',\r\n code: 'generated-column-not-exported',\r\n message: `Column \"${table.name}\".\"${column.name}\" is a ${column.generated.toUpperCase()} generated column; SQLite derives its value, so it is excluded from INSERT and recomputed on restore.`,\r\n objectReference: { kind: 'column', schemaName, name: column.name, parentName: table.name },\r\n });\r\n }\r\n }\r\n\r\n if (columns.length === 0) {\r\n warnings.push({\r\n severity: 'warning',\r\n code: 'table-has-no-insertable-columns',\r\n message: `Table \"${table.name}\" has no insertable columns, so no row data is dumped for it.`,\r\n objectReference: { kind: 'table', schemaName, name: table.name },\r\n });\r\n return {\r\n rowsExported: 0,\r\n bytesWritten: writer.bytesWritten,\r\n statementsWritten: 0,\r\n cancelled: false,\r\n warnings,\r\n };\r\n }\r\n\r\n // `INSERT INTO t` (quoted only when the name needs it) and, only when a\r\n // rowid is being preserved, the column list — the native shell writes one\r\n // in no other case, relying on the positional form otherwise.\r\n const columnList = rowidName\r\n ? `(${[rowidName, ...columns.map(column => quoteIdentifierIfNeeded(column.name))].join(',')})`\r\n : '';\r\n const statementPrefix = `INSERT INTO ${quoteIdentifierIfNeeded(table.name)}${columnList} VALUES`;\r\n\r\n const selectList = [\r\n ...(rowidName ? [columnValueSelect(rowidName, 0, utf8Database)] : []),\r\n ...columns.map((column, index) =>\r\n columnValueSelect(quoteIdentifier(column.name), index + (rowidName ? 1 : 0), utf8Database),\r\n ),\r\n ].join(', ');\r\n const valueCount = columns.length + (rowidName ? 1 : 0);\r\n const sql = `SELECT ${selectList} FROM ${quoteQualifiedIdentifier(schemaName, table.name)}${systemRowFilterClause(table, request.systemRowFilter)}`;\r\n\r\n let rowsExported = 0;\r\n let statementsWritten = 0;\r\n let output = new SqlChunkBuilder();\r\n let statement: SqlChunkBuilder | null = null;\r\n let statementRows = 0;\r\n\r\n const flushOutput = async (): Promise<void> => {\r\n if (output.isEmpty) {\r\n return;\r\n }\r\n const chunk = output.build();\r\n output = new SqlChunkBuilder();\r\n await writer.write(chunk, signal);\r\n };\r\n\r\n const closeStatement = async (): Promise<void> => {\r\n if (!statement || statementRows === 0) {\r\n return;\r\n }\r\n statement.append(';\\n');\r\n output.appendBuilder(statement);\r\n statement = null;\r\n statementRows = 0;\r\n statementsWritten++;\r\n if (output.length >= OUTPUT_CHUNK_BYTES) {\r\n await flushOutput();\r\n }\r\n };\r\n\r\n const progress = (\r\n exportState: 'started' | 'progress' | 'finished' | 'failed' | 'cancelled',\r\n ): void => {\r\n onProgress?.({\r\n phase: 'exporting-data',\r\n section: 'table-data',\r\n schemaName,\r\n tableName: table.name,\r\n objectName: table.name,\r\n rowsExported,\r\n bytesWritten: writer.bytesWritten,\r\n exportState,\r\n });\r\n };\r\n\r\n progress('started');\r\n try {\r\n for await (const row of connection.stream<SqliteRow>(\r\n { sql },\r\n {\r\n ...(signal === undefined ? {} : { signal }),\r\n ...(options.streamBatchSize === undefined ? {} : { batchSize: options.streamBatchSize }),\r\n },\r\n )) {\r\n throwIfAborted(signal);\r\n\r\n const tuple = new SqlChunkBuilder();\r\n tuple.append('(');\r\n for (let index = 0; index < valueCount; index++) {\r\n if (index > 0) {\r\n tuple.append(',');\r\n }\r\n tuple.append(renderColumnLiteral(row, index, textStyle));\r\n }\r\n tuple.append(')');\r\n\r\n // Closing *before* appending keeps the byte cap a true upper bound. A\r\n // statement always holds at least one row, however large that row is.\r\n if (\r\n statement &&\r\n (statementRows >= maxRowsPerStatement ||\r\n (statement as SqlChunkBuilder).length + tuple.length + 2 > maxStatementBytes)\r\n ) {\r\n await closeStatement();\r\n }\r\n if (!statement) {\r\n statement = new SqlChunkBuilder();\r\n statement.append(statementPrefix);\r\n } else {\r\n statement.append(',');\r\n }\r\n statement.appendBuilder(tuple);\r\n statementRows++;\r\n rowsExported++;\r\n\r\n if (rowsExported % 1000 === 0) {\r\n progress('progress');\r\n }\r\n }\r\n\r\n await closeStatement();\r\n await flushOutput();\r\n progress('finished');\r\n return {\r\n rowsExported,\r\n bytesWritten: writer.bytesWritten,\r\n statementsWritten,\r\n cancelled: false,\r\n warnings,\r\n };\r\n } catch (error) {\r\n if (isAbortError(error)) {\r\n // Buffered output is deliberately *not* flushed: a dump cut off at an\r\n // arbitrary row boundary should look truncated, not complete.\r\n progress('cancelled');\r\n return {\r\n rowsExported,\r\n bytesWritten: writer.bytesWritten,\r\n statementsWritten,\r\n cancelled: true,\r\n warnings,\r\n };\r\n }\r\n progress('failed');\r\n throw error;\r\n }\r\n}\r\n\r\n/**\r\n * For a partial dump, restricts `sqlite_sequence` to the counters of the\r\n * dumped tables and `sqlite_stat*` to their statistics. Both key the row by\r\n * table name in their first column (`name` and `tbl` respectively).\r\n */\r\nfunction systemRowFilterClause(table: SqliteTable, filter: readonly string[] | undefined): string {\r\n if (filter === undefined || table.kind !== 'system') {\r\n return '';\r\n }\r\n const column = table.name === 'sqlite_sequence' ? 'name' : 'tbl';\r\n const names = [...new Set(filter.map(toAsciiLowerCase))].map(quoteStringLiteral);\r\n if (names.length === 0) {\r\n return ' WHERE 0';\r\n }\r\n return ` WHERE lower(${column}) IN (${names.join(',')})`;\r\n}\r\n","import type { SqliteDatabase } from '../model/database.js';\r\nimport type { SqliteDiagnostic } from '../model/diagnostics.js';\r\nimport { toAsciiLowerCase, toAsciiUpperCase } from '../security/identifiers.js';\r\nimport { detectSqliteCapabilities } from '../version/capabilities.js';\r\nimport type { SqliteCapabilities } from '../version/types.js';\r\n\r\n/**\r\n * A restore target's capabilities have the same shape as a source's, but the\r\n * two stay distinct concepts: a source's describe what introspection may\r\n * use, a target's what DDL it can accept.\r\n */\r\nexport type TargetCapabilities = SqliteCapabilities;\r\n\r\nexport { detectSqliteCapabilities as detectTargetCapabilities };\r\n\r\nexport interface TargetCompatibilityOptions {\r\n /**\r\n * Virtual table modules the target has (`PRAGMA module_list`), when known.\r\n * Without it, module availability is not checked.\r\n */\r\n readonly modules?: ReadonlySet<string>;\r\n /** The dump names `sqlite_master` rather than `sqlite_schema`; see `PlainSqlRenderOptions`. */\r\n readonly legacySchemaTableName?: boolean;\r\n /** The dump uses multi-row `INSERT ... VALUES (...), (...)`. */\r\n readonly extendedInsert?: boolean;\r\n}\r\n\r\nconst FEATURE_LABELS: Record<keyof TargetCapabilities, string> = {\r\n supportsWithoutRowid: 'WITHOUT ROWID tables (SQLite 3.8.2+)',\r\n supportsMultiRowValues: 'multi-row VALUES (SQLite 3.7.11+)',\r\n supportsPragmaFunctions: 'table-valued pragma functions (SQLite 3.16.0+)',\r\n supportsTableXinfo: 'PRAGMA table_xinfo (SQLite 3.26.0+)',\r\n supportsGeneratedColumns: 'generated columns (SQLite 3.31.0+)',\r\n supportsSqliteSchemaAlias: 'the sqlite_schema table name (SQLite 3.33.0+)',\r\n supportsWritableSchemaReset: 'PRAGMA writable_schema=RESET (SQLite 3.35.0+)',\r\n supportsStrictTables: 'STRICT tables (SQLite 3.37.0+)',\r\n supportsTableList: 'PRAGMA table_list (SQLite 3.37.0+)',\r\n};\r\n\r\n/** Collations every SQLite build has. Any other must be registered by the restoring application. */\r\nconst BUILT_IN_COLLATIONS: ReadonlySet<string> = new Set(['BINARY', 'NOCASE', 'RTRIM']);\r\n\r\n/**\r\n * Reports what a dump of `database` needs that `target` cannot provide.\r\n *\r\n * Feature-level rather than statement-level: the dump carries SQLite's own\r\n * stored DDL, so what can be checked is which features the source model\r\n * actually uses — which turns \"restore failed with a syntax error at line\r\n * 4713\" into \"the target is SQLite 3.31 and this dump contains STRICT\r\n * tables\".\r\n *\r\n * Never throws: callers decide whether an unsupported feature blocks the\r\n * restore or is merely reported.\r\n */\r\nexport function checkTargetCompatibility(\r\n database: SqliteDatabase,\r\n target: TargetCapabilities,\r\n options: TargetCompatibilityOptions = {},\r\n): SqliteDiagnostic[] {\r\n const diagnostics: SqliteDiagnostic[] = [];\r\n const { schemaName } = database;\r\n const reported = new Set<keyof TargetCapabilities>();\r\n\r\n const require = (\r\n feature: keyof TargetCapabilities,\r\n detail: string,\r\n objectReference?: SqliteDiagnostic['objectReference'],\r\n ): void => {\r\n if (target[feature] || reported.has(feature)) {\r\n return;\r\n }\r\n reported.add(feature);\r\n diagnostics.push({\r\n severity: 'error',\r\n code: 'unsupported-target-feature',\r\n message: `Restore target does not support ${FEATURE_LABELS[feature]}, which this dump uses: ${detail}`,\r\n ...(objectReference === undefined ? {} : { objectReference }),\r\n });\r\n };\r\n\r\n const missingModules = new Set<string>();\r\n for (const table of database.tables) {\r\n const reference = { kind: 'table' as const, schemaName, name: table.name };\r\n if (table.strict) {\r\n require('supportsStrictTables', `table \"${table.name}\"`, reference);\r\n }\r\n if (table.withoutRowid) {\r\n require('supportsWithoutRowid', `table \"${table.name}\"`, reference);\r\n }\r\n for (const column of table.columns) {\r\n if (column.generated !== 'none') {\r\n require('supportsGeneratedColumns', `column \"${table.name}\".\"${column.name}\"`, {\r\n kind: 'column',\r\n schemaName,\r\n name: column.name,\r\n parentName: table.name,\r\n });\r\n }\r\n }\r\n if (table.kind === 'virtual') {\r\n if (!options.legacySchemaTableName) {\r\n require('supportsSqliteSchemaAlias', `virtual table \"${table.name}\" is recreated through INSERT INTO sqlite_schema`, reference);\r\n }\r\n const module =\r\n table.virtualModule === undefined ? undefined : toAsciiLowerCase(table.virtualModule);\r\n if (\r\n options.modules &&\r\n module !== undefined &&\r\n !options.modules.has(module) &&\r\n !missingModules.has(module)\r\n ) {\r\n missingModules.add(module);\r\n diagnostics.push({\r\n severity: 'error',\r\n code: 'virtual-table-module-unavailable',\r\n message: `Restore target has no \"${table.virtualModule}\" module, which virtual table \"${table.name}\" needs. The dump still restores — its schema row and shadow tables are plain SQL — but the table cannot be queried there until the module is loaded.`,\r\n objectReference: { kind: 'virtualTable', schemaName, name: table.name },\r\n });\r\n }\r\n }\r\n if (\r\n table.kind === 'system' &&\r\n /^sqlite_stat/.test(table.name) &&\r\n !options.legacySchemaTableName\r\n ) {\r\n require('supportsSqliteSchemaAlias', 'the statistics tables are recreated by ANALYZE sqlite_schema', reference);\r\n }\r\n }\r\n\r\n if (options.extendedInsert) {\r\n require('supportsMultiRowValues', 'dataExport.extendedInsert is enabled');\r\n }\r\n\r\n const customCollations = new Map<string, string>();\r\n for (const index of database.indexes) {\r\n for (const column of index.columns) {\r\n if (\r\n column.collation !== null &&\r\n !BUILT_IN_COLLATIONS.has(toAsciiUpperCase(column.collation))\r\n ) {\r\n customCollations.set(toAsciiUpperCase(column.collation), index.name);\r\n }\r\n }\r\n }\r\n for (const [collation, indexName] of customCollations) {\r\n diagnostics.push({\r\n severity: 'warning',\r\n code: 'custom-collation',\r\n message: `Index \"${indexName}\" uses the collation ${collation}, which is not built into SQLite. The restoring application must register it (sqlite3_create_collation) before the restore, or the index cannot be created.`,\r\n objectReference: { kind: 'index', schemaName, name: indexName },\r\n });\r\n }\r\n\r\n return diagnostics;\r\n}\r\n","import type { SqliteDiagnostic } from '../model/diagnostics.js';\r\n\r\n/**\r\n * Database state this package deliberately does not dump.\r\n *\r\n * Every one of these is either a property of the database *file* rather\r\n * than of its contents, or lives outside SQL entirely. Rather than silently\r\n * omitting them — which would make a dump look complete when it is not —\r\n * each is described here so `unsupportedFeatureDiagnostics()` can report\r\n * them, and `docs/known-limitations.md` can list them with the same wording.\r\n */\r\nexport const UNSUPPORTED_FEATURES: readonly {\r\n readonly code: string;\r\n readonly summary: string;\r\n readonly detail: string;\r\n}[] = [\r\n {\r\n code: 'file-settings-not-dumped',\r\n summary: 'file-level settings (page_size, auto_vacuum, journal_mode, encoding)',\r\n detail:\r\n 'These describe how the database file is laid out, not what it contains, and most can only be chosen before the first table is created. The native .dump does not carry them either. Set them on the target database before restoring if they matter; the dump restores correctly under any of them.',\r\n },\r\n {\r\n code: 'temp-and-attached-schemas-not-dumped',\r\n summary: 'the temp schema and attached databases',\r\n detail:\r\n 'A dump covers one schema — main by default. Temporary objects belong to one connection, and each attached database is a separate file; dump an attached database on its own by passing its name as schemaName.',\r\n },\r\n {\r\n code: 'application-functions-not-dumped',\r\n summary: 'application-defined functions, collations and loadable extensions',\r\n detail:\r\n 'User-defined SQL functions, collating sequences and virtual table modules are registered by the application (or loaded from a shared library), not stored in the database. The schema that uses them is dumped verbatim; the restoring application must register them first, or objects using them cannot be created or queried.',\r\n },\r\n {\r\n code: 'encryption-not-dumped',\r\n summary: 'encryption keys',\r\n detail:\r\n 'An encrypted database (SQLCipher, SEE) is dumped as plain SQL once it is opened with its key. The dump itself is not encrypted, and no key is ever written into it.',\r\n },\r\n];\r\n\r\n/** The {@link UNSUPPORTED_FEATURES} as `info` diagnostics, for a UI that lists what a dump does not include. */\r\nexport function unsupportedFeatureDiagnostics(): SqliteDiagnostic[] {\r\n return UNSUPPORTED_FEATURES.map(feature => ({\r\n severity: 'info',\r\n code: feature.code,\r\n message: `Not dumped: ${feature.summary}. ${feature.detail}`,\r\n }));\r\n}\r\n","import { acquireSqliteConnection, toNumber, toText } from '../connection/acquire.js';\r\nimport type { SqliteConnection, SqliteConnectionInput, SqliteRow } from '../connection/types.js';\r\nimport { checkTargetCompatibility } from '../compatibility/check.js';\r\nimport type { TargetCompatibilityOptions } from '../compatibility/check.js';\r\nimport type { SqliteDatabase } from '../model/database.js';\r\nimport type { SqliteDiagnostic } from '../model/diagnostics.js';\r\nimport { toAsciiLowerCase } from '../security/identifiers.js';\r\nimport { isAbortError } from '../utils/errors.js';\r\nimport { detectSqliteCapabilities } from '../version/capabilities.js';\r\nimport { detectSqliteVersion } from '../version/detect.js';\r\nimport type { SqliteCapabilities, SqliteVersion } from '../version/types.js';\r\n\r\nexport interface PreflightRestoreRequest {\r\n readonly connection: SqliteConnectionInput;\r\n /**\r\n * The model of the database the dump was taken from (from\r\n * `introspectSqlite`). With it, the report answers \"what does this dump\r\n * need that this target cannot do\"; without it, only \"what can this target\r\n * do\".\r\n */\r\n readonly database?: SqliteDatabase;\r\n readonly options?: TargetCompatibilityOptions & {\r\n /** The dump was rendered with `addDropStatements`, so existing objects are replaced rather than conflicting. */\r\n readonly addDropStatements?: boolean;\r\n };\r\n readonly signal?: AbortSignal;\r\n}\r\n\r\nexport interface PreflightRestoreReport {\r\n readonly version: SqliteVersion;\r\n readonly capabilities: SqliteCapabilities;\r\n /** `PRAGMA encoding` of the target. */\r\n readonly encoding: string;\r\n /** Whether the target enforces foreign keys (`PRAGMA foreign_keys`). */\r\n readonly foreignKeysEnabled: boolean;\r\n /** Whether the handle is already inside a transaction. `undefined` when the adapter cannot tell. */\r\n readonly inTransaction?: boolean;\r\n /** Whether the adapter can lift defensive mode for a dump that writes `sqlite_schema`. */\r\n readonly canDisableDefensiveMode: boolean;\r\n /** Virtual table modules the target has, when `PRAGMA module_list` is available. */\r\n readonly modules?: readonly string[];\r\n /** `PRAGMA compile_options` of the target, when readable. */\r\n readonly compileOptions?: readonly string[];\r\n /** Tables, views, indexes and triggers already present in the target's `main` schema. */\r\n readonly existingObjects: readonly { readonly type: string; readonly name: string }[];\r\n readonly diagnostics: readonly SqliteDiagnostic[];\r\n}\r\n\r\nasync function queryRows(\r\n connection: SqliteConnection,\r\n sql: string,\r\n signal?: AbortSignal,\r\n): Promise<readonly SqliteRow[] | undefined> {\r\n try {\r\n return (await connection.query<SqliteRow>({ sql }, signal)).rows;\r\n } catch (error) {\r\n if (isAbortError(error)) throw error;\r\n return undefined;\r\n }\r\n}\r\n\r\nfunction firstValue(rows: readonly SqliteRow[] | undefined): unknown {\r\n const first = rows?.[0];\r\n return first === undefined ? undefined : Object.values(first)[0];\r\n}\r\n\r\n/**\r\n * Inspects a restore target before anything is written to it.\r\n *\r\n * Turns a failure part-way through a restore — `table t already exists`,\r\n * `no such module: fts5`, a syntax error on a `STRICT` table — into an\r\n * up-front, actionable report. Never writes to the target.\r\n */\r\nexport async function preflightRestore(\r\n request: PreflightRestoreRequest,\r\n): Promise<PreflightRestoreReport> {\r\n const acquired = await acquireSqliteConnection(request.connection, request.signal);\r\n const connection = acquired.connection;\r\n const { signal } = request;\r\n try {\r\n const version = await detectSqliteVersion(connection, signal);\r\n const capabilities = detectSqliteCapabilities(version);\r\n const encoding =\r\n toText(firstValue(await queryRows(connection, 'PRAGMA encoding', signal))) ?? 'UTF-8';\r\n const foreignKeysEnabled =\r\n toNumber(firstValue(await queryRows(connection, 'PRAGMA foreign_keys', signal))) !== 0;\r\n const moduleRows = await queryRows(connection, 'SELECT name FROM pragma_module_list', signal);\r\n const optionRows = await queryRows(connection, 'PRAGMA compile_options', signal);\r\n const compileOptions = optionRows?.map(row => toText(Object.values(row)[0]) ?? '');\r\n const modules = moduleRows?.map(row => toText(row.name) ?? '').filter(name => name !== '');\r\n const existingRows =\r\n (await queryRows(\r\n connection,\r\n \"SELECT type, name FROM main.sqlite_master WHERE sql IS NOT NULL AND name NOT LIKE 'sqlite\\\\_%' ESCAPE '\\\\' ORDER BY rowid\",\r\n signal,\r\n )) ?? [];\r\n const existingObjects = existingRows.map(row => ({\r\n type: toText(row.type) ?? '',\r\n name: toText(row.name) ?? '',\r\n }));\r\n const inTransaction = connection.isInTransaction?.();\r\n\r\n const diagnostics: SqliteDiagnostic[] = [];\r\n if (inTransaction) {\r\n diagnostics.push({\r\n severity: 'warning',\r\n code: 'target-in-transaction',\r\n message:\r\n 'The target handle is already inside a transaction. A full dump\\'s own BEGIN TRANSACTION will fail; commit first, or restore with transaction: \"wrap\".',\r\n });\r\n }\r\n\r\n const database = request.database;\r\n if (database) {\r\n diagnostics.push(\r\n ...checkTargetCompatibility(database, capabilities, {\r\n ...request.options,\r\n ...(modules === undefined ? {} : { modules: new Set(modules.map(toAsciiLowerCase)) }),\r\n }),\r\n );\r\n\r\n const hasVirtualTables = database.tables.some(table => table.kind === 'virtual');\r\n if (hasVirtualTables && !connection.setDefensive) {\r\n diagnostics.push({\r\n severity: 'warning',\r\n code: 'defensive-mode-not-controllable',\r\n message:\r\n 'This dump recreates virtual tables by writing sqlite_schema directly, which SQLITE_DBCONFIG_DEFENSIVE forbids, and this adapter cannot turn defensive mode off. The restore succeeds only if the connection is not in defensive mode.',\r\n });\r\n }\r\n\r\n const hasStat4 = database.tables.some(table => table.name === 'sqlite_stat4');\r\n if (hasStat4 && compileOptions && !compileOptions.includes('ENABLE_STAT4')) {\r\n diagnostics.push({\r\n severity: 'error',\r\n code: 'statistics-table-unsupported',\r\n message:\r\n \"The source database has a sqlite_stat4 table, and the target SQLite is not built with SQLITE_ENABLE_STAT4, so ANALYZE there does not create it and the dump's INSERT INTO sqlite_stat4 fails. The native .dump of such a database fails the same way. Dump with objectKinds.includeSystemTables: false, or drop sqlite_stat4 from the source copy first.\",\r\n });\r\n }\r\n\r\n if (database.encoding.toUpperCase() !== encoding.toUpperCase()) {\r\n diagnostics.push({\r\n severity: 'info',\r\n code: 'encoding-differs',\r\n message: `The source database is ${database.encoding} and the target is ${encoding}. Text is converted between the two on restore, which is lossless for valid text.`,\r\n });\r\n }\r\n\r\n if (!request.options?.addDropStatements) {\r\n const existing = new Map(\r\n existingObjects.map(object => [toAsciiLowerCase(object.name), object]),\r\n );\r\n const created = [\r\n ...database.tables.filter(table => table.kind !== 'system').map(table => table.name),\r\n ...database.views.map(view => view.name),\r\n ...database.indexes.filter(index => index.sql !== null).map(index => index.name),\r\n ...database.triggers.map(trigger => trigger.name),\r\n ];\r\n for (const name of created) {\r\n const conflict = existing.get(toAsciiLowerCase(name));\r\n if (conflict) {\r\n diagnostics.push({\r\n severity: 'error',\r\n code: 'object-already-exists',\r\n message: `The target already has a ${conflict.type} named \"${conflict.name}\", so the dump's CREATE for it will fail. Restore into an empty database, drop it first, or render the dump with addDropStatements.`,\r\n objectReference: { kind: 'table', schemaName: 'main', name: conflict.name },\r\n });\r\n }\r\n }\r\n }\r\n }\r\n\r\n return {\r\n version,\r\n capabilities,\r\n encoding,\r\n foreignKeysEnabled,\r\n ...(inTransaction === undefined ? {} : { inTransaction }),\r\n canDisableDefensiveMode: typeof connection.setDefensive === 'function',\r\n ...(modules === undefined ? {} : { modules }),\r\n ...(compileOptions === undefined ? {} : { compileOptions }),\r\n existingObjects,\r\n diagnostics,\r\n };\r\n } finally {\r\n await acquired.release();\r\n }\r\n}\r\n","import type { SqliteErrorInfo } from '../connection/types.js';\r\nimport { SqliteDumperError } from '../utils/errors.js';\r\nimport type { StatementSourceLocation } from './location.js';\r\n\r\n/** Common base for every error {@link restoreSqlDump} (or its parser) throws intentionally. */\r\nexport class RestoreError extends SqliteDumperError {}\r\n\r\n/**\r\n * The input could not be split into statements correctly.\r\n *\r\n * Always fatal: unlike a statement that fails when executed, a parse failure\r\n * means the statement boundaries themselves are not trustworthy, so nothing\r\n * after the failure point can be safely executed either.\r\n */\r\nexport class SqlParseError extends RestoreError {\r\n readonly line: number;\r\n\r\n constructor(code: string, message: string, line: number, options?: { cause?: unknown }) {\r\n super(code, message, options);\r\n this.name = 'SqlParseError';\r\n this.line = line;\r\n }\r\n}\r\n\r\n/**\r\n * The input ended while a quoted token — a string, a `\"`/`` ` ``/`[...]`\r\n * identifier — was still open. The script is structurally incomplete (most\r\n * often a truncated file) and cannot be split into valid statements.\r\n *\r\n * An unterminated `/*` comment is *not* reported: SQLite itself accepts a\r\n * block comment that runs to the end of the input.\r\n */\r\nexport class MalformedSqlDumpError extends SqlParseError {\r\n readonly openConstruct: string;\r\n\r\n constructor(openConstruct: string, line: number) {\r\n super(\r\n 'malformed-sql-dump',\r\n `Unterminated ${openConstruct} starting at line ${line}: the input ends before it is closed`,\r\n line,\r\n );\r\n this.name = 'MalformedSqlDumpError';\r\n this.openConstruct = openConstruct;\r\n }\r\n}\r\n\r\n/**\r\n * One statement's accumulated text exceeded\r\n * {@link SqlStatementParserOptions.maxStatementBytes} before it was\r\n * complete.\r\n *\r\n * A statement must be sent to SQLite whole, so this bounds how much of a\r\n * pathological input — a truncated dump, or an unterminated `CREATE TRIGGER`\r\n * that swallows the rest of the file — the parser will buffer before giving\r\n * up, instead of growing without limit.\r\n */\r\nexport class StatementTooLargeError extends SqlParseError {\r\n readonly maxStatementBytes: number;\r\n\r\n constructor(maxStatementBytes: number, line: number) {\r\n super(\r\n 'statement-too-large',\r\n `Statement starting near line ${line} exceeds the configured limit of ${maxStatementBytes} bytes without being complete; increase options.maxStatementBytes if this statement is genuinely intended to be this large, or check for a CREATE TRIGGER missing its END`,\r\n line,\r\n );\r\n this.name = 'StatementTooLargeError';\r\n this.maxStatementBytes = maxStatementBytes;\r\n }\r\n}\r\n\r\n/**\r\n * A `sqlite3` shell dot-command was found that would change what the script\r\n * does to the database.\r\n *\r\n * The shell executes lines beginning with `.` itself (`.read`, `.import`,\r\n * `.open`, `.load`, `.shell`, ...) before anything reaches SQLite. Commands\r\n * that only affect the shell's own presentation (`.mode`, `.headers`,\r\n * `.print`, ...) are skipped with a warning; the rest are refused with a\r\n * precise diagnostic rather than being silently ignored, which would corrupt\r\n * the restore — a `.read` that never runs leaves the referenced file's\r\n * objects missing, and an `.import` that never runs leaves a table empty.\r\n */\r\nexport class UnsupportedClientCommandError extends SqlParseError {\r\n readonly command: string;\r\n\r\n constructor(command: string, line: number) {\r\n super(\r\n 'unsupported-client-command',\r\n `Unsupported sqlite3 shell command \".${command}\" on line ${line}: dbgate-sqlite-dumper executes SQL statements and does not implement shell dot-commands that change the database. Run this script through the sqlite3 shell, or remove the command.`,\r\n line,\r\n );\r\n this.name = 'UnsupportedClientCommandError';\r\n this.command = command;\r\n }\r\n}\r\n\r\n/**\r\n * A statement holds bytes that are not valid UTF-8 outside any string\r\n * literal, so it cannot be handed to SQLite as text without corrupting them.\r\n *\r\n * Invalid UTF-8 *inside* a string literal — which the native `.dump` writes\r\n * whenever a `TEXT` value holds such bytes — is handled transparently, by\r\n * rewriting the literal into the equivalent `CAST(X'...' AS TEXT)`. Reaching\r\n * this error means the bytes are in an identifier or keyword position.\r\n */\r\nexport class InvalidTextEncodingError extends SqlParseError {\r\n constructor(message: string, line: number) {\r\n super('invalid-text-encoding', `${message} (near line ${line})`, line);\r\n this.name = 'InvalidTextEncodingError';\r\n }\r\n}\r\n\r\n/**\r\n * A statement parsed successfully but failed when executed.\r\n *\r\n * Unlike a parse error this is scoped to one statement: with\r\n * `stopOnError: false`, restoration continues with the next one, and this\r\n * error's data — never the raw driver error, which can echo back parts of\r\n * the failing statement — is what is recorded in\r\n * {@link SqlDumpRestoreResult.errors}.\r\n */\r\nexport class RestoreExecutionError extends RestoreError {\r\n readonly statementIndex: number;\r\n readonly location: StatementSourceLocation;\r\n readonly sqlPreview: string;\r\n readonly sqliteError?: SqliteErrorInfo;\r\n\r\n constructor(\r\n statementIndex: number,\r\n location: StatementSourceLocation,\r\n sqlPreview: string,\r\n message: string,\r\n sqliteError?: SqliteErrorInfo,\r\n options?: { cause?: unknown },\r\n ) {\r\n super('restore-execution-failed', message, options);\r\n this.name = 'RestoreExecutionError';\r\n this.statementIndex = statementIndex;\r\n this.location = location;\r\n this.sqlPreview = sqlPreview;\r\n if (sqliteError) {\r\n this.sqliteError = sqliteError;\r\n }\r\n }\r\n}\r\n","import { toAsciiLowerCase, toAsciiUpperCase } from '../security/identifiers.js';\r\nimport { isIdentifierCharCode } from './complete.js';\r\n\r\ninterface LeadingToken {\r\n readonly kind: 'word' | 'quoted' | 'string' | 'punct' | 'number';\r\n /** For `word`: the text; for `quoted`/`string`: the unquoted value; else the character(s). */\r\n readonly value: string;\r\n}\r\n\r\n/**\r\n * Reads the first `limit` tokens of a statement, skipping whitespace and\r\n * comments. Enough to recognize what a statement *is* without parsing it.\r\n */\r\nfunction leadingTokens(sql: string, limit: number): LeadingToken[] {\r\n const tokens: LeadingToken[] = [];\r\n let index = 0;\r\n const length = sql.length;\r\n while (index < length && tokens.length < limit) {\r\n const character = sql[index] as string;\r\n const code = sql.charCodeAt(index);\r\n if (/\\s/.test(character) || character === '\\uFEFF') {\r\n index++;\r\n continue;\r\n }\r\n if (character === '-' && sql[index + 1] === '-') {\r\n const end = sql.indexOf('\\n', index);\r\n index = end === -1 ? length : end + 1;\r\n continue;\r\n }\r\n if (character === '/' && sql[index + 1] === '*') {\r\n const end = sql.indexOf('*/', index + 2);\r\n index = end === -1 ? length : end + 2;\r\n continue;\r\n }\r\n if (character === '\"' || character === '`' || character === \"'\" || character === '[') {\r\n const close = character === '[' ? ']' : character;\r\n let value = '';\r\n index++;\r\n while (index < length) {\r\n if (sql[index] === close) {\r\n if (close !== ']' && sql[index + 1] === close) {\r\n value += close;\r\n index += 2;\r\n continue;\r\n }\r\n index++;\r\n break;\r\n }\r\n value += sql[index];\r\n index++;\r\n }\r\n tokens.push({ kind: character === \"'\" ? 'string' : 'quoted', value });\r\n continue;\r\n }\r\n if (code >= 0x30 && code <= 0x39) {\r\n let end = index + 1;\r\n while (end < length && /[0-9A-Za-z_.+-]/.test(sql[end] as string)) {\r\n end++;\r\n }\r\n tokens.push({ kind: 'number', value: sql.slice(index, end) });\r\n index = end;\r\n continue;\r\n }\r\n if (isIdentifierCharCode(code)) {\r\n let end = index + 1;\r\n while (end < length && isIdentifierCharCode(sql.charCodeAt(end))) {\r\n end++;\r\n }\r\n tokens.push({ kind: 'word', value: sql.slice(index, end) });\r\n index = end;\r\n continue;\r\n }\r\n tokens.push({ kind: 'punct', value: character });\r\n index++;\r\n }\r\n return tokens;\r\n}\r\n\r\n/** What a statement is, as far as restore bookkeeping needs to know. */\r\nexport interface StatementInfo {\r\n /** The statement's first keyword, upper-cased: `CREATE`, `INSERT`, `PRAGMA`, `BEGIN`, ... */\r\n readonly verb: string;\r\n /** For `CREATE`: the object kind (`TABLE`, `INDEX`, `VIEW`, `TRIGGER`, `VIRTUAL TABLE`). */\r\n readonly objectKind?: string;\r\n /** The object the statement creates, fills or changes, when recognizable. */\r\n readonly objectName?: string;\r\n /** For `PRAGMA`: the pragma name, lower-cased, without a schema prefix. */\r\n readonly pragmaName?: string;\r\n /** For `PRAGMA x = value` / `PRAGMA x(value)`: the value as written, unquoted. */\r\n readonly pragmaValue?: string;\r\n /**\r\n * `begin`, `commit`, `rollback`, `savepoint`, `release` or\r\n * `rollback-to-savepoint` for transaction-control statements.\r\n */\r\n readonly transactionControl?:\r\n 'begin' | 'commit' | 'rollback' | 'rollback-to-savepoint' | 'savepoint' | 'release';\r\n}\r\n\r\nfunction nameToken(token: LeadingToken | undefined): string | undefined {\r\n if (!token) {\r\n return undefined;\r\n }\r\n return token.kind === 'word' || token.kind === 'quoted' || token.kind === 'string'\r\n ? token.value\r\n : undefined;\r\n}\r\n\r\n/** Skips an optional `schema.` qualifier, returning the unqualified name and the next position. */\r\nfunction qualifiedName(\r\n tokens: readonly LeadingToken[],\r\n position: number,\r\n): { name?: string; next: number } {\r\n const first = nameToken(tokens[position]);\r\n if (first === undefined) {\r\n return { next: position };\r\n }\r\n if (tokens[position + 1]?.kind === 'punct' && tokens[position + 1]?.value === '.') {\r\n const second = nameToken(tokens[position + 2]);\r\n return second === undefined\r\n ? { name: first, next: position + 1 }\r\n : { name: second, next: position + 3 };\r\n }\r\n return { name: first, next: position + 1 };\r\n}\r\n\r\nfunction isWord(token: LeadingToken | undefined, word: string): boolean {\r\n return token?.kind === 'word' && toAsciiUpperCase(token.value) === word;\r\n}\r\n\r\n/**\r\n * Classifies a statement from its leading tokens.\r\n *\r\n * Used for restore progress (`currentObject`), for following the script's\r\n * own transaction control, and for noticing the session-level pragmas a dump\r\n * changes (`foreign_keys`, `writable_schema`) so they can be put back if the\r\n * restore stops early.\r\n */\r\nexport function describeStatement(sql: string): StatementInfo {\r\n const tokens = leadingTokens(sql, 12);\r\n const first = tokens[0];\r\n if (!first || first.kind !== 'word') {\r\n return { verb: '' };\r\n }\r\n const verb = toAsciiUpperCase(first.value);\r\n\r\n switch (verb) {\r\n case 'BEGIN':\r\n return { verb, transactionControl: 'begin' };\r\n case 'COMMIT':\r\n case 'END':\r\n return { verb, transactionControl: 'commit' };\r\n case 'ROLLBACK': {\r\n // ROLLBACK [TRANSACTION] TO [SAVEPOINT] name only unwinds to a savepoint.\r\n const toPosition = isWord(tokens[1], 'TRANSACTION') ? 2 : 1;\r\n return isWord(tokens[toPosition], 'TO')\r\n ? { verb, transactionControl: 'rollback-to-savepoint' }\r\n : { verb, transactionControl: 'rollback' };\r\n }\r\n case 'SAVEPOINT':\r\n return { verb, transactionControl: 'savepoint' };\r\n case 'RELEASE':\r\n return { verb, transactionControl: 'release' };\r\n case 'PRAGMA': {\r\n const { name, next } = qualifiedName(tokens, 1);\r\n if (name === undefined) {\r\n return { verb };\r\n }\r\n const pragmaName = toAsciiLowerCase(name);\r\n const operator = tokens[next];\r\n if (operator?.kind === 'punct' && (operator.value === '=' || operator.value === '(')) {\r\n const valueToken = tokens[next + 1];\r\n let value = valueToken?.value;\r\n if (\r\n valueToken?.kind === 'punct' &&\r\n (valueToken.value === '-' || valueToken.value === '+')\r\n ) {\r\n value = `${valueToken.value}${tokens[next + 2]?.value ?? ''}`;\r\n }\r\n return value === undefined\r\n ? { verb, pragmaName }\r\n : { verb, pragmaName, pragmaValue: value };\r\n }\r\n return { verb, pragmaName };\r\n }\r\n case 'INSERT':\r\n case 'REPLACE': {\r\n let position = 1;\r\n if (verb === 'INSERT' && isWord(tokens[1], 'OR')) {\r\n position = 3;\r\n }\r\n if (isWord(tokens[position], 'INTO')) {\r\n position++;\r\n }\r\n const { name } = qualifiedName(tokens, position);\r\n return name === undefined ? { verb } : { verb, objectName: name };\r\n }\r\n case 'DELETE': {\r\n const position = isWord(tokens[1], 'FROM') ? 2 : 1;\r\n const { name } = qualifiedName(tokens, position);\r\n return name === undefined ? { verb } : { verb, objectName: name };\r\n }\r\n case 'UPDATE':\r\n case 'ANALYZE':\r\n case 'DROP': {\r\n let position = 1;\r\n let objectKind: string | undefined;\r\n if (verb === 'DROP' && tokens[1]?.kind === 'word') {\r\n objectKind = toAsciiUpperCase(tokens[1].value);\r\n position = 2;\r\n if (isWord(tokens[2], 'IF') && isWord(tokens[3], 'EXISTS')) {\r\n position = 4;\r\n }\r\n }\r\n const { name } = qualifiedName(tokens, position);\r\n return {\r\n verb,\r\n ...(objectKind === undefined ? {} : { objectKind }),\r\n ...(name === undefined ? {} : { objectName: name }),\r\n };\r\n }\r\n case 'CREATE': {\r\n let position = 1;\r\n while (\r\n isWord(tokens[position], 'TEMP') ||\r\n isWord(tokens[position], 'TEMPORARY') ||\r\n isWord(tokens[position], 'UNIQUE')\r\n ) {\r\n position++;\r\n }\r\n let objectKind =\r\n tokens[position]?.kind === 'word' ? toAsciiUpperCase(tokens[position]!.value) : '';\r\n position++;\r\n if (objectKind === 'VIRTUAL' && isWord(tokens[position], 'TABLE')) {\r\n objectKind = 'VIRTUAL TABLE';\r\n position++;\r\n }\r\n if (isWord(tokens[position], 'IF') && isWord(tokens[position + 1], 'NOT')) {\r\n position += 3;\r\n }\r\n const { name } = qualifiedName(tokens, position);\r\n return {\r\n verb,\r\n ...(objectKind === '' ? {} : { objectKind }),\r\n ...(name === undefined ? {} : { objectName: name }),\r\n };\r\n }\r\n default:\r\n return { verb };\r\n }\r\n}\r\n","import { isUtf8 } from 'node:buffer';\r\nimport { InvalidTextEncodingError } from './errors.js';\r\n\r\n/**\r\n * Converts a statement's bytes into text SQLite can be handed, preserving\r\n * every byte.\r\n *\r\n * SQLite does not validate the encoding of the text it stores, and the\r\n * native `.dump` writes a `TEXT` value's bytes exactly as stored — so a value\r\n * holding bytes that are not valid UTF-8 appears in the dump as a string\r\n * literal that is not valid UTF-8 either. The `sqlite3` shell passes those\r\n * bytes straight to `sqlite3_prepare()`, which stores them unchanged. A\r\n * JavaScript driver cannot: its statement text is a JavaScript string, and\r\n * every invalid sequence would become U+FFFD on the way in.\r\n *\r\n * So a literal that is not valid UTF-8 is rewritten into an expression that\r\n * yields the identical bytes as text, written entirely in ASCII:\r\n *\r\n * ```sql\r\n * 'caf\\xE9' → (CAST(X'636166e9' AS TEXT))\r\n * ```\r\n *\r\n * In a UTF-8 database (every database the native `.dump` can reproduce\r\n * exactly) that is byte-for-byte the value the shell would have stored.\r\n * Invalid bytes inside a comment are dropped along with the comment; invalid\r\n * bytes anywhere else — in an identifier or keyword position — cannot be\r\n * represented and raise {@link InvalidTextEncodingError}.\r\n *\r\n * `statement` is a byte string: one code unit per byte, as `latin1` decodes\r\n * it. Returns the statement as ordinary text, plus how many literals were\r\n * rewritten.\r\n */\r\nexport function decodeStatementBytes(\r\n statement: string,\r\n startLine: number,\r\n): { sql: string; literalsRewritten: number } {\r\n const bytes = Buffer.from(statement, 'latin1');\r\n if (isUtf8(bytes)) {\r\n return { sql: bytes.toString('utf8'), literalsRewritten: 0 };\r\n }\r\n\r\n let output = '';\r\n let literalsRewritten = 0;\r\n let line = startLine;\r\n let index = 0;\r\n const length = statement.length;\r\n\r\n const appendPlain = (segment: string): void => {\r\n const segmentBytes = Buffer.from(segment, 'latin1');\r\n if (!isUtf8(segmentBytes)) {\r\n throw new InvalidTextEncodingError(\r\n 'The statement contains bytes that are not valid UTF-8 outside any string literal, so it cannot be executed as text without corrupting them',\r\n line,\r\n );\r\n }\r\n output += segmentBytes.toString('utf8');\r\n };\r\n\r\n let plainStart = 0;\r\n while (index < length) {\r\n const character = statement[index] as string;\r\n if (character === '\\n') {\r\n line++;\r\n index++;\r\n continue;\r\n }\r\n if (character === \"'\") {\r\n appendPlain(statement.slice(plainStart, index));\r\n let end = index + 1;\r\n for (;;) {\r\n const close = statement.indexOf(\"'\", end);\r\n if (close === -1) {\r\n end = length;\r\n break;\r\n }\r\n if (statement[close + 1] === \"'\") {\r\n end = close + 2;\r\n continue;\r\n }\r\n end = close + 1;\r\n break;\r\n }\r\n const literal = statement.slice(index, end);\r\n const literalBytes = Buffer.from(literal, 'latin1');\r\n if (isUtf8(literalBytes)) {\r\n output += literalBytes.toString('utf8');\r\n } else {\r\n const value = literal.slice(1, literal.endsWith(\"'\") ? -1 : undefined).replace(/''/g, \"'\");\r\n output += `(CAST(X'${Buffer.from(value, 'latin1').toString('hex')}' AS TEXT))`;\r\n literalsRewritten++;\r\n }\r\n for (let scan = index; scan < end; scan++) {\r\n if (statement[scan] === '\\n') line++;\r\n }\r\n index = end;\r\n plainStart = end;\r\n continue;\r\n }\r\n if (character === '\"' || character === '`' || character === '[') {\r\n const close = character === '[' ? ']' : character;\r\n let end = statement.indexOf(close, index + 1);\r\n end = end === -1 ? length : end + 1;\r\n index = end;\r\n continue;\r\n }\r\n if (character === '-' && statement[index + 1] === '-') {\r\n appendPlain(statement.slice(plainStart, index));\r\n const end = statement.indexOf('\\n', index);\r\n const commentEnd = end === -1 ? length : end;\r\n const comment = statement.slice(index, commentEnd);\r\n output += isUtf8(Buffer.from(comment, 'latin1'))\r\n ? Buffer.from(comment, 'latin1').toString('utf8')\r\n : '--';\r\n index = commentEnd;\r\n plainStart = commentEnd;\r\n continue;\r\n }\r\n if (character === '/' && statement[index + 1] === '*') {\r\n appendPlain(statement.slice(plainStart, index));\r\n const end = statement.indexOf('*/', index + 2);\r\n const commentEnd = end === -1 ? length : end + 2;\r\n const comment = statement.slice(index, commentEnd);\r\n const commentBytes = Buffer.from(comment, 'latin1');\r\n output += isUtf8(commentBytes) ? commentBytes.toString('utf8') : ' ';\r\n for (let scan = index; scan < commentEnd; scan++) {\r\n if (statement[scan] === '\\n') line++;\r\n }\r\n index = commentEnd;\r\n plainStart = commentEnd;\r\n continue;\r\n }\r\n index++;\r\n }\r\n appendPlain(statement.slice(plainStart));\r\n return { sql: output, literalsRewritten };\r\n}\r\n","import { throwIfAborted } from '../utils/errors.js';\r\nimport {\r\n classifyWord,\r\n CompleteToken,\r\n completeTransition,\r\n isIdentifierCharCode,\r\n} from './complete.js';\r\nimport {\r\n MalformedSqlDumpError,\r\n StatementTooLargeError,\r\n UnsupportedClientCommandError,\r\n} from './errors.js';\r\nimport type { StatementSourceLocation } from './location.js';\r\nimport type { SqlDumpSource } from './source.js';\r\nimport { describeStatement } from './statementInfo.js';\r\nimport type { StatementInfo } from './statementInfo.js';\r\nimport { decodeStatementBytes } from './textEncoding.js';\r\n\r\nconst DEFAULT_MAX_STATEMENT_BYTES = 256 * 1024 * 1024;\r\n\r\n/**\r\n * Longest line examined as a possible `GO` / `/` terminator line. A real one\r\n * is a few bytes; the cap keeps the cross-chunk lookahead bounded on hostile\r\n * input (a line that long is simply treated as ordinary SQL).\r\n */\r\nconst MAX_TERMINATOR_LINE_BYTES = 64 * 1024;\r\n\r\n/** Longest dot-command line kept; the rest of an absurdly long one is ignored. */\r\nconst MAX_DOT_COMMAND_BYTES = 64 * 1024;\r\n\r\n/**\r\n * Shell dot-commands that only affect the `sqlite3` shell's own presentation\r\n * or diagnostics — never what the script does to the database — and are\r\n * therefore safe to skip. Anything else is refused.\r\n */\r\nconst PRESENTATIONAL_DOT_COMMANDS: ReadonlySet<string> = new Set([\r\n 'bail',\r\n 'binary',\r\n 'changes',\r\n 'databases',\r\n 'dbinfo',\r\n 'echo',\r\n 'eqp',\r\n 'explain',\r\n 'fullschema',\r\n 'headers',\r\n 'header',\r\n 'help',\r\n 'indexes',\r\n 'indices',\r\n 'log',\r\n 'mode',\r\n 'nullvalue',\r\n 'once',\r\n 'output',\r\n 'print',\r\n 'progress',\r\n 'prompt',\r\n 'scanstats',\r\n 'schema',\r\n 'separator',\r\n 'show',\r\n 'stats',\r\n 'tables',\r\n 'timeout',\r\n 'timer',\r\n 'trace',\r\n 'width',\r\n]);\r\n\r\n/** Dot-commands that end the shell's input. */\r\nconst EXIT_DOT_COMMANDS: ReadonlySet<string> = new Set(['exit', 'quit']);\r\n\r\n/**\r\n * What to do with a `sqlite3` shell dot-command (`.mode csv`, `.read x.sql`).\r\n *\r\n * - `'skip-presentational'` (default) skips commands that only affect the\r\n * shell's output (`.mode`, `.headers`, `.print`, ...), reporting each, and\r\n * refuses every command that would change what the script does to the\r\n * database (`.read`, `.import`, `.open`, `.load`, ...).\r\n * - `'error'` refuses every dot-command.\r\n *\r\n * `.quit` and `.exit` end the input in both modes, exactly as in the shell.\r\n */\r\nexport type DotCommandPolicy = 'skip-presentational' | 'error';\r\n\r\nexport interface SqlStatementParserOptions {\r\n /**\r\n * Upper bound, in bytes, on one statement's accumulated text.\r\n *\r\n * Guards against unbounded memory growth from a truncated dump or a\r\n * `CREATE TRIGGER` whose `END` is missing. Defaults to 256 MiB — far\r\n * larger than any statement a real dump contains, while still bounded.\r\n */\r\n readonly maxStatementBytes?: number;\r\n readonly dotCommands?: DotCommandPolicy;\r\n}\r\n\r\nexport interface ParsedStatement {\r\n readonly statementIndex: number;\r\n /**\r\n * Statement text, without its terminating `;` and without the whitespace\r\n * and comments that preceded it. Never empty.\r\n */\r\n readonly sql: string;\r\n readonly location: StatementSourceLocation;\r\n /** What the statement is, from its leading tokens. */\r\n readonly info: StatementInfo;\r\n /**\r\n * The object the restore is currently working on: this statement's own\r\n * object when it names one (`CREATE TABLE t`, `INSERT INTO t`), else the\r\n * last one seen. Reported through restore progress.\r\n */\r\n readonly currentObject?: string;\r\n /** Bytes of source the parser had consumed when this statement was emitted. */\r\n readonly bytesConsumed: number;\r\n /**\r\n * How many string literals holding bytes that are not valid UTF-8 were\r\n * rewritten to `CAST(X'...' AS TEXT)` so the statement could be sent as\r\n * text. See `textEncoding.ts`.\r\n */\r\n readonly textLiteralsRewritten: number;\r\n}\r\n\r\n/** A dot-command the parser skipped under `'skip-presentational'`. */\r\nexport interface SkippedDotCommand {\r\n readonly command: string;\r\n readonly line: number;\r\n}\r\n\r\ntype LexState =\r\n | 'normal'\r\n | 'singleQuote'\r\n | 'doubleQuote'\r\n | 'backtick'\r\n | 'bracket'\r\n | 'blockComment'\r\n | 'lineComment'\r\n | 'dotCommand'\r\n | 'hashComment'\r\n | 'stopped';\r\n\r\nconst OPEN_CONSTRUCT_NAME: Partial<Record<LexState, string>> = {\r\n singleQuote: \"string literal ('...')\",\r\n doubleQuote: 'double-quoted identifier (\"...\")',\r\n backtick: 'backtick-quoted identifier (`...`)',\r\n bracket: 'bracket-quoted identifier ([...])',\r\n};\r\n\r\nconst CLOSING_CHARACTER: Partial<Record<LexState, string>> = {\r\n singleQuote: \"'\",\r\n doubleQuote: '\"',\r\n backtick: '`',\r\n bracket: ']',\r\n};\r\n\r\n/** Whitespace as `sqlite3_complete()` classifies it. */\r\nfunction isCompleteWhitespace(character: string): boolean {\r\n return (\r\n character === ' ' ||\r\n character === '\\n' ||\r\n character === '\\t' ||\r\n character === '\\r' ||\r\n character === '\\f'\r\n );\r\n}\r\n\r\n/** C `isspace()` in the C locale, which the shell's line scanner uses. */\r\nfunction isCSpace(character: string): boolean {\r\n return isCompleteWhitespace(character) || character === '\\v';\r\n}\r\n\r\n/**\r\n * `quickscan(line) == QSS_Start` from `shell.c`: the rest of a line holds\r\n * only whitespace and complete comments — no SQL, no `;`, no unterminated\r\n * comment or quote.\r\n */\r\nfunction isPlainWhiteLine(text: string): boolean {\r\n let index = 0;\r\n while (index < text.length) {\r\n const character = text[index] as string;\r\n if (isCSpace(character)) {\r\n index++;\r\n continue;\r\n }\r\n if (character === '-' && text[index + 1] === '-') {\r\n return true;\r\n }\r\n if (character === '/' && text[index + 1] === '*') {\r\n const end = text.indexOf('*/', index + 2);\r\n if (end === -1) {\r\n return false;\r\n }\r\n index = end + 2;\r\n continue;\r\n }\r\n return false;\r\n }\r\n return true;\r\n}\r\n\r\n/**\r\n * `line_is_command_terminator()` from `shell.c`: a line holding only `/`\r\n * (Oracle's convention) or `GO` (SQL Server's), optionally surrounded by\r\n * whitespace and comments, ends the pending statement.\r\n */\r\nfunction isTerminatorLine(line: string): boolean {\r\n let index = 0;\r\n while (index < line.length && isCSpace(line[index] as string)) {\r\n index++;\r\n }\r\n if (line[index] === '/') {\r\n return isPlainWhiteLine(line.slice(index + 1));\r\n }\r\n if ((line[index] ?? '').toLowerCase() === 'g' && (line[index + 1] ?? '').toLowerCase() === 'o') {\r\n return isPlainWhiteLine(line.slice(index + 2));\r\n }\r\n return false;\r\n}\r\n\r\n/** Whether the start of a (possibly incomplete) line could still turn out to be a terminator line. */\r\nfunction couldBeTerminatorLine(partial: string): boolean {\r\n let index = 0;\r\n while (index < partial.length && isCSpace(partial[index] as string)) {\r\n index++;\r\n }\r\n if (index >= partial.length) {\r\n return true;\r\n }\r\n const first = (partial[index] as string).toLowerCase();\r\n if (first === '/') {\r\n return true;\r\n }\r\n return (\r\n first === 'g' &&\r\n (index + 1 >= partial.length || (partial[index + 1] as string).toLowerCase() === 'o')\r\n );\r\n}\r\n\r\n/**\r\n * An incremental splitter for `sqlite3` scripts that decides statement\r\n * boundaries exactly where the `sqlite3` shell does.\r\n *\r\n * Two layers, both ported from SQLite's own sources:\r\n *\r\n * - **Tokens and completeness** follow `sqlite3_complete()`\r\n * (see `complete.ts`): `'...'` strings, `\"...\"`, `` `...` `` and `[...]`\r\n * identifiers, `--` and (non-nesting) `/* *\\/` comments, and the state\r\n * machine that keeps the `;`-terminated statements inside a\r\n * `CREATE TRIGGER ... BEGIN ... END;` body in one statement.\r\n * - **Lines** follow the shell's `process_input()`: a line starting with `.`\r\n * at column 0, when no SQL is pending, is a dot-command; a line starting\r\n * with `#` there is a comment; a line holding only `GO` or `/` ends the\r\n * pending statement; and a carriage return immediately before a newline is\r\n * dropped, exactly as the shell's line reader drops it.\r\n *\r\n * The parser runs on **bytes** — chunks are byte strings, one code unit per\r\n * byte, as `latin1` decodes them — because a dump is not necessarily valid\r\n * UTF-8, and decoding up front would replace invalid bytes with U+FFFD\r\n * before the parser ever saw them. Every character it reacts to is ASCII,\r\n * and no byte of a multi-byte UTF-8 sequence can be mistaken for one.\r\n *\r\n * Correctness across chunk boundaries is not assumed: anything whose\r\n * meaning depends on what follows — a `-` or `/` that may open a comment, a\r\n * `*` that may close one, a `\\r` that may precede `\\n`, the start of a line\r\n * that may be a `GO` line — is carried to the next chunk.\r\n *\r\n * Memory is bounded by one statement: only the current statement's text and\r\n * a few carried bytes are held, and `maxStatementBytes` fails fast on a\r\n * pathological input rather than growing without limit.\r\n */\r\nexport class SqlStatementParser {\r\n private readonly maxStatementBytes: number;\r\n private readonly dotCommandPolicy: DotCommandPolicy;\r\n\r\n private lex: LexState = 'normal';\r\n private completeState = 0;\r\n /** Length and (lower-cased, capped) prefix of the identifier being scanned. */\r\n private wordLength = 0;\r\n private wordPrefix = '';\r\n /** In a block comment: whether the previous byte was `*`. */\r\n private blockStar = false;\r\n private openLine = 1;\r\n\r\n private carry = '';\r\n private parts: string[] = [];\r\n private partsBytes = 0;\r\n /** True once the pending statement has content other than whitespace and comments. */\r\n private hasContent = false;\r\n private statementStartLine = 1;\r\n\r\n private line = 1;\r\n private atLineStart = true;\r\n private firstChunk = true;\r\n private dotText = '';\r\n private dotLine = 1;\r\n\r\n private nextStatementIndex = 0;\r\n private finished = false;\r\n private bytesConsumedTotal = 0;\r\n private lastObject: string | undefined;\r\n private readonly skipped: SkippedDotCommand[] = [];\r\n\r\n constructor(options?: SqlStatementParserOptions) {\r\n this.maxStatementBytes = options?.maxStatementBytes ?? DEFAULT_MAX_STATEMENT_BYTES;\r\n this.dotCommandPolicy = options?.dotCommands ?? 'skip-presentational';\r\n }\r\n\r\n /** Bytes of source consumed so far. */\r\n get bytesConsumed(): number {\r\n return this.bytesConsumedTotal;\r\n }\r\n\r\n /** Dot-commands skipped so far under the `'skip-presentational'` policy. */\r\n get skippedDotCommands(): readonly SkippedDotCommand[] {\r\n return this.skipped;\r\n }\r\n\r\n /** `true` once a `.quit`/`.exit` command ended the input. */\r\n get stopped(): boolean {\r\n return this.lex === 'stopped';\r\n }\r\n\r\n /**\r\n * Feeds one chunk of the source, as a **byte string** — one code unit per\r\n * byte, as produced by `buffer.toString('latin1')`. Callers holding text\r\n * should use {@link parseSqlStatements} or {@link streamSqlStatements},\r\n * which convert for them.\r\n */\r\n push(chunk: string): ParsedStatement[] {\r\n if (this.finished) {\r\n throw new Error('SqlStatementParser.push() called after finish()');\r\n }\r\n this.bytesConsumedTotal += chunk.length;\r\n if (chunk.length === 0) {\r\n return [];\r\n }\r\n return this.scan(this.carry + chunk, false);\r\n }\r\n\r\n finish(): ParsedStatement[] {\r\n if (this.finished) {\r\n throw new Error('SqlStatementParser.finish() called more than once');\r\n }\r\n this.finished = true;\r\n const out = this.scan(this.carry, true);\r\n this.carry = '';\r\n\r\n const open = OPEN_CONSTRUCT_NAME[this.lex];\r\n if (open !== undefined) {\r\n throw new MalformedSqlDumpError(open, this.openLine);\r\n }\r\n if (this.lex === 'dotCommand') {\r\n this.handleDotCommand();\r\n }\r\n if (this.lex !== 'stopped') {\r\n this.endWord();\r\n // The shell runs whatever is left at end of input (\"this may be\r\n // incomplete; let the SQL parser deal with that\"), so a final statement\r\n // without a `;` is still executed.\r\n const statement = this.emit();\r\n if (statement) {\r\n out.push(statement);\r\n }\r\n }\r\n return out;\r\n }\r\n\r\n private scan(text: string, final: boolean): ParsedStatement[] {\r\n const out: ParsedStatement[] = [];\r\n const length = text.length;\r\n let index = 0;\r\n /** Start of the run of `text` currently being kept as statement text, or `-1`. */\r\n let keepFrom = this.hasContent && this.lex !== 'stopped' ? 0 : -1;\r\n\r\n const flush = (end: number): void => {\r\n if (keepFrom >= 0 && end > keepFrom) {\r\n const part = text.slice(keepFrom, end);\r\n this.parts.push(part);\r\n this.partsBytes += part.length;\r\n if (this.partsBytes > this.maxStatementBytes) {\r\n throw new StatementTooLargeError(this.maxStatementBytes, this.statementStartLine);\r\n }\r\n }\r\n keepFrom = -1;\r\n };\r\n const markContent = (at: number): void => {\r\n if (!this.hasContent) {\r\n this.hasContent = true;\r\n this.statementStartLine = this.line;\r\n keepFrom = at;\r\n } else if (keepFrom < 0) {\r\n keepFrom = at;\r\n }\r\n };\r\n const resume = (at: number): void => {\r\n if (this.hasContent && keepFrom < 0) {\r\n keepFrom = at;\r\n }\r\n };\r\n const carryFrom = (at: number): void => {\r\n flush(at);\r\n this.carry = text.slice(at);\r\n };\r\n\r\n if (this.firstChunk && length > 0) {\r\n // A UTF-8 byte-order mark at the very start of the input. SQLite's\r\n // tokenizer treats one as whitespace anywhere, so the shell never sees\r\n // it as SQL; it is skipped here so it cannot start a \"statement\".\r\n if (text.startsWith('\\u00ef\\u00bb\\u00bf')) {\r\n index = 3;\r\n this.firstChunk = false;\r\n } else if (!final && '\\u00ef\\u00bb\\u00bf'.startsWith(text)) {\r\n this.carry = text;\r\n return out;\r\n } else {\r\n this.firstChunk = false;\r\n }\r\n }\r\n\r\n while (index < length) {\r\n const character = text[index] as string;\r\n\r\n // The shell's line reader drops a `\\r` that immediately precedes `\\n`,\r\n // wherever it is — including inside a string literal.\r\n if (character === '\\r' && this.lex !== 'stopped') {\r\n if (index + 1 >= length && !final) {\r\n carryFrom(index);\r\n return out;\r\n }\r\n if (text[index + 1] === '\\n') {\r\n flush(index);\r\n index++;\r\n resume(index);\r\n continue;\r\n }\r\n }\r\n\r\n switch (this.lex) {\r\n case 'stopped':\r\n index = length;\r\n continue;\r\n\r\n case 'hashComment':\r\n case 'dotCommand': {\r\n const newline = text.indexOf('\\n', index);\r\n const end = newline === -1 ? length : newline;\r\n if (this.lex === 'dotCommand' && this.dotText.length < MAX_DOT_COMMAND_BYTES) {\r\n this.dotText += text.slice(index, end);\r\n }\r\n if (newline === -1) {\r\n index = length;\r\n continue;\r\n }\r\n if (this.lex === 'dotCommand') {\r\n this.handleDotCommand();\r\n if (this.stopped) {\r\n index = length;\r\n continue;\r\n }\r\n }\r\n this.lex = 'normal';\r\n index = newline;\r\n continue;\r\n }\r\n\r\n case 'singleQuote':\r\n case 'doubleQuote':\r\n case 'backtick':\r\n case 'bracket': {\r\n const close = CLOSING_CHARACTER[this.lex] as string;\r\n if (character === close) {\r\n // Doubled quotes need no lookahead: `'it''s'` is two adjacent\r\n // strings to `sqlite3_complete()` as well, which changes nothing.\r\n this.lex = 'normal';\r\n this.atLineStart = false;\r\n index++;\r\n continue;\r\n }\r\n if (character === '\\r') {\r\n // A lone `\\r`; one followed by `\\n` was already dropped above.\r\n index++;\r\n continue;\r\n }\r\n // Jump to the next byte that matters: the closing quote, or a `\\r`\r\n // that may need dropping. Newlines in between are only counted.\r\n let end = text.indexOf(close, index);\r\n if (end === -1) end = length;\r\n const crAt = text.indexOf('\\r', index);\r\n if (crAt !== -1 && crAt < end) end = crAt;\r\n this.countNewlines(text, index, end);\r\n index = end;\r\n continue;\r\n }\r\n\r\n case 'blockComment': {\r\n if (this.blockStar && character === '/') {\r\n this.blockStar = false;\r\n this.lex = 'normal';\r\n this.completeState = completeTransition(this.completeState, CompleteToken.Whitespace);\r\n this.atLineStart = false;\r\n index++;\r\n continue;\r\n }\r\n const starAt = text.indexOf('*', index);\r\n const crAt = text.indexOf('\\r', index);\r\n let end = starAt === -1 ? length : starAt;\r\n if (crAt !== -1 && crAt < end) {\r\n end = crAt;\r\n }\r\n if (end > index) {\r\n this.countNewlines(text, index, end);\r\n this.blockStar = false;\r\n index = end;\r\n continue;\r\n }\r\n if (character === '*') {\r\n this.blockStar = true;\r\n this.atLineStart = false;\r\n if (index + 1 >= length && !final) {\r\n // Keep the `*` pending, so a `/` at the start of the next chunk\r\n // closes the comment.\r\n index++;\r\n continue;\r\n }\r\n index++;\r\n continue;\r\n }\r\n // A lone `\\r` not followed by `\\n`: ordinary comment text.\r\n this.blockStar = false;\r\n index++;\r\n continue;\r\n }\r\n\r\n case 'lineComment': {\r\n if (character === '\\n') {\r\n // The newline itself is whitespace in the normal state.\r\n this.lex = 'normal';\r\n continue;\r\n }\r\n if (character === '\\r') {\r\n index++;\r\n continue;\r\n }\r\n let end = text.indexOf('\\n', index);\r\n if (end === -1) end = length;\r\n const crAt = text.indexOf('\\r', index);\r\n if (crAt !== -1 && crAt < end) end = crAt;\r\n index = end;\r\n continue;\r\n }\r\n\r\n case 'normal':\r\n break;\r\n }\r\n\r\n // --- normal state -------------------------------------------------\r\n\r\n const code = text.charCodeAt(index);\r\n\r\n if (this.wordLength > 0) {\r\n if (isIdentifierCharCode(code)) {\r\n const start = index;\r\n while (index < length && isIdentifierCharCode(text.charCodeAt(index))) {\r\n index++;\r\n }\r\n this.extendWord(text.slice(start, index));\r\n continue;\r\n }\r\n this.endWord();\r\n }\r\n\r\n if (this.atLineStart) {\r\n this.atLineStart = false;\r\n if (!this.hasContent && (character === '.' || character === '#')) {\r\n this.lex = character === '.' ? 'dotCommand' : 'hashComment';\r\n this.dotText = '';\r\n this.dotLine = this.line;\r\n index++;\r\n continue;\r\n }\r\n if (\r\n this.completeState !== 5 &&\r\n this.completeState !== 6 &&\r\n this.mayStartTerminatorLine(text, index, final)\r\n ) {\r\n const newline = text.indexOf('\\n', index);\r\n const lineEnd = newline === -1 ? length : newline;\r\n const lineText = text.slice(index, lineEnd);\r\n if (newline === -1 && !final) {\r\n if (lineText.length < MAX_TERMINATOR_LINE_BYTES && couldBeTerminatorLine(lineText)) {\r\n this.atLineStart = true;\r\n carryFrom(index);\r\n return out;\r\n }\r\n } else if (isTerminatorLine(lineText)) {\r\n // The shell replaces the whole line with `;`.\r\n flush(index);\r\n const statement = this.completeWithSemicolon();\r\n if (statement) {\r\n out.push(statement);\r\n }\r\n index = lineEnd;\r\n continue;\r\n }\r\n }\r\n }\r\n\r\n if (character === ';') {\r\n const next = completeTransition(this.completeState, CompleteToken.Semi);\r\n if (next === 1) {\r\n flush(index);\r\n this.completeState = next;\r\n const statement = this.emit();\r\n if (statement) {\r\n out.push(statement);\r\n }\r\n index++;\r\n continue;\r\n }\r\n // A `;` inside a trigger body is part of the statement.\r\n this.completeState = next;\r\n markContent(index);\r\n index++;\r\n continue;\r\n }\r\n\r\n if (isCompleteWhitespace(character)) {\r\n this.completeState = completeTransition(this.completeState, CompleteToken.Whitespace);\r\n if (character === '\\n') {\r\n this.line++;\r\n this.atLineStart = true;\r\n }\r\n index++;\r\n continue;\r\n }\r\n\r\n if (character === '-' || character === '/') {\r\n if (index + 1 >= length && !final) {\r\n carryFrom(index);\r\n return out;\r\n }\r\n const next = text[index + 1];\r\n if ((character === '-' && next === '-') || (character === '/' && next === '*')) {\r\n this.lex = character === '-' ? 'lineComment' : 'blockComment';\r\n this.blockStar = false;\r\n if (character === '-') {\r\n // `--` behaves as whitespace for `sqlite3_complete()`.\r\n this.completeState = completeTransition(this.completeState, CompleteToken.Whitespace);\r\n }\r\n index += 2;\r\n continue;\r\n }\r\n this.completeState = completeTransition(this.completeState, CompleteToken.Other);\r\n markContent(index);\r\n index++;\r\n continue;\r\n }\r\n\r\n if (character === \"'\" || character === '\"' || character === '`' || character === '[') {\r\n this.lex =\r\n character === \"'\"\r\n ? 'singleQuote'\r\n : character === '\"'\r\n ? 'doubleQuote'\r\n : character === '`'\r\n ? 'backtick'\r\n : 'bracket';\r\n this.openLine = this.line;\r\n this.completeState = completeTransition(this.completeState, CompleteToken.Other);\r\n markContent(index);\r\n index++;\r\n continue;\r\n }\r\n\r\n if (code === 0xef) {\r\n // A UTF-8 byte-order mark at the start of a token is whitespace to\r\n // SQLite's tokenizer (its `CC_BOM` class).\r\n if (index + 2 >= length && !final) {\r\n carryFrom(index);\r\n return out;\r\n }\r\n if (text.charCodeAt(index + 1) === 0xbb && text.charCodeAt(index + 2) === 0xbf) {\r\n flush(index);\r\n index += 3;\r\n resume(index);\r\n continue;\r\n }\r\n }\r\n\r\n if (isIdentifierCharCode(code)) {\r\n markContent(index);\r\n const start = index;\r\n while (index < length && isIdentifierCharCode(text.charCodeAt(index))) {\r\n index++;\r\n }\r\n this.extendWord(text.slice(start, index));\r\n continue;\r\n }\r\n\r\n this.completeState = completeTransition(this.completeState, CompleteToken.Other);\r\n markContent(index);\r\n index++;\r\n }\r\n\r\n flush(length);\r\n this.carry = '';\r\n return out;\r\n }\r\n\r\n /**\r\n * Cheap pre-check before the terminator-line lookahead: only a line whose\r\n * first non-blank character is `/` or `g` can be one. Keeps the lookahead —\r\n * which has to look at the whole line — off the ordinary `INSERT` lines\r\n * that make up almost all of a dump.\r\n */\r\n private mayStartTerminatorLine(text: string, index: number, final: boolean): boolean {\r\n let probe = index;\r\n while (probe < text.length && text[probe] !== '\\n' && isCSpace(text[probe] as string)) {\r\n probe++;\r\n }\r\n if (probe >= text.length) {\r\n return !final;\r\n }\r\n const first = text[probe];\r\n return first === '/' || first === 'g' || first === 'G';\r\n }\r\n\r\n private countNewlines(text: string, start: number, end: number): void {\r\n let position = text.indexOf('\\n', start);\r\n while (position !== -1 && position < end) {\r\n this.line++;\r\n position = text.indexOf('\\n', position + 1);\r\n }\r\n if (end > start) {\r\n this.atLineStart = text[end - 1] === '\\n';\r\n }\r\n }\r\n\r\n private extendWord(segment: string): void {\r\n if (this.wordPrefix.length < 10) {\r\n this.wordPrefix += segment.slice(0, 10 - this.wordPrefix.length);\r\n }\r\n this.wordLength += segment.length;\r\n }\r\n\r\n private endWord(): void {\r\n if (this.wordLength === 0) {\r\n return;\r\n }\r\n const token = this.wordLength > 9 ? CompleteToken.Other : classifyWord(this.wordPrefix);\r\n this.completeState = completeTransition(this.completeState, token);\r\n this.wordLength = 0;\r\n this.wordPrefix = '';\r\n }\r\n\r\n /** A terminator line: behave as if the line were `;`. */\r\n private completeWithSemicolon(): ParsedStatement | null {\r\n this.completeState = completeTransition(this.completeState, CompleteToken.Semi);\r\n return this.emit();\r\n }\r\n\r\n private emit(): ParsedStatement | null {\r\n const hadContent = this.hasContent;\r\n const byteText = this.parts.join('');\r\n this.parts = [];\r\n this.partsBytes = 0;\r\n this.hasContent = false;\r\n if (!hadContent) {\r\n return null;\r\n }\r\n // Only ASCII whitespace: `\\s` would also match byte 0xA0, which can be the\r\n // last byte of a multi-byte UTF-8 character.\r\n const trimmed = byteText.replace(/[ \\t\\n\\r\\f\\v]+$/, '');\r\n if (trimmed === '') {\r\n return null;\r\n }\r\n const { sql, literalsRewritten } = decodeStatementBytes(trimmed, this.statementStartLine);\r\n const info = describeStatement(sql);\r\n if (info.objectName !== undefined) {\r\n this.lastObject = info.objectName;\r\n }\r\n return {\r\n statementIndex: this.nextStatementIndex++,\r\n sql,\r\n location: { startLine: this.statementStartLine, endLine: this.line },\r\n info,\r\n ...(this.lastObject === undefined ? {} : { currentObject: this.lastObject }),\r\n bytesConsumed: this.bytesConsumedTotal,\r\n textLiteralsRewritten: literalsRewritten,\r\n };\r\n }\r\n\r\n private handleDotCommand(): void {\r\n const text = this.dotText;\r\n this.dotText = '';\r\n this.lex = 'normal';\r\n const command = (/^\\S*/.exec(text)?.[0] ?? '').toLowerCase();\r\n if (EXIT_DOT_COMMANDS.has(command)) {\r\n this.lex = 'stopped';\r\n return;\r\n }\r\n if (\r\n this.dotCommandPolicy === 'skip-presentational' &&\r\n PRESENTATIONAL_DOT_COMMANDS.has(command)\r\n ) {\r\n this.skipped.push({ command, line: this.dotLine });\r\n return;\r\n }\r\n throw new UnsupportedClientCommandError(command, this.dotLine);\r\n }\r\n}\r\n\r\n/** Parses a complete, already-in-memory script. A convenience wrapper over {@link SqlStatementParser}. */\r\nexport function parseSqlStatements(\r\n sql: string | Buffer,\r\n options?: SqlStatementParserOptions,\r\n): ParsedStatement[] {\r\n const parser = new SqlStatementParser(options);\r\n const byteString = (typeof sql === 'string' ? Buffer.from(sql, 'utf8') : sql).toString('latin1');\r\n return [...parser.push(byteString), ...parser.finish()];\r\n}\r\n\r\n/**\r\n * Normalizes any {@link SqlDumpSource} into *byte strings*: one JavaScript\r\n * code unit per input byte, via `latin1`. See {@link SqlStatementParser} for\r\n * why the parser runs on bytes; a `latin1` decode can also never split a\r\n * character across chunks, so no `StringDecoder` is needed.\r\n */\r\nexport async function* toByteStringChunks(source: SqlDumpSource): AsyncGenerator<string> {\r\n if (typeof source === 'string') {\r\n yield Buffer.from(source, 'utf8').toString('latin1');\r\n return;\r\n }\r\n if (source instanceof Uint8Array) {\r\n // Covers `Buffer` too, which extends `Uint8Array`.\r\n yield (Buffer.isBuffer(source) ? source : Buffer.from(source)).toString('latin1');\r\n return;\r\n }\r\n for await (const chunk of source as AsyncIterable<string | Buffer | Uint8Array>) {\r\n if (typeof chunk === 'string') {\r\n yield Buffer.from(chunk, 'utf8').toString('latin1');\r\n } else {\r\n yield (Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)).toString('latin1');\r\n }\r\n }\r\n}\r\n\r\n/**\r\n * Streams `source` into {@link ParsedStatement}s without ever buffering the\r\n * whole input: at most the current statement's text, plus a few carried\r\n * bytes, is held at a time.\r\n */\r\nexport async function* streamSqlStatements(\r\n source: SqlDumpSource,\r\n options?: SqlStatementParserOptions,\r\n signal?: AbortSignal,\r\n): AsyncGenerator<ParsedStatement> {\r\n const parser = new SqlStatementParser(options);\r\n yield* streamWithParser(parser, source, signal);\r\n}\r\n\r\n/** Drives an existing parser over `source`, so a caller can inspect it afterwards. */\r\nexport async function* streamWithParser(\r\n parser: SqlStatementParser,\r\n source: SqlDumpSource,\r\n signal?: AbortSignal,\r\n): AsyncGenerator<ParsedStatement> {\r\n for await (const chunk of toByteStringChunks(source)) {\r\n throwIfAborted(signal);\r\n for (const statement of parser.push(chunk)) {\r\n yield statement;\r\n }\r\n if (parser.stopped) {\r\n break;\r\n }\r\n }\r\n throwIfAborted(signal);\r\n for (const statement of parser.finish()) {\r\n yield statement;\r\n }\r\n}\r\n","import { executeStatement, toNumber } from '../connection/acquire.js';\r\nimport type { SqliteConnection } from '../connection/types.js';\r\nimport { isAbortError } from '../utils/errors.js';\r\nimport type { StatementInfo } from './statementInfo.js';\r\n\r\nconst TRUTHY_PRAGMA_VALUES: ReadonlySet<string> = new Set(['1', 'on', 'true', 'yes']);\r\n\r\n/** Parses a boolean pragma value the way SQLite does (`sqlite3GetBoolean`). */\r\nexport function isTruthyPragmaValue(value: string | undefined): boolean {\r\n return value !== undefined && TRUTHY_PRAGMA_VALUES.has(value.trim().toLowerCase());\r\n}\r\n\r\n/**\r\n * Follows the connection state a restore script changes, so it can be put\r\n * back when the script stops before undoing it itself — or, for the\r\n * settings a native dump never undoes, when it finishes.\r\n *\r\n * Only statements the parser has classified (see `describeStatement`) are\r\n * followed: top-level transaction control and the two session pragmas a\r\n * dump uses. Text inside row values or trigger bodies is never mistaken for\r\n * one, because a statement is classified from its leading tokens only.\r\n */\r\nexport class RestoreSessionState {\r\n private initialForeignKeys: boolean | undefined;\r\n private foreignKeysChanged = false;\r\n private writableSchemaOn = false;\r\n private schemaRowsWritten = false;\r\n /** Tracked when the adapter cannot report `isInTransaction()`. */\r\n private trackedTransaction = false;\r\n private callerTransaction = false;\r\n\r\n /** Records the state to restore to. Call once, before the first statement. */\r\n async begin(connection: SqliteConnection, signal?: AbortSignal): Promise<void> {\r\n this.callerTransaction = connection.isInTransaction?.() ?? false;\r\n try {\r\n const result = await connection.query({ sql: 'PRAGMA foreign_keys' }, signal);\r\n const first = result.rows[0];\r\n if (first !== undefined) {\r\n this.initialForeignKeys = toNumber(Object.values(first)[0]) !== 0;\r\n }\r\n } catch (error) {\r\n if (isAbortError(error)) throw error;\r\n }\r\n }\r\n\r\n /** Whether the handle was already inside a transaction the caller opened. */\r\n get joinedCallerTransaction(): boolean {\r\n return this.callerTransaction;\r\n }\r\n\r\n /** Whether any statement wrote virtual-table rows into the schema table. */\r\n get wroteSchemaRows(): boolean {\r\n return this.schemaRowsWritten;\r\n }\r\n\r\n /** Call after every statement that executed successfully. */\r\n observe(info: StatementInfo): void {\r\n if (info.transactionControl === 'begin') {\r\n this.trackedTransaction = true;\r\n } else if (info.transactionControl === 'commit' || info.transactionControl === 'rollback') {\r\n this.trackedTransaction = false;\r\n } else if (info.transactionControl === 'savepoint' && !this.trackedTransaction) {\r\n this.trackedTransaction = true;\r\n }\r\n if (info.verb === 'PRAGMA' && info.pragmaValue !== undefined) {\r\n if (info.pragmaName === 'foreign_keys') {\r\n this.foreignKeysChanged = true;\r\n } else if (info.pragmaName === 'writable_schema') {\r\n this.writableSchemaOn = isTruthyPragmaValue(info.pragmaValue);\r\n }\r\n }\r\n if (info.verb === 'INSERT' && isSchemaTableName(info.objectName)) {\r\n this.schemaRowsWritten = true;\r\n }\r\n }\r\n\r\n /** Whether a transaction the script (not the caller) opened is still open. */\r\n scriptTransactionOpen(connection: SqliteConnection): boolean {\r\n if (this.callerTransaction) {\r\n return false;\r\n }\r\n return connection.isInTransaction?.() ?? this.trackedTransaction;\r\n }\r\n\r\n /**\r\n * Puts back what the script changed. Runs without the caller's signal on\r\n * purpose: on the cancellation path that signal is already aborted, and\r\n * the cleanup must still happen. Returns a description of each change it\r\n * undid, for the `session-state-restored` warning.\r\n */\r\n async restore(\r\n connection: SqliteConnection,\r\n options: { readonly rollbackOpenTransaction: boolean },\r\n ): Promise<{ readonly rolledBack: boolean; readonly restored: readonly string[] }> {\r\n const restored: string[] = [];\r\n let rolledBack = false;\r\n\r\n if (options.rollbackOpenTransaction && this.scriptTransactionOpen(connection)) {\r\n await executeStatement(connection, 'ROLLBACK').catch(() => {});\r\n this.trackedTransaction = false;\r\n rolledBack = true;\r\n }\r\n if (this.writableSchemaOn) {\r\n await executeStatement(connection, 'PRAGMA writable_schema=OFF').catch(() => {});\r\n this.writableSchemaOn = false;\r\n restored.push('writable_schema');\r\n }\r\n // `foreign_keys` cannot change inside a transaction, so this has to come\r\n // after the rollback above. The caller's own open transaction, if any,\r\n // makes it a no-op — and the value never changed inside it either.\r\n if (this.foreignKeysChanged && this.initialForeignKeys !== undefined) {\r\n await executeStatement(\r\n connection,\r\n `PRAGMA foreign_keys=${this.initialForeignKeys ? 'ON' : 'OFF'}`,\r\n ).catch(() => {});\r\n this.foreignKeysChanged = false;\r\n }\r\n return { rolledBack, restored };\r\n }\r\n}\r\n\r\n/** `sqlite_schema`, `sqlite_master`, and their temp-schema forms. */\r\nexport function isSchemaTableName(name: string | undefined): boolean {\r\n if (name === undefined) {\r\n return false;\r\n }\r\n const lower = name.toLowerCase();\r\n return (\r\n lower === 'sqlite_schema' ||\r\n lower === 'sqlite_master' ||\r\n lower === 'sqlite_temp_schema' ||\r\n lower === 'sqlite_temp_master'\r\n );\r\n}\r\n","import { acquireSqliteConnection, executeStatement, toText } from '../connection/acquire.js';\r\nimport type { SqliteConnection, SqliteErrorInfo, SqliteRow } from '../connection/types.js';\r\nimport { redactSecrets } from '../security/redact.js';\r\nimport { isAbortError, throwIfAborted } from '../utils/errors.js';\r\nimport { RestoreExecutionError } from './errors.js';\r\nimport { safeSqlPreview } from './preview.js';\r\nimport { isSchemaTableName, isTruthyPragmaValue, RestoreSessionState } from './sessionState.js';\r\nimport { SqlStatementParser, streamWithParser } from './statementParser.js';\r\nimport type { ParsedStatement } from './statementParser.js';\r\nimport type {\r\n RestoreStatementError,\r\n RestoreWarning,\r\n SqlDumpRestoreRequest,\r\n SqlDumpRestoreResult,\r\n} from './types.js';\r\n\r\nconst WRAP_SAVEPOINT = 'dbgate_sqlite_restore';\r\n\r\n/** Most foreign-key violations listed individually before the rest are summarized. */\r\nconst MAX_REPORTED_FOREIGN_KEY_VIOLATIONS = 20;\r\n\r\n/**\r\n * Restores a plain-SQL dump using only the {@link SqliteConnection}\r\n * abstraction — no `sqlite3` shell, no external process.\r\n *\r\n * The input is split into statements by a streaming parser that reproduces\r\n * the `sqlite3` shell's own rules (see `statementParser.ts`), so a script is\r\n * executed as the same statements, in the same order, that\r\n * `sqlite3 database.db < dump.sql` would execute. Statements run\r\n * sequentially on one handle.\r\n *\r\n * A structural problem with the input — an unterminated string, an\r\n * unsupported dot-command, bytes that cannot be represented — throws,\r\n * because the statement boundaries past that point cannot be trusted. A\r\n * statement that parses but fails in SQLite is recorded in `result.errors`\r\n * instead, and unless `stopOnError` (the default) is set, the restore\r\n * continues.\r\n */\r\nexport async function restoreSqlDump(\r\n request: SqlDumpRestoreRequest,\r\n): Promise<SqlDumpRestoreResult> {\r\n const options = request.options ?? {};\r\n const stopOnError = options.stopOnError ?? true;\r\n const restoreSessionStateOnExit = options.restoreSessionState ?? true;\r\n const schemaWrites = options.schemaWrites ?? 'allow';\r\n const wrap = options.transaction === 'wrap';\r\n const signal = request.signal;\r\n\r\n request.progress?.({ phase: 'connecting' });\r\n const acquired = await acquireSqliteConnection(request.connection, signal);\r\n const connection = acquired.connection;\r\n\r\n let statementsExecuted = 0;\r\n let statementsFailed = 0;\r\n let rowsRestored = 0;\r\n let bytesConsumed = 0;\r\n const errors: RestoreStatementError[] = [];\r\n const warnings: RestoreWarning[] = [];\r\n const sessionState = new RestoreSessionState();\r\n const parser = new SqlStatementParser(options);\r\n\r\n let defensiveDisabled = false;\r\n let wrapOpen = false;\r\n let skippedTransactionControl = 0;\r\n let textLiteralsRewritten = 0;\r\n\r\n const result = (cancelled: boolean): SqlDumpRestoreResult => ({\r\n statementsExecuted,\r\n statementsFailed,\r\n rowsRestored,\r\n bytesConsumed,\r\n errors,\r\n warnings,\r\n cancelled,\r\n });\r\n\r\n const report = (\r\n phase: 'parsing' | 'executing' | 'finalizing',\r\n statement?: ParsedStatement,\r\n executionState?: 'started' | 'finished' | 'failed',\r\n error?: RestoreStatementError,\r\n ): void => {\r\n request.progress?.({\r\n phase,\r\n statementsProcessed: statementsExecuted + statementsFailed,\r\n rowsRestored,\r\n bytesConsumed,\r\n ...(statement === undefined\r\n ? {}\r\n : {\r\n statementIndex: statement.statementIndex,\r\n ...(statement.currentObject === undefined\r\n ? {}\r\n : { currentObject: statement.currentObject }),\r\n }),\r\n ...(executionState === undefined ? {} : { executionState }),\r\n ...(error === undefined\r\n ? {}\r\n : {\r\n error: {\r\n statementIndex: error.statementIndex,\r\n location: error.location,\r\n sqlPreview: error.sqlPreview,\r\n message: error.message,\r\n },\r\n }),\r\n });\r\n };\r\n\r\n /** Ends the restore's own transaction (`transaction: 'wrap'`), committing only on success. */\r\n const closeWrap = async (commit: boolean): Promise<void> => {\r\n if (!wrapOpen) {\r\n return;\r\n }\r\n wrapOpen = false;\r\n if (!commit) {\r\n await executeStatement(connection, `ROLLBACK TO ${WRAP_SAVEPOINT}`).catch(() => {});\r\n warnings.push({\r\n code: 'transaction-rolled-back',\r\n message:\r\n 'The restore did not complete, so its transaction (transaction: \"wrap\") was rolled back and the database is unchanged.',\r\n });\r\n }\r\n await executeStatement(connection, `RELEASE ${WRAP_SAVEPOINT}`).catch(() => {});\r\n };\r\n\r\n const finalize = async (completed: boolean): Promise<void> => {\r\n await closeWrap(completed);\r\n if (restoreSessionStateOnExit) {\r\n const { rolledBack, restored } = await sessionState.restore(connection, {\r\n rollbackOpenTransaction: true,\r\n });\r\n if (rolledBack) {\r\n warnings.push({\r\n code: 'transaction-rolled-back',\r\n message: completed\r\n ? \"The script opened a transaction and never committed it (a truncated dump ends this way), so it was rolled back — as the sqlite3 shell's exit would roll it back.\"\r\n : 'The restore stopped inside the transaction the script opened, so that transaction was rolled back: nothing it had written so far was kept.',\r\n });\r\n }\r\n if (restored.length > 0) {\r\n warnings.push({\r\n code: 'session-state-restored',\r\n message: `The script left ${restored.join(', ')} changed when the restore ended, so it was reset before the connection was released.`,\r\n });\r\n }\r\n }\r\n if (sessionState.wroteSchemaRows) {\r\n // Rows written straight into sqlite_schema only take effect once the\r\n // schema is re-read. A fresh connection re-reads it anyway; this makes\r\n // the restored virtual tables usable on the *same* handle too.\r\n await executeStatement(connection, 'PRAGMA writable_schema=RESET').catch(() => {});\r\n }\r\n if (defensiveDisabled && connection.setDefensive) {\r\n await connection.setDefensive(true).catch(() => {});\r\n defensiveDisabled = false;\r\n }\r\n await acquired.release();\r\n };\r\n\r\n try {\r\n await sessionState.begin(connection, signal);\r\n if (options.disableForeignKeys) {\r\n await executeStatement(connection, 'PRAGMA foreign_keys=OFF', signal);\r\n sessionState.observe({ verb: 'PRAGMA', pragmaName: 'foreign_keys', pragmaValue: 'OFF' });\r\n }\r\n if (sessionState.joinedCallerTransaction && !wrap) {\r\n warnings.push({\r\n code: 'caller-transaction-open',\r\n message:\r\n 'The connection was already inside a transaction when the restore started. A full dump\\'s own BEGIN TRANSACTION will fail in that state; commit first, or restore with transaction: \"wrap\", which nests.',\r\n });\r\n }\r\n\r\n for await (const statement of streamWithParser(parser, request.source, signal)) {\r\n throwIfAborted(signal);\r\n bytesConsumed = statement.bytesConsumed;\r\n textLiteralsRewritten += statement.textLiteralsRewritten;\r\n report('parsing', statement);\r\n const info = statement.info;\r\n\r\n if (wrap) {\r\n if (\r\n info.transactionControl === 'begin' ||\r\n info.transactionControl === 'commit' ||\r\n info.transactionControl === 'rollback'\r\n ) {\r\n skippedTransactionControl++;\r\n continue;\r\n }\r\n // `PRAGMA foreign_keys` is a no-op inside a transaction, so the\r\n // dump's leading pragmas run before the wrapping transaction opens.\r\n if (!wrapOpen && info.verb !== 'PRAGMA') {\r\n await executeStatement(connection, `SAVEPOINT ${WRAP_SAVEPOINT}`, signal);\r\n wrapOpen = true;\r\n }\r\n }\r\n\r\n const schemaWriteRefused =\r\n schemaWrites === 'refuse' &&\r\n ((info.verb === 'INSERT' && isSchemaTableName(info.objectName)) ||\r\n (info.pragmaName === 'writable_schema' && isTruthyPragmaValue(info.pragmaValue)));\r\n\r\n if (\r\n !schemaWriteRefused &&\r\n schemaWrites === 'allow' &&\r\n !defensiveDisabled &&\r\n connection.setDefensive &&\r\n info.pragmaName === 'writable_schema' &&\r\n isTruthyPragmaValue(info.pragmaValue)\r\n ) {\r\n await connection.setDefensive(false);\r\n defensiveDisabled = true;\r\n warnings.push({\r\n code: 'defensive-mode-disabled',\r\n message:\r\n 'The dump recreates virtual tables by writing sqlite_schema directly (as every native .dump of such a database does), so SQLITE_DBCONFIG_DEFENSIVE was disabled for the rest of the restore and re-enabled afterwards.',\r\n statementIndex: statement.statementIndex,\r\n });\r\n }\r\n\r\n report('executing', statement, 'started');\r\n try {\r\n if (schemaWriteRefused) {\r\n throw new Error(\r\n 'Statement writes the schema table directly, which schemaWrites: \"refuse\" does not allow',\r\n );\r\n }\r\n const executed = await executeStatement(connection, statement.sql, signal);\r\n rowsRestored += executed.changes;\r\n statementsExecuted++;\r\n sessionState.observe(info);\r\n report('executing', statement, 'finished');\r\n } catch (error) {\r\n if (isAbortError(error)) {\r\n throw error;\r\n }\r\n statementsFailed++;\r\n const statementError = toStatementError(connection, statement, error);\r\n errors.push(statementError);\r\n report('executing', statement, 'failed', statementError);\r\n if (stopOnError) {\r\n collectParserWarnings(parser, warnings, textLiteralsRewritten, skippedTransactionControl);\r\n await finalize(false);\r\n return result(false);\r\n }\r\n }\r\n }\r\n\r\n report('finalizing');\r\n if (options.verifyForeignKeys) {\r\n await closeWrap(true);\r\n warnings.push(...(await checkForeignKeys(connection, signal)));\r\n }\r\n collectParserWarnings(parser, warnings, textLiteralsRewritten, skippedTransactionControl);\r\n await finalize(true);\r\n return result(false);\r\n } catch (error) {\r\n collectParserWarnings(parser, warnings, textLiteralsRewritten, skippedTransactionControl);\r\n await finalize(false);\r\n if (isAbortError(error)) {\r\n return result(true);\r\n }\r\n throw error;\r\n }\r\n}\r\n\r\nfunction collectParserWarnings(\r\n parser: SqlStatementParser,\r\n warnings: RestoreWarning[],\r\n textLiteralsRewritten: number,\r\n skippedTransactionControl: number,\r\n): void {\r\n for (const skipped of parser.skippedDotCommands) {\r\n warnings.push({\r\n code: 'dot-command-skipped',\r\n message: `The sqlite3 shell command \".${skipped.command}\" on line ${skipped.line} only affects the shell's own output, so it was skipped.`,\r\n });\r\n }\r\n if (textLiteralsRewritten > 0) {\r\n warnings.push({\r\n code: 'text-literal-rewritten',\r\n message: `${textLiteralsRewritten} string literal(s) held bytes that are not valid UTF-8 and were executed as CAST(X'...' AS TEXT), which stores the identical bytes.`,\r\n });\r\n }\r\n if (skippedTransactionControl > 0) {\r\n warnings.push({\r\n code: 'script-transaction-control-skipped',\r\n message: `${skippedTransactionControl} BEGIN/COMMIT/ROLLBACK statement(s) in the script were skipped, because transaction: \"wrap\" runs the whole restore in its own transaction.`,\r\n });\r\n }\r\n}\r\n\r\n/** Runs `PRAGMA foreign_key_check` over the restored database. */\r\nasync function checkForeignKeys(\r\n connection: SqliteConnection,\r\n signal?: AbortSignal,\r\n): Promise<RestoreWarning[]> {\r\n const found: RestoreWarning[] = [];\r\n let total = 0;\r\n const byTable = new Map<string, number>();\r\n for await (const row of connection.stream<SqliteRow>(\r\n { sql: 'PRAGMA foreign_key_check' },\r\n signal === undefined ? {} : { signal },\r\n )) {\r\n total++;\r\n const table = toText(row.table) ?? '?';\r\n byTable.set(table, (byTable.get(table) ?? 0) + 1);\r\n if (found.length < MAX_REPORTED_FOREIGN_KEY_VIOLATIONS) {\r\n found.push({\r\n code: 'foreign-key-violation',\r\n message: `Row ${toText(row.rowid) ?? '(no rowid)'} of table \"${table}\" references a missing row in \"${toText(row.parent) ?? '?'}\" (foreign key #${toText(row.fkid) ?? '?'}).`,\r\n });\r\n }\r\n }\r\n if (total > found.length) {\r\n found.push({\r\n code: 'foreign-key-violation',\r\n message: `${total} foreign-key violations in total: ${[...byTable].map(([table, count]) => `${table} (${count})`).join(', ')}.`,\r\n });\r\n }\r\n return found;\r\n}\r\n\r\nfunction toStatementError(\r\n connection: SqliteConnection,\r\n statement: ParsedStatement,\r\n error: unknown,\r\n): RestoreStatementError {\r\n const described = connection.describeError?.(error);\r\n const message = redactSecrets(\r\n described?.message ?? (error instanceof Error ? error.message : String(error)),\r\n );\r\n const sqliteError: SqliteErrorInfo | undefined = described\r\n ? { ...described, message: redactSecrets(described.message) }\r\n : undefined;\r\n const executionError = new RestoreExecutionError(\r\n statement.statementIndex,\r\n statement.location,\r\n safeSqlPreview(statement.sql),\r\n message,\r\n sqliteError,\r\n { cause: error },\r\n );\r\n return {\r\n statementIndex: executionError.statementIndex,\r\n location: executionError.location,\r\n sqlPreview: executionError.sqlPreview,\r\n message: executionError.message,\r\n ...(executionError.sqliteError === undefined\r\n ? {}\r\n : { sqliteError: executionError.sqliteError }),\r\n };\r\n}\r\n","import type { Writable } from 'node:stream';\r\nimport { inspectDumpArchive } from '../archive/planner.js';\r\nimport type { ArchiveEntry } from '../archive/types.js';\r\nimport { acquireSqliteConnection } from '../connection/acquire.js';\r\nimport { beginSqliteDumpSession } from '../connection/session.js';\r\nimport type { SqliteConnectionInput } from '../connection/types.js';\r\nimport { exportTableDataAsInserts } from '../data/insertExport.js';\r\nimport { introspectSqlite } from '../introspection/introspect.js';\r\nimport type { SqliteDiagnostic } from '../model/diagnostics.js';\r\nimport { renderPlainSql } from '../renderer/plainSql.js';\r\nimport { foldSqliteName, normalizeDumpSelection } from '../selection/normalize.js';\r\nimport { SqliteDumperError } from '../utils/errors.js';\r\nimport type { DumpProgressCallback } from '../utils/progress.js';\r\nimport { StreamDumpWriter } from '../writer/streamWriter.js';\r\nimport type { DumpResult, DumpSqliteOptions } from './types.js';\r\n\r\n/**\r\n * Runs a complete SQLite dump: acquire one handle, open a read snapshot,\r\n * introspect, plan, render, and stream row data — writing plain SQL in the\r\n * native `.dump` layout to `output`.\r\n *\r\n * Everything happens on **one** handle inside **one** read transaction, so\r\n * every table is read from the same state of the database even while other\r\n * connections write to it. When a source is passed, one handle is acquired\r\n * for the whole dump and released afterwards; a bare connection is borrowed\r\n * and never closed.\r\n */\r\nexport async function dumpSqlite(\r\n connectionInput: SqliteConnectionInput,\r\n options: DumpSqliteOptions,\r\n output: Writable,\r\n onProgress?: DumpProgressCallback,\r\n signal?: AbortSignal,\r\n): Promise<DumpResult> {\r\n onProgress?.({ phase: 'connecting' });\r\n const acquired = await acquireSqliteConnection(connectionInput, signal);\r\n\r\n const session = await (async () => {\r\n onProgress?.({ phase: 'starting-snapshot' });\r\n try {\r\n return await beginSqliteDumpSession(\r\n acquired.connection,\r\n options.consistency === undefined ? {} : { consistency: options.consistency },\r\n signal,\r\n );\r\n } catch (error) {\r\n await acquired.release();\r\n throw error;\r\n }\r\n })();\r\n\r\n try {\r\n onProgress?.({ phase: 'introspecting' });\r\n const introspection = await introspectSqlite(\r\n acquired.connection,\r\n options.schemaName === undefined ? {} : { schemaName: options.schemaName },\r\n signal,\r\n );\r\n onProgress?.({\r\n phase: 'detecting-version',\r\n message: introspection.version.versionString,\r\n schemaName: introspection.database.schemaName,\r\n });\r\n\r\n const mode = options.mode ?? 'full';\r\n const selection = normalizeDumpSelection(options.selection);\r\n const archive = inspectDumpArchive(introspection.database, {\r\n mode,\r\n selection,\r\n ...(options.objectKinds === undefined ? {} : { objectKinds: options.objectKinds }),\r\n });\r\n onProgress?.({ phase: 'planning-archive', objectsTotal: archive.entries.length });\r\n\r\n if (!archive.valid) {\r\n throw new SqliteDumperError(\r\n 'invalid-archive',\r\n 'Archive planning failed; inspect the diagnostics, cycles and unsatisfiedDependencies returned by inspectDumpArchive for details',\r\n );\r\n }\r\n\r\n const writer = new StreamDumpWriter(output);\r\n const tablesByName = new Map(\r\n introspection.database.tables.map(table => [foldSqliteName(table.name), table]),\r\n );\r\n\r\n let rowsExported = 0;\r\n let statementsWritten = 0;\r\n const dataWarnings: SqliteDiagnostic[] = [];\r\n\r\n const onTableData = async (entry: ArchiveEntry): Promise<boolean> => {\r\n const table = tablesByName.get(foldSqliteName(entry.name));\r\n if (!table) {\r\n return false;\r\n }\r\n const result = await exportTableDataAsInserts({\r\n connection: acquired.connection,\r\n schemaName: introspection.database.schemaName,\r\n table,\r\n writer,\r\n encoding: introspection.database.encoding,\r\n ...(entry.systemRowFilter === undefined ? {} : { systemRowFilter: entry.systemRowFilter }),\r\n ...(options.dataExport === undefined ? {} : { options: options.dataExport }),\r\n ...(signal === undefined ? {} : { signal }),\r\n ...(onProgress === undefined ? {} : { onProgress }),\r\n });\r\n rowsExported += result.rowsExported;\r\n statementsWritten += result.statementsWritten;\r\n dataWarnings.push(...result.warnings);\r\n if (result.cancelled) {\r\n throw new DOMException('The operation was aborted.', 'AbortError');\r\n }\r\n return true;\r\n };\r\n\r\n const renderResult = await renderPlainSql({\r\n database: introspection.database,\r\n archive,\r\n writer,\r\n mode,\r\n sourceVersion: introspection.version,\r\n ...(options.render === undefined ? {} : { options: options.render }),\r\n ...(signal === undefined ? {} : { signal }),\r\n ...(onProgress === undefined ? {} : { onProgress }),\r\n onTableData,\r\n });\r\n\r\n onProgress?.({ phase: 'finalizing', bytesWritten: renderResult.bytesWritten });\r\n\r\n const sessionWarnings: SqliteDiagnostic[] = session.joinedExistingTransaction\r\n ? [\r\n {\r\n severity: 'info',\r\n code: 'dump-joined-caller-transaction',\r\n message:\r\n \"The connection was already inside a transaction, so the dump was read within it and includes that transaction's uncommitted changes.\",\r\n },\r\n ]\r\n : [];\r\n\r\n return {\r\n bytesWritten: renderResult.bytesWritten,\r\n renderedDumpIds: renderResult.renderedDumpIds,\r\n skippedDumpIds: renderResult.skippedDumpIds,\r\n warnings: [\r\n ...introspection.diagnostics,\r\n ...archive.diagnostics,\r\n ...sessionWarnings,\r\n ...renderResult.warnings,\r\n ...dedupeDiagnostics(dataWarnings),\r\n ],\r\n cancelled: renderResult.cancelled,\r\n rowsExported,\r\n statementsWritten,\r\n };\r\n } finally {\r\n // The read transaction must end before the handle goes back to a\r\n // source, or the next borrower inherits it (and its lock).\r\n await session.finish();\r\n await acquired.release();\r\n }\r\n}\r\n\r\nfunction dedupeDiagnostics(diagnostics: readonly SqliteDiagnostic[]): SqliteDiagnostic[] {\r\n const seen = new Set<string>();\r\n return diagnostics.filter(diagnostic => {\r\n const key = `${diagnostic.code}\\u0000${diagnostic.message}`;\r\n if (seen.has(key)) {\r\n return false;\r\n }\r\n seen.add(key);\r\n return true;\r\n });\r\n}\r\n"],"mappings":"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","names":["throwIfAborted","structureId","throwIfAborted","throwIfAborted","column","throwIfAborted","throwIfAborted","require","module","import_node_buffer","DEFAULT_MAX_STATEMENT_BYTES","isCompleteWhitespace","throwIfAborted","throwIfAborted"]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/connection/types.ts","../src/connection/acquire.ts","../src/connection/session.ts","../src/version/types.ts","../src/version/detect.ts","../src/version/capabilities.ts","../src/security/identifiers.ts","../src/selection/normalize.ts","../src/security/literals.ts","../src/security/redact.ts","../src/writer/streamWriter.ts","../src/writer/bufferWriter.ts","../src/archive/sectionRules.ts","../src/utils/hash.ts","../src/archive/identity.ts","../src/archive/planner.ts","../src/utils/errors.ts","../src/introspection/sqlText.ts","../src/introspection/introspect.ts","../src/renderer/types.ts","../src/restore/complete.ts","../src/renderer/objectRenderers.ts","../src/restore/preview.ts","../src/renderer/plainSql.ts","../src/data/chunkBuilder.ts","../src/data/valueQuery.ts","../src/data/insertExport.ts","../src/compatibility/check.ts","../src/compatibility/unsupported.ts","../src/preflight/preflightRestore.ts","../src/restore/errors.ts","../src/restore/statementInfo.ts","../src/restore/textEncoding.ts","../src/restore/statementParser.ts","../src/restore/sessionState.ts","../src/restore/restoreSqlDump.ts","../src/api/dump.ts"],"sourcesContent":["export * from './connection/index.js';\nexport * from './version/index.js';\nexport * from './model/index.js';\nexport * from './selection/index.js';\nexport * from './security/index.js';\nexport * from './writer/index.js';\nexport * from './archive/index.js';\nexport * from './introspection/index.js';\nexport * from './renderer/index.js';\nexport * from './data/index.js';\nexport * from './compatibility/index.js';\nexport * from './preflight/index.js';\nexport * from './restore/index.js';\nexport * from './utils/index.js';\nexport * from './api/index.js';\n","/**\n * Client-agnostic SQLite connection abstraction.\n *\n * The core package never imports a Node.js driver directly. Callers provide\n * a {@link SqliteConnection} (or a {@link SqliteConnectionSource} that can\n * acquire one) implemented by an adapter such as\n * `dbgate-sqlite-dumper/better-sqlite3`.\n *\n * SQLite is an embedded engine, so a \"connection\" here is one open database\n * handle. The contract is deliberately the same shape the sibling dumper\n * packages use for their network drivers, so an application can treat every\n * dumper the same way.\n */\n\n/** Scalar values accepted as bound query parameters (`?` placeholders). */\nexport type SqliteParameterValue = string | number | bigint | Buffer | Uint8Array | null;\n\n/** A single SQL statement plus its positional (`?`) parameters. */\nexport interface SqliteQuery {\n readonly sql: string;\n /** Bound in order for each `?` placeholder. Adapters must never string-interpolate these. */\n readonly parameters?: readonly SqliteParameterValue[];\n}\n\n/**\n * Scalar values that can appear in a returned row: SQLite's five storage\n * classes as JavaScript sees them.\n *\n * `INTEGER` may arrive as `number` or `bigint` depending on the adapter; the\n * core never relies on either for exactness. Row data is read through SQL\n * that has SQLite itself render every numeric value as text (see\n * `data/valueQuery.ts`), so a 64-bit integer or a `REAL`'s exact digits\n * never pass through a JavaScript number on the way into the dump.\n */\nexport type SqliteColumnValue =\n string | number | bigint | Buffer | Uint8Array | ArrayBuffer | readonly number[] | null;\n\n/** A single result row, keyed by column name. */\nexport interface SqliteRow {\n readonly [column: string]: SqliteColumnValue;\n}\n\n/** Buffered result of a non-streaming query. */\nexport interface SqliteQueryResult<Row extends SqliteRow = SqliteRow> {\n readonly rows: readonly Row[];\n /** Result column names, in order, when the adapter can report them. */\n readonly columns?: readonly string[];\n}\n\nexport interface SqliteStreamOptions {\n readonly signal?: AbortSignal;\n /**\n * Hint for adapters that fetch rows in batches. SQLite steps one row at a\n * time in-process, so most adapters simply ignore it.\n */\n readonly batchSize?: number;\n}\n\n/** Result of executing one statement through {@link SqliteConnection.execute}. */\nexport interface SqliteExecResult {\n /**\n * Rows inserted, updated or deleted by *this* statement — `0` for DDL and\n * for statements that return rows. Adapters must not report SQLite's\n * `sqlite3_changes()` for a statement that is not DML, because it still\n * holds the count from the previous DML statement.\n */\n readonly changes: number;\n}\n\n/** Structured information about a SQLite error, extracted by an adapter. */\nexport interface SqliteErrorInfo {\n /** Symbolic (extended) result code, e.g. `SQLITE_CONSTRAINT_UNIQUE`. */\n readonly code?: string;\n /** Numeric (extended) result code, e.g. `2067`, when the adapter can report it. */\n readonly errno?: number;\n readonly message: string;\n}\n\n/**\n * What a connection can and cannot do, for engines that speak SQLite's SQL\n * but are not an embedded SQLite handle — Cloudflare D1, reached over HTTP,\n * is the case this exists for. Every field is optional and defaults to what\n * an ordinary SQLite handle does, so a local adapter declares nothing.\n *\n * The dump honours each restriction by choosing a different but equivalent\n * query, so the output is the same dump an ordinary handle onto the same\n * database would produce.\n */\nexport interface SqliteConnectionFeatures {\n /**\n * `false` when the engine accepts no `BEGIN` / `SAVEPOINT`. A dump then\n * reads without a snapshot (`consistency: 'none'`) and reports\n * `snapshot-unavailable`. Defaults to `true`.\n */\n readonly transactions?: boolean;\n /**\n * `false` when the table-valued `pragma_xxx()` functions are refused; the\n * catalog is then read through the `PRAGMA xxx(arg)` statements instead.\n * Defaults to `true` (for SQLite 3.16+).\n */\n readonly pragmaFunctions?: boolean;\n /**\n * `false` when only the classic introspection pragmas are allowed:\n * `table_info` / `index_info` in place of `table_xinfo` / `index_xinfo`,\n * and no `table_list`. The dump is the same; what is lost is detail only a\n * diagnostic uses (generated columns, index key order and collations).\n * Defaults to `true`.\n */\n readonly extendedPragmas?: boolean;\n /**\n * `false` when statements must not name a schema (`\"main\".\"t\"`). Only the\n * `main` schema can be dumped then. Defaults to `true`.\n */\n readonly schemaQualifiedNames?: boolean;\n /**\n * How binary values cross the connection. `'hex'` has SQLite return them\n * as `hex()` text, for transports — such as JSON — that cannot carry bytes\n * exactly. Defaults to `'native'`.\n */\n readonly binaryTransport?: 'native' | 'hex';\n /**\n * Read table data in pages of this many rows through {@link\n * SqliteConnection.query} instead of {@link SqliteConnection.stream}, for\n * engines that return a whole result at once. Pages are keyed on the rowid\n * or the primary key, so each one is an index seek.\n */\n readonly pagedReadSize?: number;\n /**\n * Name prefixes of objects the engine keeps for itself in `sqlite_schema`\n * and refuses to let a client read — D1's `_cf_` tables. They are left out\n * of the dump. Compared case-insensitively.\n */\n readonly reservedNamePrefixes?: readonly string[];\n}\n\n/**\n * One open SQLite database handle.\n *\n * Implementations must serialize statements sent through the same handle.\n * In particular, while a {@link stream} is being consumed no other statement\n * is sent on it — this package never interleaves them, because most\n * synchronous drivers refuse to run a second statement while one is still\n * stepping.\n */\nexport interface SqliteConnection {\n /** Restrictions of the engine behind this handle; see {@link SqliteConnectionFeatures}. */\n readonly features?: SqliteConnectionFeatures;\n\n query<Row extends SqliteRow = SqliteRow>(\n query: SqliteQuery,\n signal?: AbortSignal,\n ): Promise<SqliteQueryResult<Row>>;\n\n /**\n * Runs several read-only queries in one round trip, returning one result\n * per query in order. Optional: introspection uses it, when present, to\n * fetch the catalog of every table in a few requests instead of several\n * per table. If a batch fails as a whole, its queries are run one by one.\n */\n queryBatch?(\n queries: readonly SqliteQuery[],\n signal?: AbortSignal,\n ): Promise<readonly SqliteQueryResult[]>;\n\n /** Streams rows without buffering the full result set in memory. */\n stream<Row extends SqliteRow = SqliteRow>(\n query: SqliteQuery,\n options?: SqliteStreamOptions,\n ): AsyncIterable<Row>;\n\n /**\n * Executes one already-complete statement's SQL text with no parameter\n * binding and no client-side rewriting.\n *\n * Restore routes every statement through this rather than `query()`\n * because a dump's statement text must reach SQLite byte for byte: a driver\n * that treats `?` or `:name` as a placeholder would corrupt any `INSERT`\n * carrying one inside a string literal. Adapters that cannot make this\n * guarantee may omit it; callers then fall back to `query()` with no\n * parameters.\n */\n execute?(sql: string, signal?: AbortSignal): Promise<SqliteExecResult>;\n\n /** Extracts structured error fields from a driver error, for diagnostics. */\n describeError?(error: unknown): SqliteErrorInfo | undefined;\n\n /**\n * Whether a transaction is open on this handle (`!sqlite3_get_autocommit`).\n *\n * SQLite has no SQL-level way to ask this, and it matters: a restore that\n * stops part-way through a dump's own `BEGIN TRANSACTION` must roll it back\n * before handing the handle back, or the caller inherits an open\n * transaction holding a write lock on the file. Adapters that cannot answer\n * may omit it; restore then tracks the script's own transaction statements\n * instead.\n */\n isInTransaction?(): boolean;\n\n /**\n * Turns `SQLITE_DBCONFIG_DEFENSIVE` on or off.\n *\n * A dump of a database containing virtual tables recreates them by\n * inserting into `sqlite_schema` under `PRAGMA writable_schema=ON` — exactly\n * as the native `.dump` does — and defensive mode forbids that. Restore\n * uses this, when the adapter provides it, to lift the restriction for the\n * duration of such a restore and put it back afterwards.\n */\n setDefensive?(enabled: boolean): Promise<void>;\n\n /**\n * Requests cancellation of the currently executing statement, if any.\n * Synchronous drivers cannot interrupt a statement mid-step; they\n * implement this as a no-op, and cancellation then takes effect between\n * rows and between statements.\n */\n cancel(): Promise<void>;\n}\n\n/** A connection acquired from a pool-like source, plus its release callback. */\nexport interface AcquiredSqliteConnection {\n readonly connection: SqliteConnection;\n /**\n * Whether this handle is exclusively held for the duration of the\n * operation. `false` for a bare {@link SqliteConnection} the caller handed\n * over directly — it may be shared, so any state this package changes on\n * it must be restored rather than assumed discarded.\n */\n readonly dedicated: boolean;\n /** Idempotent; safe to call more than once. */\n release(): Promise<void>;\n}\n\n/**\n * Represents a resource that must be acquired to obtain one database\n * handle, such as a pool of handles onto the same file. Direct\n * {@link SqliteConnection} instances are borrowed by the library and are\n * never closed by it.\n */\nexport interface SqliteConnectionSource {\n acquire(signal?: AbortSignal): Promise<AcquiredSqliteConnection>;\n}\n\n/** Anything the public API accepts in place of a database handle. */\nexport type SqliteConnectionInput = SqliteConnection | SqliteConnectionSource;\n\nexport function isSqliteConnectionSource(\n input: SqliteConnectionInput,\n): input is SqliteConnectionSource {\n return typeof (input as SqliteConnectionSource).acquire === 'function';\n}\n","import type {\n AcquiredSqliteConnection,\n SqliteConnection,\n SqliteConnectionFeatures,\n SqliteConnectionInput,\n SqliteExecResult,\n} from './types.js';\nimport { isSqliteConnectionSource } from './types.js';\n\n/**\n * Normalizes a {@link SqliteConnectionInput} into an acquired connection with\n * a release callback. A direct connection resolves immediately with a no-op\n * release and `dedicated: false` (the caller may be sharing it); a source is\n * asked for one handle through its own `acquire()`, which is what snapshot\n * consistency requires.\n */\nexport async function acquireSqliteConnection(\n input: SqliteConnectionInput,\n signal?: AbortSignal,\n): Promise<AcquiredSqliteConnection> {\n if (isSqliteConnectionSource(input)) {\n return input.acquire(signal);\n }\n return {\n connection: input as SqliteConnection,\n dedicated: false,\n release: async () => {},\n };\n}\n\n/** Runs one statement through `execute()` when the adapter has it, else through `query()`. */\nexport async function executeStatement(\n connection: SqliteConnection,\n sql: string,\n signal?: AbortSignal,\n): Promise<SqliteExecResult> {\n if (connection.execute) {\n return connection.execute(sql, signal);\n }\n await connection.query({ sql }, signal);\n return { changes: 0 };\n}\n\n/**\n * Coerces an integer-valued catalog cell to a JavaScript number.\n *\n * Adapters may return SQLite `INTEGER`s as `number` or `bigint`; catalog\n * values (column positions, flags, `user_version`) always fit in a double,\n * so either shape is accepted here.\n */\nexport function toNumber(value: unknown, fallback = 0): number {\n if (typeof value === 'number') {\n return value;\n }\n if (typeof value === 'bigint') {\n return Number(value);\n }\n if (typeof value === 'string' && value.trim() !== '' && Number.isFinite(Number(value))) {\n return Number(value);\n }\n return fallback;\n}\n\n/** Coerces a text-valued catalog cell to a string, or `null` for SQL `NULL`. */\nexport function toText(value: unknown): string | null {\n if (value === null || value === undefined) {\n return null;\n }\n if (typeof value === 'string') {\n return value;\n }\n if (value instanceof Uint8Array || value instanceof ArrayBuffer || Array.isArray(value)) {\n return toBuffer(value as Uint8Array | ArrayBuffer | readonly number[]).toString('utf8');\n }\n return String(value);\n}\n\n/**\n * Bytes as a `Buffer`, from any shape a driver returns them in: `Buffer`,\n * `Uint8Array`, `ArrayBuffer` (libSQL), or an array of byte values (the\n * JSON transport of Cloudflare D1).\n */\nexport function toBuffer(value: Uint8Array | ArrayBuffer | readonly number[]): Buffer {\n if (Buffer.isBuffer(value)) {\n return value;\n }\n if (value instanceof Uint8Array) {\n return Buffer.from(value.buffer, value.byteOffset, value.byteLength);\n }\n if (value instanceof ArrayBuffer) {\n return Buffer.from(value);\n }\n return Buffer.from(value as number[]);\n}\n\n/** {@link SqliteConnectionFeatures} with every default filled in. */\nexport interface ResolvedConnectionFeatures {\n readonly transactions: boolean;\n readonly pragmaFunctions: boolean;\n readonly extendedPragmas: boolean;\n readonly schemaQualifiedNames: boolean;\n readonly binaryTransport: 'native' | 'hex';\n readonly pagedReadSize: number | undefined;\n readonly reservedNamePrefixes: readonly string[];\n}\n\nexport function connectionFeatures(connection: SqliteConnection): ResolvedConnectionFeatures {\n const features: SqliteConnectionFeatures = connection.features ?? {};\n const pageSize = features.pagedReadSize;\n return {\n transactions: features.transactions ?? true,\n pragmaFunctions: features.pragmaFunctions ?? true,\n extendedPragmas: features.extendedPragmas ?? true,\n schemaQualifiedNames: features.schemaQualifiedNames ?? true,\n binaryTransport: features.binaryTransport ?? 'native',\n pagedReadSize:\n pageSize === undefined || !Number.isFinite(pageSize)\n ? undefined\n : Math.max(1, Math.floor(pageSize)),\n reservedNamePrefixes: features.reservedNamePrefixes ?? [],\n };\n}\n","import { connectionFeatures, executeStatement } from './acquire.js';\nimport type { SqliteConnection } from './types.js';\n\n/**\n * How a dump obtains a consistent view of the database.\n *\n * - `'snapshot'` (default) — opens a read transaction (as a `SAVEPOINT`, see\n * below) and performs one read inside it before anything else, so every\n * table is read from the same state of the file. In WAL mode that is a\n * true snapshot and writers carry on unblocked; in rollback-journal mode\n * the transaction holds a `SHARED` lock, which keeps writers out until the\n * dump finishes. Either way the result is consistent — it is the same\n * mechanism the native `.dump` uses (`SAVEPOINT dump`).\n * - `'none'` — no transaction; each statement reads whatever is committed\n * when it runs. Only safe when nothing else writes to the database.\n */\nexport type SqliteConsistencyMode = 'snapshot' | 'none';\n\nexport interface SqliteDumpSessionOptions {\n readonly consistency?: SqliteConsistencyMode;\n}\n\nexport interface SqliteDumpSession {\n readonly consistency: SqliteConsistencyMode;\n /**\n * `true` when the handle was already inside a transaction the caller\n * opened, so the dump reads within *their* transaction and sees their\n * uncommitted changes. Reported so a caller can tell.\n */\n readonly joinedExistingTransaction: boolean;\n /**\n * `true` when a snapshot was asked for but the engine has no transactions\n * (see `SqliteConnectionFeatures.transactions`), so the session reads\n * without one and {@link consistency} is `'none'`.\n */\n readonly snapshotUnavailable: boolean;\n /**\n * Ends the read transaction. Idempotent. Never throws for a handle that is\n * already closed — cleanup must not mask the error that caused it.\n */\n finish(): Promise<void>;\n}\n\n/**\n * Savepoint name used for the dump's read transaction. Distinct from the\n * native shell's `dump` so a dump taken from inside a caller's own savepoint\n * named `dump` cannot release theirs by accident.\n */\nconst DUMP_SAVEPOINT = 'dbgate_sqlite_dump';\n\n/**\n * Opens the dump's read session.\n *\n * A `SAVEPOINT` rather than `BEGIN`: outside a transaction the two are the\n * same (a savepoint then starts a deferred transaction), but inside one a\n * `BEGIN` fails while a savepoint nests. A caller who is already in a\n * transaction therefore gets a dump of what *they* see instead of an error.\n *\n * A deferred transaction does not take its read lock until the first read,\n * so the session performs one immediately — otherwise the snapshot would be\n * taken lazily by whichever catalog query happened to come first, which is\n * the same thing but leaves the guarantee to an accident of ordering.\n */\nexport async function beginSqliteDumpSession(\n connection: SqliteConnection,\n options?: SqliteDumpSessionOptions,\n signal?: AbortSignal,\n): Promise<SqliteDumpSession> {\n const requested = options?.consistency ?? 'snapshot';\n const joinedExistingTransaction = connection.isInTransaction?.() ?? false;\n const snapshotUnavailable =\n requested === 'snapshot' && !connectionFeatures(connection).transactions;\n const consistency: SqliteConsistencyMode = snapshotUnavailable ? 'none' : requested;\n\n if (consistency === 'none') {\n return { consistency, joinedExistingTransaction, snapshotUnavailable, finish: async () => {} };\n }\n\n await executeStatement(connection, `SAVEPOINT ${DUMP_SAVEPOINT}`, signal);\n let finished = false;\n const finish = async (): Promise<void> => {\n if (finished) {\n return;\n }\n finished = true;\n // Deliberately *without* the caller's signal: if the dump was cancelled\n // that signal is already aborted, and reusing it would skip the release\n // and leave a read transaction (and on rollback-journal databases, a\n // SHARED lock) open on a handle the caller may keep using.\n await executeStatement(connection, `RELEASE ${DUMP_SAVEPOINT}`).catch(() => {});\n };\n\n try {\n await connection.query({ sql: 'SELECT count(*) AS n FROM sqlite_master' }, signal);\n } catch (error) {\n await finish();\n throw error;\n }\n\n return { consistency, joinedExistingTransaction, snapshotUnavailable: false, finish };\n}\n","/** Normalized SQLite library version. */\nexport interface SqliteVersion {\n /** Raw `sqlite_version()` string, e.g. `\"3.45.1\"`. */\n readonly versionString: string;\n readonly majorVersion: number;\n readonly minorVersion: number;\n readonly patchVersion: number;\n /**\n * The numeric form SQLite itself uses for `SQLITE_VERSION_NUMBER`:\n * `major * 1000000 + minor * 1000 + patch`. `3045001` for 3.45.1.\n */\n readonly versionNumber: number;\n /** `sqlite_source_id()`, identifying the exact check-in, when available. */\n readonly sourceId?: string;\n}\n\n/**\n * Capabilities derived once from {@link SqliteVersion}. These describe what\n * the SQLite library behind a handle understands; they are used both for the\n * source (which catalog pragmas introspection may use) and, through\n * `compatibility/`, for a restore target (what DDL it can accept).\n */\nexport interface SqliteCapabilities {\n /** `WITHOUT ROWID` tables; 3.8.2+. */\n readonly supportsWithoutRowid: boolean;\n /** Multi-row `INSERT ... VALUES (...), (...)`; 3.7.11+. */\n readonly supportsMultiRowValues: boolean;\n /** Table-valued pragma functions (`pragma_table_info(...)`); 3.16.0+. */\n readonly supportsPragmaFunctions: boolean;\n /** `PRAGMA table_xinfo`, which reports hidden and generated columns; 3.26.0+. */\n readonly supportsTableXinfo: boolean;\n /** Generated (`GENERATED ALWAYS AS`) columns; 3.31.0+. */\n readonly supportsGeneratedColumns: boolean;\n /** The `sqlite_schema` alias for `sqlite_master`; 3.33.0+. */\n readonly supportsSqliteSchemaAlias: boolean;\n /** `PRAGMA writable_schema=RESET`; 3.35.0+. */\n readonly supportsWritableSchemaReset: boolean;\n /** `STRICT` tables; 3.37.0+. */\n readonly supportsStrictTables: boolean;\n /** `PRAGMA table_list`, which reports `WITHOUT ROWID`, `STRICT` and shadow tables; 3.37.0+. */\n readonly supportsTableList: boolean;\n}\n\n/**\n * Parses a `sqlite_version()` string. Only the leading `major.minor.patch`\n * is interpreted; anything after it is kept verbatim for reporting.\n */\nexport function parseSqliteVersion(versionString: string): {\n majorVersion: number;\n minorVersion: number;\n patchVersion: number;\n versionNumber: number;\n} {\n const match = /^(\\d+)\\.(\\d+)(?:\\.(\\d+))?/.exec(versionString.trim());\n if (!match) {\n throw new Error(`Cannot parse SQLite version string: ${JSON.stringify(versionString)}`);\n }\n const majorVersion = Number(match[1]);\n const minorVersion = Number(match[2]);\n const patchVersion = match[3] === undefined ? 0 : Number(match[3]);\n return {\n majorVersion,\n minorVersion,\n patchVersion,\n versionNumber: majorVersion * 1_000_000 + minorVersion * 1000 + patchVersion,\n };\n}\n","import { toText } from '../connection/acquire.js';\nimport type { SqliteConnection, SqliteRow } from '../connection/types.js';\nimport { parseSqliteVersion } from './types.js';\nimport type { SqliteVersion } from './types.js';\n\n/**\n * Detects the SQLite library version behind a handle.\n *\n * This is the version of the library the *driver* links, which is not\n * necessarily the version of the `sqlite3` command-line shell installed on\n * the same machine — `better-sqlite3`, for instance, bundles its own. The\n * difference matters for one thing in a dump: `REAL` values are rendered by\n * SQLite's own `printf`, whose digit generation changed between releases.\n */\nexport async function detectSqliteVersion(\n connection: SqliteConnection,\n signal?: AbortSignal,\n): Promise<SqliteVersion> {\n const result = await connection.query<SqliteRow>(\n { sql: 'SELECT sqlite_version() AS versionString' },\n signal,\n );\n const versionString = toText(result.rows[0]?.versionString);\n if (!versionString) {\n throw new Error('Unable to detect SQLite version: sqlite_version() returned no data');\n }\n\n let sourceId: string | undefined;\n try {\n const source = await connection.query<SqliteRow>(\n { sql: 'SELECT sqlite_source_id() AS sourceId' },\n signal,\n );\n sourceId = toText(source.rows[0]?.sourceId) ?? undefined;\n } catch {\n // Optional detail only: a build with the function omitted is still usable.\n }\n\n return {\n versionString,\n ...parseSqliteVersion(versionString),\n ...(sourceId === undefined ? {} : { sourceId }),\n };\n}\n","import type { SqliteCapabilities, SqliteVersion } from './types.js';\n\n/**\n * Derives {@link SqliteCapabilities} from a detected {@link SqliteVersion}.\n *\n * Gating is by `versionNumber` (`major*1000000 + minor*1000 + patch`), so a\n * capability is gated at the exact release that shipped it. Each gate is the\n * release named in SQLite's own change log for that feature.\n */\nexport function detectSqliteCapabilities(version: SqliteVersion): SqliteCapabilities {\n const atLeast = (target: number): boolean => version.versionNumber >= target;\n return {\n supportsWithoutRowid: atLeast(3_008_002),\n supportsMultiRowValues: atLeast(3_007_011),\n supportsPragmaFunctions: atLeast(3_016_000),\n supportsTableXinfo: atLeast(3_026_000),\n supportsGeneratedColumns: atLeast(3_031_000),\n supportsSqliteSchemaAlias: atLeast(3_033_000),\n supportsWritableSchemaReset: atLeast(3_035_000),\n supportsStrictTables: atLeast(3_037_000),\n supportsTableList: atLeast(3_037_000),\n };\n}\n","/**\n * SQLite's keywords, as `sqlite3_keyword_check()` reports them in a default\n * build (the 147 listed at https://sqlite.org/lang_keywords.html).\n *\n * The native `.dump` quotes a table or column name only when it has to —\n * when it is not a plain `[A-Za-z_][A-Za-z0-9_]*` identifier, or when it is\n * one of these words — and reproducing its output byte for byte means\n * making exactly the same decision.\n */\nconst SQLITE_KEYWORDS: ReadonlySet<string> = new Set(\n `ABORT ACTION ADD AFTER ALL ALTER ALWAYS ANALYZE AND AS ASC ATTACH AUTOINCREMENT BEFORE BEGIN\n BETWEEN BY CASCADE CASE CAST CHECK COLLATE COLUMN COMMIT CONFLICT CONSTRAINT CREATE CROSS\n CURRENT CURRENT_DATE CURRENT_TIME CURRENT_TIMESTAMP DATABASE DEFAULT DEFERRABLE DEFERRED DELETE\n DESC DETACH DISTINCT DO DROP EACH ELSE END ESCAPE EXCEPT EXCLUDE EXCLUSIVE EXISTS EXPLAIN FAIL\n FILTER FIRST FOLLOWING FOR FOREIGN FROM FULL GENERATED GLOB GROUP GROUPS HAVING IF IGNORE\n IMMEDIATE IN INDEX INDEXED INITIALLY INNER INSERT INSTEAD INTERSECT INTO IS ISNULL JOIN KEY LAST\n LEFT LIKE LIMIT MATCH MATERIALIZED NATURAL NO NOT NOTHING NOTNULL NULL NULLS OF OFFSET ON OR\n ORDER OTHERS OUTER OVER PARTITION PLAN PRAGMA PRECEDING PRIMARY QUERY RAISE RANGE RECURSIVE\n REFERENCES REGEXP REINDEX RELEASE RENAME REPLACE RESTRICT RETURNING RIGHT ROLLBACK ROW ROWS\n SAVEPOINT SELECT SET TABLE TEMP TEMPORARY THEN TIES TO TRANSACTION TRIGGER UNBOUNDED UNION\n UNIQUE UPDATE USING VACUUM VALUES VIEW VIRTUAL WHEN WHERE WINDOW WITH WITHOUT`\n .split(/\\s+/)\n .filter(word => word !== ''),\n);\n\n/** True when `name` is an SQLite keyword, compared case-insensitively as SQLite does. */\nexport function isSqliteKeyword(name: string): boolean {\n return SQLITE_KEYWORDS.has(toAsciiUpperCase(name));\n}\n\n/** The number of keywords known to {@link isSqliteKeyword}; exported for tests. */\nexport const SQLITE_KEYWORD_COUNT = SQLITE_KEYWORDS.size;\n\nfunction isAsciiAlpha(code: number): boolean {\n return (code >= 0x41 && code <= 0x5a) || (code >= 0x61 && code <= 0x7a);\n}\n\nfunction isAsciiDigit(code: number): boolean {\n return code >= 0x30 && code <= 0x39;\n}\n\n/**\n * Upper-cases ASCII letters only, which is how SQLite compares identifiers\n * and keywords: its case folding is ASCII-only (`sqlite3UpperToLower`), so\n * `ß` and `Dž` are never folded and a locale-aware `toUpperCase()` would\n * disagree with the engine.\n */\nexport function toAsciiUpperCase(value: string): string {\n return value.replace(/[a-z]+/g, run => run.toUpperCase());\n}\n\n/** Lower-cases ASCII letters only; see {@link toAsciiUpperCase}. */\nexport function toAsciiLowerCase(value: string): string {\n return value.replace(/[A-Z]+/g, run => run.toLowerCase());\n}\n\n/**\n * Whether the native shell would quote `name`, and with what — a port of\n * `quoteChar()` from SQLite's `shell.c`:\n *\n * ```c\n * if( !IsAlpha(zName[0]) && zName[0]!='_' ) return '\"';\n * for(i=0; zName[i]; i++){\n * if( !IsAlnum(zName[i]) && zName[i]!='_' ) return '\"';\n * }\n * return sqlite3_keyword_check(zName, i) ? '\"' : 0;\n * ```\n *\n * `IsAlpha`/`IsAlnum` are the C-locale classifications, so any non-ASCII\n * character forces quoting.\n */\nexport function needsIdentifierQuoting(name: string): boolean {\n if (name.length === 0) {\n return true;\n }\n const first = name.charCodeAt(0);\n if (!isAsciiAlpha(first) && first !== 0x5f) {\n return true;\n }\n for (let index = 0; index < name.length; index++) {\n const code = name.charCodeAt(index);\n if (!isAsciiAlpha(code) && !isAsciiDigit(code) && code !== 0x5f) {\n return true;\n }\n }\n return isSqliteKeyword(name);\n}\n\n/**\n * Double-quotes an identifier, doubling any embedded `\"`. Always quotes.\n *\n * Used for every query this package *runs*. Quoting unconditionally there\n * removes the whole question of which words are reserved in which SQLite\n * release; the output-shaping decision, where the native layout matters, is\n * {@link quoteIdentifierIfNeeded}.\n */\nexport function quoteIdentifier(name: string): string {\n return `\"${name.replace(/\"/g, '\"\"')}\"`;\n}\n\n/**\n * Quotes an identifier exactly when the native `.dump` would\n * ({@link needsIdentifierQuoting}), so `INSERT INTO t` stays unquoted while\n * `INSERT INTO \"order\"` and `INSERT INTO \"a b\"` are quoted.\n */\nexport function quoteIdentifierIfNeeded(name: string): string {\n return needsIdentifierQuoting(name) ? quoteIdentifier(name) : name;\n}\n\n/** `\"schema\".\"name\"`, for queries against an attached database. */\nexport function quoteQualifiedIdentifier(schemaName: string, name: string): string {\n return `${quoteIdentifier(schemaName)}.${quoteIdentifier(name)}`;\n}\n","import { toAsciiLowerCase } from '../security/identifiers.js';\nimport type { DumpSelection, NormalizedDumpSelection } from './types.js';\n\n/** Folds a name the way SQLite compares identifiers: ASCII letters only. */\nexport function foldSqliteName(name: string): string {\n return toAsciiLowerCase(name);\n}\n\nfunction toSet(names: readonly string[] | undefined): ReadonlySet<string> | undefined {\n return names ? new Set(names.map(foldSqliteName)) : undefined;\n}\n\nexport function normalizeDumpSelection(selection?: DumpSelection): NormalizedDumpSelection {\n const normalized = {\n tables: toSet(selection?.tables),\n excludeTables: new Set((selection?.excludeTables ?? []).map(foldSqliteName)),\n views: toSet(selection?.views),\n excludeViews: new Set((selection?.excludeViews ?? []).map(foldSqliteName)),\n triggers: toSet(selection?.triggers),\n excludeTriggers: new Set((selection?.excludeTriggers ?? []).map(foldSqliteName)),\n excludeIndexes: new Set((selection?.excludeIndexes ?? []).map(foldSqliteName)),\n dataExcludedTables: new Set((selection?.dataExcludedTables ?? []).map(foldSqliteName)),\n };\n const isPartial =\n normalized.tables !== undefined ||\n normalized.views !== undefined ||\n normalized.triggers !== undefined ||\n normalized.excludeTables.size > 0 ||\n normalized.excludeViews.size > 0 ||\n normalized.excludeTriggers.size > 0 ||\n normalized.excludeIndexes.size > 0;\n return { ...normalized, isPartial };\n}\n\nfunction isSelected(\n name: string,\n include: ReadonlySet<string> | undefined,\n exclude: ReadonlySet<string>,\n): boolean {\n const key = foldSqliteName(name);\n if (exclude.has(key)) {\n return false;\n }\n return include ? include.has(key) : true;\n}\n\nexport function isTableSelected(name: string, selection: NormalizedDumpSelection): boolean {\n return isSelected(name, selection.tables, selection.excludeTables);\n}\n\nexport function isViewSelected(name: string, selection: NormalizedDumpSelection): boolean {\n return isSelected(name, selection.views, selection.excludeViews);\n}\n\nexport function isTriggerSelected(name: string, selection: NormalizedDumpSelection): boolean {\n return isSelected(name, selection.triggers, selection.excludeTriggers);\n}\n\nexport function isIndexSelected(name: string, selection: NormalizedDumpSelection): boolean {\n return !selection.excludeIndexes.has(foldSqliteName(name));\n}\n\n/** True when the table's *rows* should be skipped while its structure is still dumped. */\nexport function isTableDataExcluded(name: string, selection: NormalizedDumpSelection): boolean {\n return selection.dataExcludedTables.has(foldSqliteName(name));\n}\n","/**\n * SQL literal rendering, ported from the functions SQLite's own shell uses\n * for `.dump` (`shell.c`), so a value renders exactly as `sqlite3` renders\n * it.\n *\n * SQLite string literals have exactly one escape: a `'` inside the literal\n * is doubled. There are **no** backslash escapes — `'\\n'` is a backslash\n * followed by the letter `n` — which is why the shell cannot write a newline\n * as `\\n` and instead wraps the literal in a `replace()` call (see\n * {@link renderEscapedStringLiteral}).\n *\n * Every function here works on a JavaScript string in which each code unit\n * may be either a real character or — for text that is not valid UTF-8 — one\n * byte (a `latin1` \"byte string\"). The characters the escaping reacts to\n * (`'`, `\\n`, `\\r`) are ASCII, and no byte of a multi-byte UTF-8 sequence can\n * be mistaken for one, so the same code is correct for both representations.\n */\n\n/**\n * `unused_string()` from `shell.c`: returns the first of `a`, `b`, `(a0)`,\n * `(a1)`, ... that does not occur anywhere in `text`, to stand in for a\n * character inside a `replace()`d literal without colliding with the text.\n */\nfunction unusedString(text: string, a: string, b: string): string {\n if (!text.includes(a)) {\n return a;\n }\n if (!text.includes(b)) {\n return b;\n }\n for (let counter = 0; ; counter++) {\n const candidate = `(${a}${counter})`;\n if (!text.includes(candidate)) {\n return candidate;\n }\n }\n}\n\n/**\n * `output_quoted_string()`: `'...'` with every `'` doubled, newlines and\n * carriage returns written raw. The shell uses this form under\n * `.dump --newlines`.\n */\nexport function renderQuotedStringLiteral(text: string): string {\n return `'${text.replace(/'/g, \"''\")}'`;\n}\n\n/**\n * `output_quoted_escaped_string()`: the form the native `.dump` uses by\n * default.\n *\n * A literal containing neither `\\n` nor `\\r` is written as a plain quoted\n * string. Otherwise each newline is replaced by a placeholder that does not\n * otherwise occur in the text (`\\n`, else `\\012`, else `(\\n0)`, ...) and the\n * literal is wrapped in `replace(..., '<placeholder>', char(10))` — and the\n * same for carriage returns with `char(13)` — so that the dump keeps one\n * statement per line and survives any tool that normalizes line endings.\n *\n * ```sql\n * replace('line one\\nline two','\\n',char(10))\n * replace(replace('a\\r\\nb','\\r',char(13)),'\\n',char(10))\n * ```\n */\nexport function renderEscapedStringLiteral(text: string): string {\n if (!text.includes('\\n') && !text.includes('\\r')) {\n return renderQuotedStringLiteral(text);\n }\n const hasNewline = text.includes('\\n');\n const hasCarriageReturn = text.includes('\\r');\n const newlinePlaceholder = hasNewline ? unusedString(text, '\\\\n', '\\\\012') : '';\n const carriageReturnPlaceholder = hasCarriageReturn ? unusedString(text, '\\\\r', '\\\\015') : '';\n\n let body = '';\n for (let index = 0; index < text.length; index++) {\n const character = text[index] as string;\n if (character === \"'\") {\n body += \"''\";\n } else if (character === '\\n') {\n body += newlinePlaceholder;\n } else if (character === '\\r') {\n body += carriageReturnPlaceholder;\n } else {\n body += character;\n }\n }\n\n // The opening `replace(`s are written newline-first, the closing\n // arguments carriage-return-first, exactly as the shell nests them.\n let literal = `${hasNewline ? 'replace(' : ''}${hasCarriageReturn ? 'replace(' : ''}'${body}'`;\n if (hasCarriageReturn) {\n literal += `,'${carriageReturnPlaceholder}',char(13))`;\n }\n if (hasNewline) {\n literal += `,'${newlinePlaceholder}',char(10))`;\n }\n return literal;\n}\n\nexport type TextLiteralStyle = 'escaped' | 'raw-newlines';\n\n/**\n * Renders a `TEXT` value as a SQL expression.\n *\n * SQLite text may contain `NUL` characters, which the native shell cannot\n * represent at all: it handles values as C strings, so everything after the\n * first `NUL` is silently dropped from the dump. This package keeps them,\n * joining the pieces with `||char(0)||` — an expression that evaluates to\n * the identical value in a database of any text encoding. Text with no\n * `NUL`, which is all text in practice, renders exactly as the shell renders\n * it.\n */\nexport function renderTextLiteral(text: string, style: TextLiteralStyle = 'escaped'): string {\n const render = style === 'escaped' ? renderEscapedStringLiteral : renderQuotedStringLiteral;\n if (!text.includes('\\u0000')) {\n return render(text);\n }\n return text.split('\\u0000').map(render).join('||char(0)||');\n}\n\n/**\n * `output_hex_blob()`: `X'...'` in lower-case hexadecimal, which is how the\n * native `.dump` writes every `BLOB`. An empty blob is `X''`.\n */\nexport function renderBlobLiteral(value: Uint8Array): string {\n return `X'${Buffer.from(value.buffer, value.byteOffset, value.byteLength).toString('hex')}'`;\n}\n\n/**\n * Renders a string as a plain single-quoted SQL literal, for text this\n * package composes itself (table names in `INSERT INTO sqlite_schema ...`,\n * `sqlite_sequence` filters).\n */\nexport function quoteStringLiteral(text: string): string {\n return renderQuotedStringLiteral(text);\n}\n","/**\n * Redacts the value side of the credential-carrying statements that exist\n * in the SQLite world, so a failing statement never echoes an actual secret\n * into a preview, a diagnostic, or an error message.\n *\n * Plain SQLite has no credentials, but the encryption extensions most\n * applications use — SQLCipher and the SQLite Encryption Extension — take\n * their key through SQL: `PRAGMA key = '...'`, `PRAGMA rekey`,\n * `PRAGMA hexkey`/`hexrekey`, `PRAGMA textkey`, and `ATTACH ... KEY '...'`.\n * A script that opens an encrypted database starts with exactly such a\n * statement.\n *\n * Deliberately narrow and pattern-based rather than a parser: it covers the\n * specific syntax those extensions use, not arbitrary \"looks sensitive\" text.\n */\nconst SQL_SECRET_PATTERNS: readonly RegExp[] = [\n // PRAGMA [schema.]key = 'secret' / PRAGMA key('secret'), and the rekey/hexkey/textkey forms\n /(\\bPRAGMA\\s+(?:[\\w\"`[\\]]+\\s*\\.\\s*)?(?:hex|text)?(?:re)?key\\s*(?:=\\s*|\\(\\s*))(?:'(?:[^']|'')*'|\"(?:[^\"]|\"\")*\"|[^\\s;)]+)/gi,\n // ATTACH DATABASE 'file' AS name KEY 'secret'\n /(\\bATTACH\\b[\\s\\S]*?\\bKEY\\s+)(?:'(?:[^']|'')*'|\"(?:[^\"]|\"\")*\"|X'[0-9A-Fa-f]*'|[^\\s;)]+)/gi,\n];\n\nexport function redactSecrets(text: string): string {\n return SQL_SECRET_PATTERNS.reduce(\n (result, pattern) =>\n result.replace(pattern, (_match, prefix: string) => `${prefix}'***REDACTED***'`),\n text,\n );\n}\n","import type { Writable } from 'node:stream';\nimport type { DumpWriter } from './types.js';\n\nfunction throwIfAborted(signal: AbortSignal | undefined): void {\n if (signal?.aborted) {\n throw new DOMException('The operation was aborted.', 'AbortError');\n }\n}\n\n/**\n * Writes incrementally to a caller-owned `Writable`, honoring backpressure\n * (awaiting the stream's own `drain` when `write()` returns `false`) and\n * `AbortSignal` cancellation. Never calls `end()`/`close()` on the stream.\n *\n * `Buffer` chunks are written verbatim; `string` chunks are encoded as\n * UTF-8. See {@link DumpWriter} for why both shapes exist.\n */\nexport class StreamDumpWriter implements DumpWriter {\n private readonly stream: Writable;\n private bytes = 0;\n private writeError: Error | null = null;\n\n constructor(stream: Writable) {\n this.stream = stream;\n }\n\n get bytesWritten(): number {\n return this.bytes;\n }\n\n async write(chunk: string | Buffer, signal?: AbortSignal): Promise<void> {\n if (chunk.length === 0) {\n return;\n }\n if (this.writeError) {\n throw this.writeError;\n }\n throwIfAborted(signal);\n\n const isBuffer = Buffer.isBuffer(chunk);\n this.bytes += isBuffer ? chunk.length : Buffer.byteLength(chunk, 'utf8');\n\n const onWritten = (error?: Error | null): void => {\n if (error && !this.writeError) {\n this.writeError = error;\n }\n };\n\n // Backpressure is gated on `write()`'s return value, with the `drain`\n // listener attached in this same tick. Awaiting the completion callback\n // first would be wrong: Node emits `drain` *before* running the callbacks\n // of the writes that emptied the buffer, so subscribing afterwards waits\n // for an event that has already fired and never fires again.\n const canWriteMore = isBuffer\n ? this.stream.write(chunk, onWritten)\n : this.stream.write(chunk, 'utf8', onWritten);\n\n if (canWriteMore === false) {\n await new Promise<void>((resolve, reject) => {\n const cleanup = (): void => {\n this.stream.removeListener('drain', onDrain);\n this.stream.removeListener('error', onError);\n signal?.removeEventListener('abort', onAbort);\n };\n const onDrain = (): void => {\n cleanup();\n resolve();\n };\n const onError = (error: Error): void => {\n cleanup();\n reject(error);\n };\n // A consumer that stopped reading never emits `drain`, so this await is\n // exactly where a cancelled dump would otherwise stall indefinitely.\n const onAbort = (): void => {\n cleanup();\n reject(new DOMException('The operation was aborted.', 'AbortError'));\n };\n this.stream.once('drain', onDrain);\n this.stream.once('error', onError);\n signal?.addEventListener('abort', onAbort, { once: true });\n });\n }\n\n if (this.writeError) {\n throw this.writeError;\n }\n throwIfAborted(signal);\n }\n}\n","import type { DumpWriter } from './types.js';\n\n/**\n * In-memory {@link DumpWriter}, for tests and bounded previews. Not for\n * production dump sizes.\n *\n * Accumulates `Buffer`s rather than strings so a dump containing text that\n * is not valid UTF-8 round-trips byte-exactly; {@link toString} is a\n * convenience for the common all-text case and will replace invalid UTF-8\n * with U+FFFD, so use {@link toBuffer} when binary fidelity matters.\n */\nexport class BufferDumpWriter implements DumpWriter {\n private readonly chunks: Buffer[] = [];\n private bytes = 0;\n\n get bytesWritten(): number {\n return this.bytes;\n }\n\n async write(chunk: string | Buffer, signal?: AbortSignal): Promise<void> {\n if (signal?.aborted) {\n throw new DOMException('The operation was aborted.', 'AbortError');\n }\n const buffer = Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk, 'utf8');\n this.chunks.push(buffer);\n this.bytes += buffer.length;\n }\n\n toBuffer(): Buffer {\n return Buffer.concat(this.chunks);\n }\n\n toString(): string {\n return this.toBuffer().toString('utf8');\n }\n}\n","import type { ArchiveObjectType, DumpSection } from './types.js';\n\nconst SECTION_BY_OBJECT_TYPE: Record<ArchiveObjectType, DumpSection> = {\n table: 'tables',\n tableData: 'tables',\n virtualTable: 'tables',\n index: 'schema',\n trigger: 'schema',\n view: 'schema',\n};\n\nconst SECTION_PRIORITY: Record<DumpSection, number> = {\n tables: 0,\n schema: 1,\n};\n\n/**\n * Ordering *within* one table's group in the `tables` section: structure,\n * then rows — the native `.dump` writes each table's `INSERT`s directly\n * after its `CREATE TABLE`.\n */\nconst TABLE_GROUP_PRIORITY: Record<ArchiveObjectType, number> = {\n table: 0,\n virtualTable: 0,\n tableData: 1,\n index: 0,\n trigger: 0,\n view: 0,\n};\n\nexport function assignDumpSection(objectType: ArchiveObjectType): DumpSection {\n return SECTION_BY_OBJECT_TYPE[objectType];\n}\n\nexport function dumpSectionPriority(section: DumpSection): number {\n return SECTION_PRIORITY[section];\n}\n\nexport function tableGroupPriority(objectType: ArchiveObjectType): number {\n return TABLE_GROUP_PRIORITY[objectType];\n}\n","import { createHash } from 'node:crypto';\n\n/**\n * Builds a collision-resistant identity string from ordered parts.\n *\n * Parts are length-prefixed rather than joined with a separator, because\n * SQLite identifiers may contain any character at all — including\n * whatever separator would otherwise be chosen. Without the prefix,\n * `[\"a.b\", \"c\"]` and `[\"a\", \"b.c\"]` would produce the same identity.\n */\nexport function createCanonicalIdentity(parts: readonly string[]): string {\n return parts.map(part => `${part.length}:${part}`).join('|');\n}\n\n/** Stable short hash of a canonical identity, used as an archive entry's `dumpId`. */\nexport function createDumpId(identity: string): string {\n return createHash('sha1').update(identity, 'utf8').digest('hex').slice(0, 16);\n}\n","import { createCanonicalIdentity } from '../utils/hash.js';\nimport type { ArchiveObjectType } from './types.js';\n\nexport interface ArchiveIdentityInput {\n readonly objectType: ArchiveObjectType;\n readonly schemaName: string;\n readonly name: string;\n readonly parentName?: string;\n}\n\nexport function createArchiveIdentity(input: ArchiveIdentityInput): string {\n return createCanonicalIdentity([\n input.objectType,\n input.schemaName,\n input.name,\n input.parentName ?? '',\n ]);\n}\n","import type { SqliteDatabase, SqliteTable } from '../model/database.js';\nimport type { SqliteDiagnostic } from '../model/diagnostics.js';\nimport {\n foldSqliteName,\n isIndexSelected,\n isTableDataExcluded,\n isTableSelected,\n isTriggerSelected,\n isViewSelected,\n normalizeDumpSelection,\n} from '../selection/normalize.js';\nimport type { DumpObjectKinds, NormalizedDumpSelection } from '../selection/types.js';\nimport { createDumpId } from '../utils/hash.js';\nimport { createArchiveIdentity } from './identity.js';\nimport { assignDumpSection } from './sectionRules.js';\nimport type {\n ArchiveCycle,\n ArchiveDependency,\n ArchiveEntry,\n ArchiveObjectType,\n DumpArchiveInspection,\n DumpMode,\n UnsatisfiedDependency,\n} from './types.js';\n\nexport interface InspectDumpArchiveOptions {\n readonly mode?: DumpMode;\n readonly selection?: NormalizedDumpSelection;\n readonly objectKinds?: DumpObjectKinds;\n}\n\ninterface MutableEntry {\n dumpId: string;\n identity: string;\n objectType: ArchiveObjectType;\n name: string;\n parentName?: string;\n tableKind?: SqliteTable['kind'];\n systemRowFilter?: readonly string[];\n dependsOn: ArchiveDependency[];\n}\n\n/** `sqlite3_strglob(\"sqlite_stat?\", name)` — the tables `ANALYZE` maintains. */\nexport function isStatisticsTableName(name: string): boolean {\n return /^sqlite_stat[\\s\\S]$/.test(name);\n}\n\n/** The native shell compares this name with `strcmp`, so case-sensitively. */\nexport const SEQUENCE_TABLE_NAME = 'sqlite_sequence';\n\n/**\n * Converts a normalized {@link SqliteDatabase} into an ordered,\n * dependency-validated set of {@link ArchiveEntry} objects.\n *\n * Independent of SQL text, output streams and connections: it decides only\n * *what* is dumped and in *what order*. The order is the native `.dump`'s —\n * see {@link DumpSection} — which is creation order (`sqlite_schema` rowid)\n * rather than a topological sort. Creation order is itself a valid\n * dependency order for everything SQLite checks at `CREATE` time, and the\n * dump's `PRAGMA foreign_keys=OFF` covers the rest. Dependencies are still\n * recorded and then *verified* against that order, so a model or planning\n * bug surfaces as `valid: false` rather than as an unrestorable dump.\n */\nexport function inspectDumpArchive(\n database: SqliteDatabase,\n options: InspectDumpArchiveOptions = {},\n): DumpArchiveInspection {\n const mode = options.mode ?? 'full';\n const selection = options.selection ?? normalizeDumpSelection();\n const kinds = options.objectKinds ?? {};\n const includeTables = kinds.includeTables ?? true;\n const includeViews = kinds.includeViews ?? true;\n const includeIndexes = kinds.includeIndexes ?? true;\n const includeTriggers = kinds.includeTriggers ?? true;\n const includeVirtualTables = kinds.includeVirtualTables ?? true;\n const includeSystemTables = kinds.includeSystemTables ?? true;\n\n const wantsSchema = mode !== 'data-only';\n const wantsData = mode !== 'schema-only';\n const schemaName = database.schemaName;\n\n const diagnostics: SqliteDiagnostic[] = [];\n const entries: MutableEntry[] = [];\n const byDumpId = new Map<string, MutableEntry>();\n\n function addEntry(\n objectType: ArchiveObjectType,\n name: string,\n extra: Partial<Pick<MutableEntry, 'parentName' | 'tableKind' | 'systemRowFilter'>> = {},\n ): string {\n const identity = createArchiveIdentity({\n objectType,\n schemaName,\n name,\n ...(extra.parentName === undefined ? {} : { parentName: extra.parentName }),\n });\n const dumpId = createDumpId(identity);\n if (byDumpId.has(dumpId)) {\n diagnostics.push({\n severity: 'error',\n code: 'duplicate-archive-identity',\n message: `Duplicate archive identity for ${objectType} \"${name}\" in schema \"${schemaName}\"`,\n objectReference: { kind: 'table', schemaName, name },\n });\n return dumpId;\n }\n const entry: MutableEntry = { dumpId, identity, objectType, name, ...extra, dependsOn: [] };\n entries.push(entry);\n byDumpId.set(dumpId, entry);\n return dumpId;\n }\n\n function addDependency(\n fromDumpId: string,\n toDumpId: string | undefined,\n strength: ArchiveDependency['strength'],\n ): void {\n if (!toDumpId || fromDumpId === toDumpId) {\n return;\n }\n const entry = byDumpId.get(fromDumpId);\n if (!entry) {\n return;\n }\n const existing = entry.dependsOn.find(dependency => dependency.targetDumpId === toDumpId);\n if (existing) {\n if (strength === 'hard' && existing.strength === 'preference') {\n entry.dependsOn = entry.dependsOn.filter(\n dependency => dependency.targetDumpId !== toDumpId,\n );\n entry.dependsOn.push({ targetDumpId: toDumpId, strength: 'hard' });\n }\n return;\n }\n entry.dependsOn.push({ targetDumpId: toDumpId, strength });\n }\n\n const tablesByName = new Map(database.tables.map(table => [foldSqliteName(table.name), table]));\n\n const isUserTableSelected = (table: SqliteTable): boolean => {\n switch (table.kind) {\n case 'table':\n return includeTables && isTableSelected(table.name, selection);\n case 'virtual':\n return includeVirtualTables && isTableSelected(table.name, selection);\n case 'shadow': {\n // A shadow table belongs to its virtual table and follows it: it is\n // the virtual table's data. Selecting `ft` selects `ft_data`,\n // `ft_idx`, ... too, just as the native `.dump ft` does.\n const owner =\n table.ownerVirtualTable === undefined\n ? undefined\n : tablesByName.get(foldSqliteName(table.ownerVirtualTable));\n if (!owner) {\n return includeTables && isTableSelected(table.name, selection);\n }\n return includeVirtualTables && isTableSelected(owner.name, selection);\n }\n case 'system':\n return false;\n }\n };\n\n const selectedUserTables = database.tables.filter(isUserTableSelected);\n const selectedTableNames = selectedUserTables.map(table => table.name);\n\n const tableDumpId = new Map<string, string>();\n const tableDataDumpId = new Map<string, string>();\n\n // Pass 1 — tables, in creation order, with sqlite_sequence last. This is\n // `ORDER BY tbl_name='sqlite_sequence', rowid`, the native query.\n const orderedTables = [...database.tables].sort((a, b) => {\n const aLast = a.name === SEQUENCE_TABLE_NAME ? 1 : 0;\n const bLast = b.name === SEQUENCE_TABLE_NAME ? 1 : 0;\n return aLast - bLast || a.schemaRowid - b.schemaRowid;\n });\n\n for (const table of orderedTables) {\n const key = foldSqliteName(table.name);\n\n if (table.kind === 'system') {\n const isSequence = table.name === SEQUENCE_TABLE_NAME;\n if (!includeSystemTables || (!isSequence && !isStatisticsTableName(table.name))) {\n // Any other `sqlite_` table is internal and never dumped natively either.\n continue;\n }\n const systemRowFilter = selection.isPartial ? selectedTableNames : undefined;\n if (systemRowFilter && systemRowFilter.length === 0) {\n continue;\n }\n const extra = {\n tableKind: table.kind,\n ...(systemRowFilter === undefined ? {} : { systemRowFilter }),\n };\n let structureId: string | undefined;\n if (wantsSchema && wantsData) {\n // `DELETE FROM sqlite_sequence;` / `ANALYZE sqlite_schema;` only make\n // sense together with the rows that follow them; a schema-only dump\n // carries neither counters nor statistics.\n structureId = addEntry('table', table.name, extra);\n tableDumpId.set(key, structureId);\n }\n if (wantsData) {\n const dataId = addEntry('tableData', table.name, { ...extra, parentName: table.name });\n tableDataDumpId.set(key, dataId);\n addDependency(dataId, structureId, 'hard');\n if (!wantsSchema) {\n diagnostics.push({\n severity: 'warning',\n code: 'data-only-system-table',\n message: isSequence\n ? 'A data-only dump inserts the sqlite_sequence rows without first clearing the table, exactly as the native .dump --data-only does; restoring it into a database whose tables already advanced their AUTOINCREMENT counters leaves duplicate counter rows. Set objectKinds.includeSystemTables to false to leave the counters to the inserts themselves.'\n : `A data-only dump inserts into ${table.name} without creating it first, exactly as the native .dump --data-only does; restoring it into a database that has never been analyzed fails with \"no such table\". Set objectKinds.includeSystemTables to false to leave statistics out.`,\n objectReference: { kind: 'table', schemaName, name: table.name },\n });\n }\n }\n continue;\n }\n\n if (!isUserTableSelected(table)) {\n continue;\n }\n\n if (table.kind === 'virtual') {\n if (wantsSchema) {\n tableDumpId.set(key, addEntry('virtualTable', table.name, { tableKind: table.kind }));\n } else if (!isTableDataExcluded(table.name, selection)) {\n // A native quirk reproduced on purpose: `.dump --data-only` checks\n // for data-only *before* it checks for a virtual table, so it selects\n // the virtual table's rows through the module — in addition to the\n // shadow tables' rows, which hold the same data.\n tableDataDumpId.set(\n key,\n addEntry('tableData', table.name, { tableKind: table.kind, parentName: table.name }),\n );\n diagnostics.push({\n severity: 'warning',\n code: 'data-only-virtual-table',\n message: `A data-only dump carries the rows of virtual table \"${table.name}\" twice — through the table itself and in its shadow tables — exactly as the native .dump --data-only does. Restoring it into a database where \"${table.name}\" already exists conflicts with that table's own shadow rows; exclude the shadow tables through selection.dataExcludedTables to load the rows through the virtual table only.`,\n objectReference: { kind: 'virtualTable', schemaName, name: table.name },\n });\n }\n continue;\n }\n\n if (table.kind === 'shadow' && !wantsData && table.ownerVirtualTable !== undefined) {\n // A schema-only dump creates each virtual table through its module,\n // whose constructor creates the shadow tables itself (see the\n // renderer); defensive mode would refuse them as statements anyway.\n continue;\n }\n\n let structureId: string | undefined;\n if (wantsSchema) {\n structureId = addEntry('table', table.name, { tableKind: table.kind });\n tableDumpId.set(key, structureId);\n if (table.kind === 'shadow' && table.ownerVirtualTable !== undefined) {\n addDependency(\n structureId,\n tableDumpId.get(foldSqliteName(table.ownerVirtualTable)),\n 'preference',\n );\n }\n }\n if (wantsData && !isTableDataExcluded(table.name, selection)) {\n const dataId = addEntry('tableData', table.name, {\n tableKind: table.kind,\n parentName: table.name,\n });\n tableDataDumpId.set(key, dataId);\n addDependency(dataId, structureId, 'hard');\n }\n }\n\n // Foreign keys are recorded as *preferences* only: the dump's\n // `PRAGMA foreign_keys=OFF` makes any table order restorable, which is\n // precisely what makes circular foreign keys work.\n for (const foreignKey of database.foreignKeys) {\n const from = tableDumpId.get(foldSqliteName(foreignKey.tableName));\n const to = tableDumpId.get(foldSqliteName(foreignKey.referencedTableName));\n if (from && to) {\n addDependency(from, to, 'preference');\n }\n }\n\n // Pass 2 — indexes, triggers and views, in creation order.\n if (wantsSchema) {\n const selectedViewNames = new Set(\n includeViews\n ? database.views\n .filter(view => isViewSelected(view.name, selection))\n .map(view => foldSqliteName(view.name))\n : [],\n );\n const viewDumpId = new Map<string, string>();\n\n type SchemaObject =\n | { kind: 'index'; schemaRowid: number; index: SqliteDatabase['indexes'][number] }\n | { kind: 'trigger'; schemaRowid: number; trigger: SqliteDatabase['triggers'][number] }\n | { kind: 'view'; schemaRowid: number; view: SqliteDatabase['views'][number] };\n\n const objects: SchemaObject[] = [\n ...database.indexes.map(index => ({\n kind: 'index' as const,\n schemaRowid: index.schemaRowid,\n index,\n })),\n ...database.triggers.map(trigger => ({\n kind: 'trigger' as const,\n schemaRowid: trigger.schemaRowid,\n trigger,\n })),\n ...database.views.map(view => ({\n kind: 'view' as const,\n schemaRowid: view.schemaRowid,\n view,\n })),\n ].sort((a, b) => a.schemaRowid - b.schemaRowid);\n\n for (const object of objects) {\n switch (object.kind) {\n case 'index': {\n const { index } = object;\n // An automatic index (UNIQUE / PRIMARY KEY) has no DDL of its own;\n // the table's CREATE TABLE recreates it.\n if (index.sql === null || !includeIndexes || !isIndexSelected(index.name, selection)) {\n continue;\n }\n const tableId = tableDumpId.get(foldSqliteName(index.tableName));\n if (!tableId) {\n continue;\n }\n const dumpId = addEntry('index', index.name, { parentName: index.tableName });\n addDependency(dumpId, tableId, 'hard');\n // Building an index after the rows are loaded is faster, but not required.\n addDependency(dumpId, tableDataDumpId.get(foldSqliteName(index.tableName)), 'preference');\n break;\n }\n case 'trigger': {\n const { trigger } = object;\n if (!includeTriggers || !isTriggerSelected(trigger.name, selection)) {\n continue;\n }\n const parentKey = foldSqliteName(trigger.tableName);\n const parentId = tableDumpId.get(parentKey) ?? viewDumpId.get(parentKey);\n if (!parentId) {\n // Dropped rather than orphaned: a trigger cannot be created on a\n // table the dump will not create.\n diagnostics.push({\n severity: 'info',\n code: 'trigger-table-not-selected',\n message: `Trigger \"${trigger.name}\" is not dumped because its table \"${trigger.tableName}\" is not part of the dump`,\n objectReference: {\n kind: 'trigger',\n schemaName,\n name: trigger.name,\n parentName: trigger.tableName,\n },\n });\n continue;\n }\n const dumpId = addEntry('trigger', trigger.name, { parentName: trigger.tableName });\n addDependency(dumpId, parentId, 'hard');\n // Hard, not cosmetic: a trigger created before its table's rows are\n // loaded fires once per inserted row, fabricating side effects the\n // source database never had.\n addDependency(dumpId, tableDataDumpId.get(parentKey), 'hard');\n break;\n }\n case 'view': {\n const { view } = object;\n const key = foldSqliteName(view.name);\n if (!selectedViewNames.has(key)) {\n continue;\n }\n const dumpId = addEntry('view', view.name);\n viewDumpId.set(key, dumpId);\n // SQLite resolves a view's body when the view is used, not when it\n // is created, so tables and other views are only a preference.\n for (const tableId of tableDumpId.values()) {\n addDependency(dumpId, tableId, 'preference');\n }\n break;\n }\n }\n }\n }\n\n const { cycles, unsatisfiedDependencies } = validateOrder(entries);\n const valid =\n cycles.length === 0 &&\n unsatisfiedDependencies.length === 0 &&\n !diagnostics.some(diagnostic => diagnostic.severity === 'error');\n\n for (const cycle of cycles) {\n diagnostics.push({\n severity: 'error',\n code: 'archive-dependency-cycle',\n message: `Hard dependency cycle between archive entries: ${cycle.memberDumpIds.join(', ')}`,\n });\n }\n for (const violation of unsatisfiedDependencies) {\n diagnostics.push({\n severity: 'error',\n code: 'archive-order-violation',\n message: `Archive entry ${violation.fromDumpId} is emitted before its hard dependency ${violation.toDumpId}`,\n });\n }\n\n return {\n valid,\n entries: entries.map((entry, index) =>\n toArchiveEntry(entry, schemaName, valid ? index : undefined),\n ),\n diagnostics,\n cycles,\n unsatisfiedDependencies,\n };\n}\n\nfunction toArchiveEntry(\n entry: MutableEntry,\n schemaName: string,\n sequenceNumber: number | undefined,\n): ArchiveEntry {\n return {\n dumpId: entry.dumpId,\n identity: entry.identity,\n objectType: entry.objectType,\n section: assignDumpSection(entry.objectType),\n schemaName,\n name: entry.name,\n ...(entry.parentName === undefined ? {} : { parentName: entry.parentName }),\n ...(entry.tableKind === undefined ? {} : { tableKind: entry.tableKind }),\n ...(entry.systemRowFilter === undefined ? {} : { systemRowFilter: entry.systemRowFilter }),\n dependsOn: entry.dependsOn,\n ...(sequenceNumber === undefined ? {} : { sequenceNumber }),\n };\n}\n\n/**\n * Verifies the fixed emission order against the recorded hard dependencies,\n * and separately reports any hard cycle.\n *\n * This is a *check*, not a sort. The order is dictated by native\n * compatibility, so if a hard dependency points backwards the right answer\n * is to surface it rather than to reorder and hide the cause.\n */\nfunction validateOrder(ordered: readonly MutableEntry[]): {\n cycles: ArchiveCycle[];\n unsatisfiedDependencies: UnsatisfiedDependency[];\n} {\n const positionByDumpId = new Map(ordered.map((entry, index) => [entry.dumpId, index]));\n const unsatisfiedDependencies: UnsatisfiedDependency[] = [];\n\n for (const entry of ordered) {\n const fromPosition = positionByDumpId.get(entry.dumpId) as number;\n for (const dependency of entry.dependsOn) {\n if (dependency.strength !== 'hard') {\n continue;\n }\n const toPosition = positionByDumpId.get(dependency.targetDumpId);\n if (toPosition !== undefined && toPosition > fromPosition) {\n unsatisfiedDependencies.push({\n fromDumpId: entry.dumpId,\n toDumpId: dependency.targetDumpId,\n });\n }\n }\n }\n\n return { cycles: findHardCycles(ordered), unsatisfiedDependencies };\n}\n\nfunction byCodepoint(a: string, b: string): number {\n return a < b ? -1 : a > b ? 1 : 0;\n}\n\n/** Tarjan's strongly-connected components over hard edges only; any component of size > 1 is a cycle. */\nfunction findHardCycles(entries: readonly MutableEntry[]): ArchiveCycle[] {\n const indexByDumpId = new Map<string, number>();\n const lowLink = new Map<string, number>();\n const onStack = new Set<string>();\n const stack: string[] = [];\n const byDumpId = new Map(entries.map(entry => [entry.dumpId, entry]));\n const cycles: ArchiveCycle[] = [];\n let nextIndex = 0;\n\n const strongConnect = (dumpId: string): void => {\n indexByDumpId.set(dumpId, nextIndex);\n lowLink.set(dumpId, nextIndex);\n nextIndex++;\n stack.push(dumpId);\n onStack.add(dumpId);\n\n for (const dependency of byDumpId.get(dumpId)?.dependsOn ?? []) {\n if (dependency.strength !== 'hard' || !byDumpId.has(dependency.targetDumpId)) {\n continue;\n }\n const target = dependency.targetDumpId;\n if (!indexByDumpId.has(target)) {\n strongConnect(target);\n lowLink.set(dumpId, Math.min(lowLink.get(dumpId) as number, lowLink.get(target) as number));\n } else if (onStack.has(target)) {\n lowLink.set(\n dumpId,\n Math.min(lowLink.get(dumpId) as number, indexByDumpId.get(target) as number),\n );\n }\n }\n\n if (lowLink.get(dumpId) === indexByDumpId.get(dumpId)) {\n const component: string[] = [];\n for (;;) {\n const member = stack.pop() as string;\n onStack.delete(member);\n component.push(member);\n if (member === dumpId) {\n break;\n }\n }\n if (component.length > 1) {\n cycles.push({ memberDumpIds: component.sort(byCodepoint) });\n }\n }\n };\n\n for (const entry of entries) {\n if (!indexByDumpId.has(entry.dumpId)) {\n strongConnect(entry.dumpId);\n }\n }\n return cycles;\n}\n","/** Base class for every error this package throws intentionally. */\nexport class SqliteDumperError extends Error {\n readonly code: string;\n\n constructor(code: string, message: string, options?: { cause?: unknown }) {\n super(message, options);\n this.name = 'SqliteDumperError';\n this.code = code;\n }\n}\n\n/** Thrown when an operation stops because its `AbortSignal` was triggered. */\nexport class OperationCancelledError extends SqliteDumperError {\n constructor(message = 'The operation was cancelled') {\n super('operation-cancelled', message);\n this.name = 'OperationCancelledError';\n }\n}\n\nexport function throwIfAborted(signal: AbortSignal | undefined): void {\n if (signal?.aborted) {\n throw new OperationCancelledError();\n }\n}\n\n/**\n * True for both cancellation shapes this package can observe: its own\n * {@link OperationCancelledError} and the `DOMException` an `AbortSignal`\n * (or a Node stream aborted through one) raises.\n */\nexport function isAbortError(error: unknown): boolean {\n return (\n (error instanceof DOMException && error.name === 'AbortError') ||\n (error instanceof Error && error.name === 'OperationCancelledError')\n );\n}\n","/**\n * Small, deliberately conservative helpers for reading facts out of the\n * verbatim DDL SQLite keeps in `sqlite_schema.sql`, for the few facts no\n * catalog pragma reports on every supported version.\n */\n\n/**\n * Blanks out string literals, quoted identifiers and comments (keeping\n * their length), so a keyword search cannot match text *inside* them —\n * `DEFAULT 'AUTOINCREMENT'` is not an autoincrement column.\n */\nexport function maskSqlLiterals(sql: string): string {\n let output = '';\n let index = 0;\n while (index < sql.length) {\n const character = sql[index] as string;\n if (character === \"'\" || character === '\"' || character === '`' || character === '[') {\n const close = character === '[' ? ']' : character;\n let end = sql.indexOf(close, index + 1);\n end = end === -1 ? sql.length : end + 1;\n output += ' '.repeat(end - index);\n index = end;\n continue;\n }\n if (character === '-' && sql[index + 1] === '-') {\n let end = sql.indexOf('\\n', index);\n end = end === -1 ? sql.length : end;\n output += ' '.repeat(end - index);\n index = end;\n continue;\n }\n if (character === '/' && sql[index + 1] === '*') {\n let end = sql.indexOf('*/', index + 2);\n end = end === -1 ? sql.length : end + 2;\n output += ' '.repeat(end - index);\n index = end;\n continue;\n }\n output += character;\n index++;\n }\n return output;\n}\n\n/** `true` when the `CREATE TABLE` text declares an `AUTOINCREMENT` column. */\nexport function declaresAutoincrement(sql: string): boolean {\n return /\\bAUTOINCREMENT\\b/i.test(maskSqlLiterals(sql));\n}\n\n/**\n * Table options after the closing parenthesis of a `CREATE TABLE`\n * (`WITHOUT ROWID`, `STRICT`, in any combination). Used only when the\n * library is too old for `PRAGMA table_list`, which reports both directly.\n */\nexport function parseTableOptions(sql: string): { withoutRowid: boolean; strict: boolean } {\n const masked = maskSqlLiterals(sql);\n const close = masked.lastIndexOf(')');\n const tail = close === -1 ? '' : masked.slice(close + 1);\n return {\n withoutRowid: /\\bWITHOUT\\s+ROWID\\b/i.test(tail),\n strict: /\\bSTRICT\\b/i.test(tail),\n };\n}\n\n/** The module named in `CREATE VIRTUAL TABLE name USING module(...)`. */\nexport function parseVirtualTableModule(sql: string): string | undefined {\n const masked = maskSqlLiterals(sql);\n const match = /\\bUSING\\s+([A-Za-z0-9_$\\u0080-\\uffff]+)/i.exec(masked);\n return match\n ? sql.slice(match.index, match.index + match[0].length).replace(/^USING\\s+/i, '')\n : undefined;\n}\n","import { connectionFeatures, toNumber, toText } from '../connection/acquire.js';\nimport type { ResolvedConnectionFeatures } from '../connection/acquire.js';\nimport type { SqliteConnection, SqliteQuery, SqliteRow } from '../connection/types.js';\nimport type {\n SqliteColumn,\n SqliteColumnHidden,\n SqliteDatabase,\n SqliteForeignKey,\n SqliteIndex,\n SqliteIndexColumn,\n SqliteSequence,\n SqliteTable,\n SqliteTableKind,\n SqliteTrigger,\n SqliteView,\n} from '../model/database.js';\nimport type { SqliteDiagnostic } from '../model/diagnostics.js';\nimport { quoteIdentifier, toAsciiLowerCase, toAsciiUpperCase } from '../security/identifiers.js';\nimport { quoteStringLiteral } from '../security/literals.js';\nimport { isAbortError, SqliteDumperError, throwIfAborted } from '../utils/errors.js';\nimport { detectSqliteCapabilities } from '../version/capabilities.js';\nimport { detectSqliteVersion } from '../version/detect.js';\nimport type { SqliteCapabilities, SqliteVersion } from '../version/types.js';\nimport { declaresAutoincrement, parseTableOptions, parseVirtualTableModule } from './sqlText.js';\n\nexport interface IntrospectSqliteOptions {\n /**\n * Schema to introspect: `main` (default), `temp`, or the name of an\n * attached database.\n */\n readonly schemaName?: string;\n}\n\nexport interface SqliteIntrospectionResult {\n readonly database: SqliteDatabase;\n readonly version: SqliteVersion;\n readonly capabilities: SqliteCapabilities;\n readonly diagnostics: readonly SqliteDiagnostic[];\n}\n\ninterface SchemaRow {\n readonly schemaRowid: number;\n readonly type: string;\n readonly name: string;\n readonly tableName: string;\n readonly sql: string | null;\n}\n\n/**\n * Reads the complete schema of one SQLite database into a normalized\n * {@link SqliteDatabase}.\n *\n * Every object comes from `sqlite_schema` (read through its historical name\n * `sqlite_master`, which every release accepts), in rowid order — the order\n * the native `.dump` uses. Column, index and foreign-key detail comes from\n * the table-valued pragma functions where the library has them, falling back\n * to the plain `PRAGMA` statements otherwise.\n *\n * Runs entirely on the one handle it is given, in sequence, and never writes.\n * A handle that declares {@link SqliteConnection.features} restrictions is\n * read with the equivalent queries it does allow; one that has\n * {@link SqliteConnection.queryBatch} gets the per-table catalog in batches.\n */\nexport async function introspectSqlite(\n connection: SqliteConnection,\n options?: IntrospectSqliteOptions,\n signal?: AbortSignal,\n): Promise<SqliteIntrospectionResult> {\n const schemaName = options?.schemaName ?? 'main';\n const version = await detectSqliteVersion(connection, signal);\n const capabilities = detectSqliteCapabilities(version);\n const features = connectionFeatures(connection);\n const diagnostics: SqliteDiagnostic[] = [];\n if (!features.schemaQualifiedNames && toAsciiLowerCase(schemaName) !== 'main') {\n throw new SqliteDumperError(\n 'schema-not-found',\n `This connection can only read the main database, not ${JSON.stringify(schemaName)}`,\n );\n }\n const catalog = new CatalogReader(connection, schemaName, capabilities, features, signal);\n\n const allSchemaRows = await catalog.schemaRows();\n if (allSchemaRows === null) {\n throw new SqliteDumperError(\n 'schema-not-found',\n `No database named ${JSON.stringify(schemaName)} is attached to this connection`,\n );\n }\n const reserved = allSchemaRows.filter(row => isReservedRow(row, features.reservedNamePrefixes));\n const schemaRows = allSchemaRows.filter(row => !reserved.includes(row));\n if (reserved.length > 0) {\n diagnostics.push({\n severity: 'info',\n code: 'reserved-objects-skipped',\n message: `Left out ${reserved.length} object${reserved.length === 1 ? '' : 's'} the database engine reserves for itself and does not let clients read: ${reserved.map(row => JSON.stringify(row.name)).join(', ')}.`,\n });\n }\n\n const tableList = await catalog.tableList();\n const virtualTableNames = schemaRows\n .filter(row => row.type === 'table' && isVirtualTableSql(row.sql))\n .map(row => row.name);\n\n await catalog.prefetch(schemaRows);\n\n const tables: SqliteTable[] = [];\n const indexes: SqliteIndex[] = [];\n const foreignKeys: SqliteForeignKey[] = [];\n const indexRowsByName = new Map(\n schemaRows.filter(row => row.type === 'index').map(row => [toAsciiLowerCase(row.name), row]),\n );\n\n for (const row of schemaRows) {\n throwIfAborted(signal);\n if (row.type !== 'table' || row.sql === null) {\n continue;\n }\n const listed = tableList?.get(toAsciiLowerCase(row.name));\n const kind = classifyTable(row, listed?.type, virtualTableNames);\n\n let columns: SqliteColumn[] = [];\n try {\n columns = await catalog.columns(row.name);\n } catch (error) {\n if (isAbortError(error)) throw error;\n diagnostics.push({\n severity: kind === 'virtual' ? 'warning' : 'error',\n code: kind === 'virtual' ? 'virtual-table-module-unavailable' : 'table-columns-unreadable',\n message:\n kind === 'virtual'\n ? `The columns of virtual table \"${row.name}\" cannot be read, most likely because its module is not available in this SQLite build (${errorMessage(error)}). Its definition and its shadow tables are still dumped, which is all a restore needs.`\n : `The columns of table \"${row.name}\" cannot be read: ${errorMessage(error)}`,\n objectReference: {\n kind: kind === 'virtual' ? 'virtualTable' : 'table',\n schemaName,\n name: row.name,\n },\n });\n }\n\n const parsedOptions = parseTableOptions(row.sql);\n const withoutRowid = listed\n ? listed.withoutRowid\n : kind === 'table' || kind === 'shadow'\n ? parsedOptions.withoutRowid\n : false;\n const strict = listed ? listed.strict : parsedOptions.strict;\n\n let tableIndexes: SqliteIndex[] = [];\n let tableForeignKeys: SqliteForeignKey[] = [];\n if (kind !== 'virtual') {\n tableIndexes = await catalog.indexes(row.name, indexRowsByName);\n tableForeignKeys = await catalog.foreignKeys(row.name);\n }\n indexes.push(...tableIndexes);\n foreignKeys.push(...tableForeignKeys);\n\n const virtualModule = kind === 'virtual' ? parseVirtualTableModule(row.sql) : undefined;\n const ownerVirtualTable =\n kind === 'shadow' ? findOwner(row.name, virtualTableNames) : undefined;\n\n tables.push({\n name: row.name,\n kind,\n schemaRowid: row.schemaRowid,\n sql: row.sql,\n withoutRowid,\n strict,\n hasAutoincrement: kind === 'table' && declaresAutoincrement(row.sql),\n ...(virtualModule === undefined ? {} : { virtualModule }),\n ...(ownerVirtualTable === undefined ? {} : { ownerVirtualTable }),\n rowidAliasColumn:\n kind === 'virtual' || withoutRowid ? null : findRowidAlias(columns, tableIndexes),\n columns,\n });\n }\n\n // Indexes are attached to their table through the pragmas above; any\n // `CREATE INDEX` row whose table could not be read is still carried, so the\n // dump does not silently lose it.\n const seenIndexes = new Set(indexes.map(index => toAsciiLowerCase(index.name)));\n for (const row of schemaRows) {\n if (row.type === 'index' && row.sql !== null && !seenIndexes.has(toAsciiLowerCase(row.name))) {\n indexes.push({\n name: row.name,\n tableName: row.tableName,\n schemaRowid: row.schemaRowid,\n sql: row.sql,\n isUnique: /^CREATE\\s+UNIQUE\\b/i.test(row.sql),\n origin: 'c',\n isPartial: false,\n columns: [],\n });\n }\n }\n indexes.sort((a, b) => a.schemaRowid - b.schemaRowid);\n\n const views: SqliteView[] = schemaRows\n .filter(row => row.type === 'view' && row.sql !== null)\n .map(row => ({ name: row.name, schemaRowid: row.schemaRowid, sql: row.sql as string }));\n const triggers: SqliteTrigger[] = schemaRows\n .filter(row => row.type === 'trigger' && row.sql !== null)\n .map(row => ({\n name: row.name,\n tableName: row.tableName,\n schemaRowid: row.schemaRowid,\n sql: row.sql as string,\n }));\n\n const sequences = tables.some(table => table.name === 'sqlite_sequence')\n ? await catalog.sequences()\n : [];\n\n const settings = await catalog.settings();\n\n return {\n database: {\n schemaName,\n ...settings,\n tables,\n indexes,\n views,\n triggers,\n foreignKeys,\n sequences,\n },\n version,\n capabilities,\n diagnostics,\n };\n}\n\nfunction errorMessage(error: unknown): string {\n return error instanceof Error ? error.message : String(error);\n}\n\n/** Whether a `sqlite_schema` row is, or belongs to, an object named with a reserved prefix. */\nfunction isReservedRow(row: SchemaRow, prefixes: readonly string[]): boolean {\n if (prefixes.length === 0) {\n return false;\n }\n const names = [toAsciiLowerCase(row.name), toAsciiLowerCase(row.tableName)];\n return prefixes.some(prefix => {\n const lower = toAsciiLowerCase(prefix);\n return names.some(name => name.startsWith(lower));\n });\n}\n\n/** Queries per request handed to {@link SqliteConnection.queryBatch}. */\nconst PREFETCH_BATCH_SIZE = 50;\n\nfunction queryKey(query: SqliteQuery): string {\n return `${query.sql}\\u0000${JSON.stringify(query.parameters ?? [])}`;\n}\n\nfunction isVirtualTableSql(sql: string | null): boolean {\n // The native shell tests exactly this prefix (`strncmp`, case-sensitive);\n // SQLite normalizes the start of every stored CREATE statement, so it is\n // reliable.\n return sql !== null && sql.startsWith('CREATE VIRTUAL TABLE');\n}\n\nfunction classifyTable(\n row: SchemaRow,\n listedType: string | undefined,\n virtualTableNames: readonly string[],\n): SqliteTableKind {\n if (row.name.startsWith('sqlite_')) {\n return 'system';\n }\n if (isVirtualTableSql(row.sql)) {\n return 'virtual';\n }\n if (listedType !== undefined) {\n return listedType === 'shadow' ? 'shadow' : 'table';\n }\n // Without `PRAGMA table_list`, recognize shadow tables the way the native\n // `.dump` does when it expands a table pattern: by the `<vtab>_` prefix.\n return findOwner(row.name, virtualTableNames) === undefined ? 'table' : 'shadow';\n}\n\n/** The virtual table whose `<name>_` prefix `tableName` carries — the longest, if several do. */\nfunction findOwner(tableName: string, virtualTableNames: readonly string[]): string | undefined {\n const lower = toAsciiLowerCase(tableName);\n let owner: string | undefined;\n for (const name of virtualTableNames) {\n const prefix = `${toAsciiLowerCase(name)}_`;\n if (lower.startsWith(prefix) && lower.length > prefix.length) {\n if (owner === undefined || name.length > owner.length) {\n owner = name;\n }\n }\n }\n return owner;\n}\n\n/**\n * The column that *is* the rowid: a lone `INTEGER PRIMARY KEY`. Declared\n * exactly `INTEGER` (not `INT`, not `BIGINT`), and not `PRIMARY KEY DESC` —\n * the one spelling SQLite implements as a separate unique index, which shows\n * up as an index with origin `pk`.\n */\nfunction findRowidAlias(\n columns: readonly SqliteColumn[],\n indexes: readonly SqliteIndex[],\n): string | null {\n const primaryKey = columns.filter(column => column.primaryKeyPosition > 0);\n if (primaryKey.length !== 1) {\n return null;\n }\n const column = primaryKey[0] as SqliteColumn;\n if (toAsciiUpperCase(column.declaredType) !== 'INTEGER') {\n return null;\n }\n if (indexes.some(index => index.origin === 'pk')) {\n return null;\n }\n return column.name;\n}\n\ninterface ListedTable {\n readonly type: string;\n readonly withoutRowid: boolean;\n readonly strict: boolean;\n}\n\n/** Catalog queries for one schema, using the pragma functions when available. */\nclass CatalogReader {\n /** `\"schema\".`, or empty for a connection that cannot qualify names. */\n private readonly qualifier: string;\n private readonly usePragmaFunctions: boolean;\n // Not readonly: an engine that refuses the extended pragmas outright (some\n // remote engines allow only the classic ones) is switched to the classic\n // ones the first time one of them succeeds where its extended form failed.\n private useTableXinfo: boolean;\n private useIndexXinfo: boolean;\n private readonly prefetched = new Map<string, readonly SqliteRow[]>();\n\n constructor(\n private readonly connection: SqliteConnection,\n private readonly schemaName: string,\n private readonly capabilities: SqliteCapabilities,\n private readonly features: ResolvedConnectionFeatures,\n private readonly signal?: AbortSignal,\n ) {\n this.qualifier = features.schemaQualifiedNames ? `${quoteIdentifier(schemaName)}.` : '';\n this.usePragmaFunctions = capabilities.supportsPragmaFunctions && features.pragmaFunctions;\n this.useTableXinfo = capabilities.supportsTableXinfo && features.extendedPragmas;\n this.useIndexXinfo = features.extendedPragmas;\n }\n\n private async rows(\n sql: string,\n parameters?: readonly (string | number)[],\n ): Promise<readonly SqliteRow[]> {\n return this.run(parameters === undefined ? { sql } : { sql, parameters });\n }\n\n private async run(query: SqliteQuery): Promise<readonly SqliteRow[]> {\n const prefetched = this.prefetched.get(queryKey(query));\n if (prefetched !== undefined) {\n return prefetched;\n }\n const result = await this.connection.query<SqliteRow>(query, this.signal);\n return result.rows;\n }\n\n /** `PRAGMA schema.name(argument)`, as a table-valued function when the library has them. */\n private pragmaQuery(name: string, argument: string, columns: string): SqliteQuery {\n if (this.usePragmaFunctions) {\n return {\n sql: `SELECT ${columns} FROM pragma_${name}(?, ?)`,\n parameters: [argument, this.schemaName],\n };\n }\n return { sql: `PRAGMA ${this.qualifier}${name}(${quoteStringLiteral(argument)})` };\n }\n\n private columnsQuery(tableName: string): SqliteQuery {\n const withHidden = this.useTableXinfo;\n return this.pragmaQuery(\n withHidden ? 'table_xinfo' : 'table_info',\n tableName,\n `cid, name, type, \"notnull\" AS isNotNull, dflt_value AS defaultValue, pk${withHidden ? ', hidden' : ''}`,\n );\n }\n\n private indexListQuery(tableName: string): SqliteQuery {\n return this.pragmaQuery(\n 'index_list',\n tableName,\n 'seq, name, \"unique\" AS isUnique, origin, partial',\n );\n }\n\n private indexColumnsQuery(indexName: string): SqliteQuery {\n return this.useIndexXinfo\n ? this.pragmaQuery(\n 'index_xinfo',\n indexName,\n 'seqno, cid, name, \"desc\" AS isDesc, coll, \"key\" AS isKey',\n )\n : this.pragmaQuery('index_info', indexName, 'seqno, cid, name');\n }\n\n private foreignKeysQuery(tableName: string): SqliteQuery {\n return this.pragmaQuery(\n 'foreign_key_list',\n tableName,\n 'id, seq, \"table\" AS referencedTable, \"from\" AS fromColumn, \"to\" AS toColumn, on_update AS onUpdate, on_delete AS onDelete, \"match\" AS matchMode',\n );\n }\n\n /**\n * Fetches the per-table catalog of every object up front through\n * {@link SqliteConnection.queryBatch}, when the connection has it — for a\n * remote engine, a few requests instead of several per table. A batch that\n * fails is simply not cached: its queries then run one by one later, where\n * a failing one is handled (or reported) as it would be without batching.\n */\n async prefetch(schemaRows: readonly SchemaRow[]): Promise<void> {\n if (!this.connection.queryBatch) {\n return;\n }\n const queries: SqliteQuery[] = [];\n for (const row of schemaRows) {\n if (row.type === 'table' && row.sql !== null) {\n queries.push(this.columnsQuery(row.name));\n if (!isVirtualTableSql(row.sql)) {\n queries.push(this.indexListQuery(row.name), this.foreignKeysQuery(row.name));\n }\n } else if (row.type === 'index') {\n queries.push(this.indexColumnsQuery(row.name));\n }\n }\n for (let start = 0; start < queries.length; start += PREFETCH_BATCH_SIZE) {\n throwIfAborted(this.signal);\n const batch = queries.slice(start, start + PREFETCH_BATCH_SIZE);\n let results;\n try {\n results = await this.connection.queryBatch(batch, this.signal);\n } catch (error) {\n if (isAbortError(error)) throw error;\n continue;\n }\n if (results.length !== batch.length) {\n continue;\n }\n batch.forEach((query, index) => {\n this.prefetched.set(\n queryKey(query),\n (results[index] as { rows: readonly SqliteRow[] }).rows,\n );\n });\n }\n }\n\n async schemaRows(): Promise<SchemaRow[] | null> {\n if (this.features.schemaQualifiedNames) {\n let databases: readonly SqliteRow[] | undefined;\n try {\n databases = await this.rows('PRAGMA database_list');\n } catch (error) {\n // An engine that refuses the pragma still has a main database.\n if (isAbortError(error) || toAsciiLowerCase(this.schemaName) !== 'main') throw error;\n }\n const known =\n databases === undefined ||\n databases.some(\n row => toAsciiLowerCase(toText(row.name) ?? '') === toAsciiLowerCase(this.schemaName),\n );\n if (!known) {\n return null;\n }\n }\n const master =\n toAsciiLowerCase(this.schemaName) === 'temp' ? 'sqlite_temp_master' : 'sqlite_master';\n const rows = await this.rows(\n `SELECT rowid AS schemaRowid, type, name, tbl_name AS tableName, sql FROM ${this.qualifier}${master} ORDER BY rowid`,\n );\n return rows.map(row => ({\n schemaRowid: toNumber(row.schemaRowid),\n type: toText(row.type) ?? '',\n name: toText(row.name) ?? '',\n tableName: toText(row.tableName) ?? '',\n sql: toText(row.sql),\n }));\n }\n\n async tableList(): Promise<Map<string, ListedTable> | undefined> {\n if (!this.capabilities.supportsTableList || !this.features.extendedPragmas) {\n return undefined;\n }\n try {\n const rows = this.usePragmaFunctions\n ? await this.rows('SELECT name, type, wr, strict FROM pragma_table_list WHERE schema = ?', [\n this.schemaName,\n ])\n : (await this.rows(`PRAGMA ${this.qualifier}table_list`)).filter(\n row =>\n !this.features.schemaQualifiedNames ||\n toAsciiLowerCase(toText(row.schema) ?? '') === toAsciiLowerCase(this.schemaName),\n );\n return new Map(\n rows.map(row => [\n toAsciiLowerCase(toText(row.name) ?? ''),\n {\n type: toText(row.type) ?? 'table',\n withoutRowid: toNumber(row.wr) !== 0,\n strict: toNumber(row.strict) !== 0,\n },\n ]),\n );\n } catch (error) {\n if (isAbortError(error)) throw error;\n // `PRAGMA table_list` prepares every view to count its columns, so one\n // broken view makes it fail as a whole. The DDL-parsing fallback\n // below does not depend on it.\n return undefined;\n }\n }\n\n /** Runs an extended pragma's query, retrying it in its classic form if the engine refuses it. */\n private async runExtended(\n flag: 'useTableXinfo' | 'useIndexXinfo',\n query: () => SqliteQuery,\n ): Promise<readonly SqliteRow[]> {\n try {\n return await this.run(query());\n } catch (error) {\n if (isAbortError(error) || !this[flag]) throw error;\n this[flag] = false;\n try {\n return await this.run(query());\n } catch {\n // The classic form fails too, so the extended one was not the\n // problem (a virtual table whose module is missing, say).\n this[flag] = true;\n throw error;\n }\n }\n }\n\n async columns(tableName: string): Promise<SqliteColumn[]> {\n let withHidden = this.useTableXinfo;\n const rows = await this.runExtended('useTableXinfo', () => {\n withHidden = this.useTableXinfo;\n return this.columnsQuery(tableName);\n });\n return rows.map(row => {\n const hidden = (withHidden ? toNumber(row.hidden) : 0) as SqliteColumnHidden;\n return {\n cid: toNumber(row.cid),\n name: toText(row.name) ?? '',\n declaredType: toText(row.type) ?? '',\n notNull: toNumber(row.isNotNull ?? row.notnull) !== 0,\n defaultValue: toText(row.defaultValue ?? row.dflt_value),\n primaryKeyPosition: toNumber(row.pk),\n hidden,\n generated: hidden === 2 ? 'virtual' : hidden === 3 ? 'stored' : 'none',\n };\n });\n }\n\n async indexes(\n tableName: string,\n schemaRows: ReadonlyMap<string, SchemaRow>,\n ): Promise<SqliteIndex[]> {\n const list = await this.run(this.indexListQuery(tableName));\n const result: SqliteIndex[] = [];\n for (const row of list) {\n const name = toText(row.name) ?? '';\n const schemaRow = schemaRows.get(toAsciiLowerCase(name));\n const origin = (toText(row.origin) ?? 'c') as SqliteIndex['origin'];\n let columns: SqliteIndexColumn[] = [];\n try {\n const keyRows = await this.runExtended('useIndexXinfo', () => this.indexColumnsQuery(name));\n columns = keyRows\n // `index_info` lists only the key columns, and has no `key` column.\n .filter(keyRow => {\n const isKey = keyRow.isKey ?? keyRow.key;\n return isKey === undefined || toNumber(isKey) !== 0;\n })\n .sort((a, b) => toNumber(a.seqno) - toNumber(b.seqno))\n .map(keyRow => ({\n name: toText(keyRow.name),\n cid: toNumber(keyRow.cid),\n descending: toNumber(keyRow.isDesc ?? keyRow.desc) !== 0,\n collation: toText(keyRow.coll),\n }));\n } catch (error) {\n if (isAbortError(error)) throw error;\n }\n result.push({\n name,\n tableName,\n // A WITHOUT ROWID table's primary-key index is the table itself and\n // has no sqlite_schema row; it sorts with its table.\n schemaRowid: schemaRow?.schemaRowid ?? 0,\n sql: schemaRow?.sql ?? null,\n isUnique: toNumber(row.isUnique ?? row.unique) !== 0,\n origin: origin === 'u' || origin === 'pk' ? origin : 'c',\n isPartial: toNumber(row.partial) !== 0,\n columns,\n });\n }\n return result;\n }\n\n async foreignKeys(tableName: string): Promise<SqliteForeignKey[]> {\n const rows = await this.run(this.foreignKeysQuery(tableName));\n const byId = new Map<\n number,\n SqliteForeignKey & { columns: { from: string; to: string | null }[] }\n >();\n const ordered = [...rows].sort(\n (a, b) => toNumber(a.id) - toNumber(b.id) || toNumber(a.seq) - toNumber(b.seq),\n );\n for (const row of ordered) {\n const id = toNumber(row.id);\n let foreignKey = byId.get(id);\n if (!foreignKey) {\n foreignKey = {\n tableName,\n id,\n referencedTableName: toText(row.referencedTable ?? row.table) ?? '',\n columns: [],\n onUpdate: toText(row.onUpdate ?? row.on_update) ?? 'NO ACTION',\n onDelete: toText(row.onDelete ?? row.on_delete) ?? 'NO ACTION',\n match: toText(row.matchMode ?? row.match) ?? 'NONE',\n };\n byId.set(id, foreignKey);\n }\n foreignKey.columns.push({\n from: toText(row.fromColumn ?? row.from) ?? '',\n to: toText(row.toColumn ?? row.to),\n });\n }\n return [...byId.values()];\n }\n\n async sequences(): Promise<SqliteSequence[]> {\n const rows = await this.rows(\n `SELECT name, CAST(seq AS TEXT) AS value FROM ${this.qualifier}sqlite_sequence`,\n );\n return rows.map(row => ({\n tableName: toText(row.name) ?? '',\n value: toText(row.value) ?? '0',\n }));\n }\n\n async settings(): Promise<\n Pick<SqliteDatabase, 'encoding' | 'userVersion' | 'applicationId' | 'pageSize'>\n > {\n const read = async (pragma: string): Promise<unknown> => {\n try {\n const rows = await this.rows(`PRAGMA ${this.qualifier}${pragma}`);\n const first = rows[0];\n return first === undefined ? undefined : Object.values(first)[0];\n } catch (error) {\n if (isAbortError(error)) throw error;\n return undefined;\n }\n };\n // `encoding` is a property of the main database; an attached database\n // always shares it.\n let encoding: unknown;\n try {\n const rows = await this.rows('PRAGMA encoding');\n encoding = rows[0] === undefined ? undefined : Object.values(rows[0])[0];\n } catch (error) {\n if (isAbortError(error)) throw error;\n }\n const pageSize = await read('page_size');\n return {\n encoding: toText(encoding) ?? 'UTF-8',\n userVersion: toNumber(await read('user_version')),\n applicationId: toNumber(await read('application_id')),\n ...(pageSize === undefined ? {} : { pageSize: toNumber(pageSize) }),\n };\n }\n}\n","import type { ArchiveEntry, DumpArchiveInspection, DumpMode } from '../archive/types.js';\nimport type { SqliteDatabase } from '../model/database.js';\nimport type { SqliteDiagnostic } from '../model/diagnostics.js';\nimport type { DumpProgressCallback } from '../utils/progress.js';\nimport type { SqliteVersion } from '../version/types.js';\nimport type { DumpWriter } from '../writer/types.js';\n\nexport interface PlainSqlRenderOptions {\n /**\n * Wrap the dump in `PRAGMA foreign_keys=OFF;` / `BEGIN TRANSACTION;` …\n * `COMMIT;`, exactly as the native `.dump` does. Defaults to `true`, and\n * turning it off produces a `session-guards-disabled` warning.\n *\n * These are not decoration. `foreign_keys=OFF` is what lets tables be\n * created and filled in creation order whatever references what —\n * circular foreign keys included — and the transaction is what makes the\n * restore both atomic and fast: without it every `INSERT` is its own\n * transaction, and its own disk sync. A data-only dump never carries them,\n * matching `.dump --data-only`.\n */\n readonly includeSessionGuards?: boolean;\n /**\n * Emit the `/* WARNING: Script requires that SQLITE_DBCONFIG_DEFENSIVE be\n * disabled *\\/` line the native `.dump` writes first when the dump\n * contains virtual tables. Defaults to `true`.\n */\n readonly includeHeaderComments?: boolean;\n /**\n * Emit `DROP ... IF EXISTS` before each object's `CREATE`, so the dump can\n * be restored over an existing copy. Defaults to `false`: the native\n * `.dump` has no such option, and a dump restored into a fresh database\n * does not need it.\n */\n readonly addDropStatements?: boolean;\n /**\n * Emit `PRAGMA user_version=…;` and `PRAGMA application_id=…;` before the\n * final `COMMIT`, when either is non-zero. Defaults to `false`, matching\n * the native `.dump` — which does not carry them, so an application that\n * versions its schema through `user_version` loses that version in a\n * native round trip. When they are not dumped, a non-zero value is\n * reported as a `user-version-not-dumped` / `application-id-not-dumped`\n * warning.\n */\n readonly includeDatabaseSettings?: boolean;\n /**\n * Write `sqlite_master` instead of `sqlite_schema` in the two places the\n * dump names the schema table (`ANALYZE sqlite_schema;` and the virtual\n * table `INSERT INTO sqlite_schema ...`). Defaults to `false`. The\n * `sqlite_schema` spelling needs SQLite 3.33.0 or later on the restoring\n * side; set this for a dump that must restore on something older.\n */\n readonly legacySchemaTableName?: boolean;\n /**\n * How to react to an archive entry that cannot be rendered. `'error'`\n * (default) fails the render; `'warn-omit'` skips the entry and records a\n * warning diagnostic.\n */\n readonly unsupportedFeaturePolicy?: 'error' | 'warn-omit';\n}\n\nexport interface ResolvedPlainSqlRenderOptions {\n readonly includeSessionGuards: boolean;\n readonly includeHeaderComments: boolean;\n readonly addDropStatements: boolean;\n readonly includeDatabaseSettings: boolean;\n readonly legacySchemaTableName: boolean;\n readonly unsupportedFeaturePolicy: 'error' | 'warn-omit';\n}\n\nexport function resolvePlainSqlRenderOptions(\n options?: PlainSqlRenderOptions,\n): ResolvedPlainSqlRenderOptions {\n return {\n includeSessionGuards: options?.includeSessionGuards ?? true,\n includeHeaderComments: options?.includeHeaderComments ?? true,\n addDropStatements: options?.addDropStatements ?? false,\n includeDatabaseSettings: options?.includeDatabaseSettings ?? false,\n legacySchemaTableName: options?.legacySchemaTableName ?? false,\n unsupportedFeaturePolicy: options?.unsupportedFeaturePolicy ?? 'error',\n };\n}\n\nexport interface PlainSqlRenderRequest {\n readonly database: SqliteDatabase;\n readonly archive: DumpArchiveInspection;\n readonly writer: DumpWriter;\n readonly options?: PlainSqlRenderOptions;\n readonly signal?: AbortSignal;\n readonly onProgress?: DumpProgressCallback;\n /** Source library version; informational. */\n readonly sourceVersion?: SqliteVersion;\n /** Which dump mode produced `archive`. Defaults to `'full'`. */\n readonly mode?: DumpMode;\n /**\n * Called for each `tableData` entry, for callers that can actually stream\n * the rows (see `dumpSqlite`, which supplies this backed by a live\n * connection). Resolve `true` once the rows have been written to\n * `writer`; resolve `false` to fall back to the default \"not rendered\"\n * warning for that entry.\n */\n readonly onTableData?: (entry: ArchiveEntry) => Promise<boolean>;\n}\n\nexport interface PlainSqlRenderResult {\n readonly bytesWritten: number;\n readonly renderedDumpIds: readonly string[];\n readonly skippedDumpIds: readonly string[];\n readonly warnings: readonly SqliteDiagnostic[];\n readonly cancelled: boolean;\n}\n","/**\n * A port of SQLite's `sqlite3_complete()` (`complete.c`) — the function the\n * `sqlite3` shell calls to decide whether the text it has accumulated so far\n * is one or more *complete* statements, and therefore ready to run.\n *\n * Splitting on `;` is not enough, and not in an edge-case way: a trigger\n * body is a list of statements, each ending in `;`, inside a single\n * `CREATE TRIGGER ... BEGIN ... END;`. `sqlite3_complete()` recognizes that\n * with a small state machine over eight token classes, and reproducing that\n * machine exactly is what makes this package split a script where the shell\n * does.\n */\n\n/** Token classes of the `sqlite3_complete()` state machine. */\nexport const CompleteToken = {\n Semi: 0,\n Whitespace: 1,\n Other: 2,\n Explain: 3,\n Create: 4,\n Temp: 5,\n Trigger: 6,\n End: 7,\n} as const;\n\nexport type CompleteToken = (typeof CompleteToken)[keyof typeof CompleteToken];\n\n/**\n * States of the machine:\n *\n * - `0` INVALID — nothing but whitespace/comments seen yet.\n * - `1` START — at the start of a statement, or just after a complete one.\n * - `2` NORMAL — inside an ordinary statement.\n * - `3` EXPLAIN — the statement began with `EXPLAIN`.\n * - `4` CREATE — the statement began with `CREATE` (or `EXPLAIN CREATE`).\n * - `5` TRIGGER — inside `CREATE [TEMP] TRIGGER ...`, before or within its body.\n * - `6` SEMI — just saw a `;` inside a trigger body.\n * - `7` END — saw `END` right after such a `;`; the next `;` completes the trigger.\n */\nexport const COMPLETE_TRANSITIONS: readonly (readonly number[])[] = [\n // SEMI WS OTHER EXPLAIN CREATE TEMP TRIGGER END\n /* 0 */ [1, 0, 2, 3, 4, 2, 2, 2],\n /* 1 */ [1, 1, 2, 3, 4, 2, 2, 2],\n /* 2 */ [1, 2, 2, 2, 2, 2, 2, 2],\n /* 3 */ [1, 3, 3, 2, 4, 2, 2, 2],\n /* 4 */ [1, 4, 2, 2, 2, 4, 5, 2],\n /* 5 */ [6, 5, 5, 5, 5, 5, 5, 5],\n /* 6 */ [6, 6, 5, 5, 5, 5, 5, 7],\n /* 7 */ [1, 7, 5, 5, 5, 5, 5, 5],\n];\n\n/** Applies one token to a state. */\nexport function completeTransition(state: number, token: CompleteToken): number {\n return (COMPLETE_TRANSITIONS[state] as readonly number[])[token] as number;\n}\n\n/**\n * `IdChar()` from `complete.c`: letters, digits, `_`, `$`, and every byte (or\n * code unit) at or above `0x80`, which is how SQLite admits non-ASCII\n * identifiers without decoding them.\n */\nexport function isIdentifierCharCode(code: number): boolean {\n return (\n (code >= 0x61 && code <= 0x7a) ||\n (code >= 0x41 && code <= 0x5a) ||\n (code >= 0x30 && code <= 0x39) ||\n code === 0x5f ||\n code === 0x24 ||\n code >= 0x80\n );\n}\n\n/** Classifies a complete identifier-like word the way `sqlite3_complete()` does. */\nexport function classifyWord(word: string): CompleteToken {\n switch (word.length) {\n case 3:\n return word.toLowerCase() === 'end' ? CompleteToken.End : CompleteToken.Other;\n case 4:\n return word.toLowerCase() === 'temp' ? CompleteToken.Temp : CompleteToken.Other;\n case 6:\n return word.toLowerCase() === 'create' ? CompleteToken.Create : CompleteToken.Other;\n case 7: {\n const lower = word.toLowerCase();\n if (lower === 'trigger') return CompleteToken.Trigger;\n if (lower === 'explain') return CompleteToken.Explain;\n return CompleteToken.Other;\n }\n case 9:\n return word.toLowerCase() === 'temporary' ? CompleteToken.Temp : CompleteToken.Other;\n default:\n return CompleteToken.Other;\n }\n}\n\nfunction isCompleteWhitespace(character: string): boolean {\n return (\n character === ' ' ||\n character === '\\r' ||\n character === '\\t' ||\n character === '\\n' ||\n character === '\\f'\n );\n}\n\n/**\n * `sqlite3_complete()`: `true` when `sql` ends with a complete statement —\n * a `;` that is not inside a string, identifier, comment or trigger body,\n * followed by nothing but whitespace and comments.\n *\n * Faithful to the C, including its quirks: an unterminated `/*` comment or\n * quoted token makes the text incomplete, while a trailing `--` comment\n * with no newline does not.\n */\nexport function isCompleteStatement(sql: string): boolean {\n let state = 0;\n let index = 0;\n const length = sql.length;\n\n while (index < length) {\n const character = sql[index] as string;\n let token: CompleteToken;\n\n if (character === ';') {\n token = CompleteToken.Semi;\n } else if (isCompleteWhitespace(character)) {\n token = CompleteToken.Whitespace;\n } else if (character === '/') {\n if (sql[index + 1] !== '*') {\n token = CompleteToken.Other;\n } else {\n index += 2;\n while (index < length && !(sql[index] === '*' && sql[index + 1] === '/')) {\n index++;\n }\n if (index >= length) {\n return false;\n }\n index++;\n token = CompleteToken.Whitespace;\n }\n } else if (character === '-') {\n if (sql[index + 1] !== '-') {\n token = CompleteToken.Other;\n } else {\n while (index < length && sql[index] !== '\\n') {\n index++;\n }\n if (index >= length) {\n return state === 1;\n }\n token = CompleteToken.Whitespace;\n }\n } else if (character === '[') {\n index++;\n while (index < length && sql[index] !== ']') {\n index++;\n }\n if (index >= length) {\n return false;\n }\n token = CompleteToken.Other;\n } else if (character === '`' || character === '\"' || character === \"'\") {\n index++;\n while (index < length && sql[index] !== character) {\n index++;\n }\n if (index >= length) {\n return false;\n }\n token = CompleteToken.Other;\n } else if (isIdentifierCharCode(sql.charCodeAt(index))) {\n let end = index + 1;\n while (end < length && isIdentifierCharCode(sql.charCodeAt(end))) {\n end++;\n }\n token = classifyWord(sql.slice(index, end));\n index = end - 1;\n } else {\n token = CompleteToken.Other;\n }\n\n state = completeTransition(state, token);\n index++;\n }\n return state === 1;\n}\n","import { isCompleteStatement } from '../restore/complete.js';\nimport { quoteIdentifierIfNeeded, toAsciiLowerCase } from '../security/identifiers.js';\nimport { quoteStringLiteral } from '../security/literals.js';\n\n/** The native `.dump` preamble: integrity checks off, then one transaction around everything. */\nexport const SESSION_GUARD_HEADER = 'PRAGMA foreign_keys=OFF;\\nBEGIN TRANSACTION;\\n';\n\nexport const SESSION_GUARD_FOOTER = 'COMMIT;\\n';\n\nexport const WRITABLE_SCHEMA_ON = 'PRAGMA writable_schema=ON;\\n';\n\nexport const WRITABLE_SCHEMA_OFF = 'PRAGMA writable_schema=OFF;\\n';\n\n/**\n * `printSchemaLine()` from `shell.c`: how the native `.dump` writes a\n * table's stored `CREATE TABLE` text.\n *\n * Two details are reproduced exactly, because both change the bytes:\n *\n * - **A trailing comment.** SQLite stores DDL verbatim, so it can end in a\n * `--` comment (which would swallow an appended `;`) or even an\n * unterminated `/*` comment (which SQLite accepts at end of input). When\n * the text contains either, the shell tries appending nothing, `*\\/` and a\n * newline, in that order, and keeps the first variant that\n * `sqlite3_complete()` accepts once `;` is added.\n * - **`IF NOT EXISTS` for quoted names.** A `CREATE TABLE` whose name is\n * written in single or double quotes becomes\n * `CREATE TABLE IF NOT EXISTS`. Virtual table modules create their shadow\n * tables with exactly that spelling (`CREATE TABLE 'ft_data'(...)`), and\n * by the time the dump reaches them on restore, a module may already have\n * created them.\n */\nexport function renderSchemaLine(sql: string, tail = ';\\n'): string {\n let text = sql;\n if (tail.startsWith(';') && (text.includes('/*') || text.includes('--'))) {\n for (const terminator of ['', '*/', '\\n']) {\n if (isCompleteStatement(`${text}${terminator};`)) {\n text = `${text}${terminator}`;\n break;\n }\n }\n }\n if (/^CREATE TABLE ['\"]/.test(text)) {\n return `CREATE TABLE IF NOT EXISTS ${text.slice(13)}${tail}`;\n }\n return `${text}${tail}`;\n}\n\n/**\n * How `run_table_dump_query()` in `shell.c` writes an index, trigger or view:\n * the stored text, then `;` — on a line of its own if the text contains\n * `--` anywhere, so a trailing line comment cannot swallow it. (The test is\n * a plain substring search, so a `--` inside a string literal triggers it\n * too, and does here.)\n */\nexport function renderSchemaObject(sql: string): string {\n return sql.includes('--') ? `${sql}\\n;\\n` : `${sql};\\n`;\n}\n\n/**\n * A virtual table, recreated the way the native `.dump` does it: by writing\n * its row into `sqlite_schema` directly (under `PRAGMA writable_schema=ON`)\n * instead of running `CREATE VIRTUAL TABLE`.\n *\n * Running the `CREATE` would invoke the module's constructor, which for most\n * modules creates and initializes the shadow tables — and the dump is about\n * to recreate those itself, with the source's exact contents. Writing the\n * schema row leaves the shadow tables to the dump, so an FTS index or R-tree\n * comes back byte-identical rather than rebuilt.\n */\nexport function renderVirtualTable(name: string, sql: string, schemaTableName: string): string {\n // `'%q'` in the shell's format string: single quotes doubled, nothing else.\n const quotedName = quoteStringLiteral(name);\n return `INSERT INTO ${schemaTableName}(type,name,tbl_name,rootpage,sql)VALUES('table',${quotedName},${quotedName},0,${quoteStringLiteral(sql)});\\n`;\n}\n\n/**\n * The statement that prepares a system table for its rows.\n *\n * - `sqlite_sequence` is emptied, so the `AUTOINCREMENT` counters that\n * follow replace — rather than duplicate — the counters the preceding\n * inserts advanced. A partial dump only resets the counters of the tables\n * it contains.\n * - `sqlite_stat1`/`sqlite_stat4` are created, if missing, by analyzing the\n * (trivial) schema table, which is how the native `.dump` guarantees they\n * exist before inserting into them.\n */\nexport function renderSystemTablePrelude(\n name: string,\n schemaTableName: string,\n systemRowFilter: readonly string[] | undefined,\n): string {\n if (name === 'sqlite_sequence') {\n if (systemRowFilter === undefined) {\n return 'DELETE FROM sqlite_sequence;\\n';\n }\n const names = [...new Set(systemRowFilter.map(toAsciiLowerCase))].map(quoteStringLiteral);\n return `DELETE FROM sqlite_sequence WHERE lower(name) IN (${names.join(',')});\\n`;\n }\n return `ANALYZE ${schemaTableName};\\n`;\n}\n\nexport type DroppableKind = 'TABLE' | 'INDEX' | 'TRIGGER' | 'VIEW';\n\n/** `DROP <kind> IF EXISTS <name>;`, for `addDropStatements`. */\nexport function renderDrop(kind: DroppableKind, name: string): string {\n return `DROP ${kind} IF EXISTS ${quoteIdentifierIfNeeded(name)};\\n`;\n}\n\n/** `PRAGMA user_version=…;` / `PRAGMA application_id=…;`, for `includeDatabaseSettings`. */\nexport function renderDatabaseSettings(userVersion: number, applicationId: number): string {\n let text = '';\n if (userVersion !== 0) {\n text += `PRAGMA user_version=${userVersion};\\n`;\n }\n if (applicationId !== 0) {\n text += `PRAGMA application_id=${applicationId};\\n`;\n }\n return text;\n}\n","import { redactSecrets } from '../security/redact.js';\n\n/**\n * Truncates SQL for inclusion in an error message or a progress event.\n *\n * Never a full statement — a single `INSERT` can carry a megabyte of blob —\n * and never a literal encryption key.\n */\nexport function safeSqlPreview(sql: string, maximumLength = 200): string {\n const normalized = redactSecrets(sql).trim().replace(/\\s+/g, ' ');\n if (normalized.length <= maximumLength) {\n return normalized;\n }\n let cut = normalized.slice(0, maximumLength);\n // Never split a surrogate pair: an emoji straddling the cut would leave a\n // lone high surrogate, making the preview ill-formed UTF-16 —\n // `JSON.stringify` would emit an unpaired `\\ud83d`, and writing it as UTF-8\n // would substitute U+FFFD.\n const lastUnit = cut.charCodeAt(cut.length - 1);\n if (lastUnit >= 0xd800 && lastUnit <= 0xdbff) {\n cut = cut.slice(0, -1);\n }\n return `${cut}…`;\n}\n\n/** The warning line the native `.dump` writes first when the dump contains virtual tables. */\nexport const DEFENSIVE_WARNING_COMMENT =\n '/* WARNING: Script requires that SQLITE_DBCONFIG_DEFENSIVE be disabled */';\n\n/**\n * Heuristically detects whether `sample` looks like a SQLite dump — whether\n * produced by the native `.dump` command or by this package, which write the\n * same thing.\n *\n * A full dump opens with `PRAGMA foreign_keys=OFF;` and\n * `BEGIN TRANSACTION;`, optionally preceded by the defensive-mode warning\n * comment; that opening is what is recognized. A `--data-only` dump has no\n * such preamble and is indistinguishable from any other script of\n * `INSERT`s, so it is only recognized when it carries the warning comment.\n *\n * Only the first few kilobytes need to be supplied; the check never reads\n * beyond what it is given, so a caller can pass the head of a large file.\n */\nexport function isSqliteDump(sample: string | Uint8Array): boolean {\n const text = typeof sample === 'string' ? sample : Buffer.from(sample).toString('utf8');\n const head = text\n .slice(0, 8192)\n .replace(/^\\uFEFF/, '')\n .replace(/\\r\\n/g, '\\n');\n let rest = head.trimStart();\n if (rest.startsWith(DEFENSIVE_WARNING_COMMENT)) {\n rest = rest.slice(DEFENSIVE_WARNING_COMMENT.length).trimStart();\n if (rest === '' || /^INSERT INTO /.test(rest) || rest.startsWith('PRAGMA foreign_keys=OFF;')) {\n return true;\n }\n }\n return /^PRAGMA foreign_keys=OFF;\\s*\\nBEGIN TRANSACTION;/.test(rest);\n}\n","import type { ArchiveEntry } from '../archive/types.js';\nimport type { SqliteIndex, SqliteTrigger, SqliteView } from '../model/database.js';\nimport type { SqliteDiagnostic } from '../model/diagnostics.js';\nimport { DEFENSIVE_WARNING_COMMENT } from '../restore/preview.js';\nimport { foldSqliteName } from '../selection/normalize.js';\nimport { isAbortError, SqliteDumperError, throwIfAborted } from '../utils/errors.js';\nimport type { DumpProgressSection } from '../utils/progress.js';\nimport {\n renderDatabaseSettings,\n renderDrop,\n renderSchemaLine,\n renderSchemaObject,\n renderSystemTablePrelude,\n renderVirtualTable,\n SESSION_GUARD_FOOTER,\n SESSION_GUARD_HEADER,\n WRITABLE_SCHEMA_OFF,\n WRITABLE_SCHEMA_ON,\n} from './objectRenderers.js';\nimport { resolvePlainSqlRenderOptions } from './types.js';\nimport type {\n PlainSqlRenderRequest,\n PlainSqlRenderResult,\n ResolvedPlainSqlRenderOptions,\n} from './types.js';\n\nconst SECTION_BY_ENTRY: Record<ArchiveEntry['objectType'], DumpProgressSection> = {\n table: 'table-structure',\n tableData: 'table-data',\n virtualTable: 'virtual-table',\n index: 'index',\n trigger: 'trigger',\n view: 'view',\n};\n\n/**\n * Renders a validated {@link DumpArchiveInspection} as plain SQL in the\n * native `.dump` layout — the same statements, in the same order, spelled\n * the same way.\n *\n * Purely a function of the static model and the archive plan: it never\n * queries the database, which is why row data has to arrive through the\n * `onTableData` hook (see `exportTableDataAsInserts` for the streaming\n * implementation `dumpSqlite` supplies).\n */\nexport async function renderPlainSql(\n request: PlainSqlRenderRequest,\n): Promise<PlainSqlRenderResult> {\n const options = resolvePlainSqlRenderOptions(request.options);\n const { database, archive, writer, signal, onProgress, onTableData } = request;\n const mode = request.mode ?? 'full';\n\n if (!archive.valid) {\n throw new SqliteDumperError(\n 'invalid-archive',\n 'Cannot render an archive inspection that failed validation; see archive.diagnostics, archive.cycles and archive.unsatisfiedDependencies',\n );\n }\n\n const warnings: SqliteDiagnostic[] = [];\n const renderedDumpIds: string[] = [];\n const skippedDumpIds: string[] = [];\n const schemaTableName = options.legacySchemaTableName ? 'sqlite_master' : 'sqlite_schema';\n\n const tables = new Map(database.tables.map(table => [foldSqliteName(table.name), table]));\n const indexes = new Map(database.indexes.map(index => [foldSqliteName(index.name), index]));\n const triggers = new Map(\n database.triggers.map(trigger => [foldSqliteName(trigger.name), trigger]),\n );\n const views = new Map(database.views.map(view => [foldSqliteName(view.name), view]));\n\n const emit = async (text: string): Promise<void> => {\n if (text !== '') {\n await writer.write(text, signal);\n }\n };\n\n const guards = options.includeSessionGuards && mode !== 'data-only';\n if (!options.includeSessionGuards && mode !== 'data-only') {\n warnings.push({\n severity: 'warning',\n code: 'session-guards-disabled',\n message:\n 'render.includeSessionGuards is false, so the dump omits PRAGMA foreign_keys=OFF and its BEGIN TRANSACTION / COMMIT. Tables that reference each other may fail to restore in the emitted order, and every INSERT runs as its own transaction, which makes restoring a large dump dramatically slower.',\n });\n }\n\n reportUnDumpedSettings(request, options, warnings);\n\n // The warning appears whenever the dump contains a virtual table, even in\n // a data-only dump — the native `.dump` decides it from the schema alone.\n const containsVirtualTables =\n mode !== 'schema-only' &&\n archive.entries.some(\n entry =>\n entry.objectType === 'virtualTable' ||\n entry.tableKind === 'virtual' ||\n (entry.tableKind === 'shadow' &&\n tables.get(foldSqliteName(entry.name))?.ownerVirtualTable !== undefined),\n );\n\n let writableSchema = false;\n\n try {\n if (options.includeHeaderComments && containsVirtualTables) {\n await emit(`${DEFENSIVE_WARNING_COMMENT}\\n`);\n }\n if (guards) {\n await emit(SESSION_GUARD_HEADER);\n }\n\n let processed = 0;\n const total = archive.entries.length;\n\n for (const entry of archive.entries) {\n throwIfAborted(signal);\n processed++;\n onProgress?.({\n phase: 'rendering-schema',\n section: SECTION_BY_ENTRY[entry.objectType],\n objectsProcessed: processed,\n objectsTotal: total,\n objectName: entry.name,\n schemaName: entry.schemaName,\n bytesWritten: writer.bytesWritten,\n });\n\n let handled: boolean;\n switch (entry.objectType) {\n case 'table': {\n const table = tables.get(foldSqliteName(entry.name));\n if (!table) {\n handled = missing(entry, 'table', warnings, options);\n break;\n }\n if (table.kind === 'system') {\n await emit(\n renderSystemTablePrelude(table.name, schemaTableName, entry.systemRowFilter),\n );\n } else {\n if (options.addDropStatements) {\n await emit(renderDrop('TABLE', table.name));\n }\n await emit(renderSchemaLine(table.sql));\n }\n handled = true;\n break;\n }\n\n case 'virtualTable': {\n const table = tables.get(foldSqliteName(entry.name));\n if (!table) {\n handled = missing(entry, 'virtual table', warnings, options);\n break;\n }\n if (options.addDropStatements) {\n await emit(renderDrop('TABLE', table.name));\n }\n if (mode === 'schema-only') {\n // No shadow-table rows follow in a schema-only dump, so the table\n // must be created by its module, which initializes them — as the\n // native `.schema` writes it. The shadow tables' own\n // `CREATE TABLE IF NOT EXISTS` lines then do nothing.\n await emit(renderSchemaLine(table.sql));\n } else {\n if (!writableSchema) {\n await emit(WRITABLE_SCHEMA_ON);\n writableSchema = true;\n }\n await emit(renderVirtualTable(table.name, table.sql, schemaTableName));\n }\n handled = true;\n break;\n }\n\n case 'tableData': {\n const table = tables.get(foldSqliteName(entry.name));\n if (!table) {\n handled = missing(entry, 'table', warnings, options);\n break;\n }\n if (onTableData) {\n handled = await onTableData(entry);\n } else {\n warnings.push({\n severity: 'warning',\n code: 'data-not-rendered',\n message: `Row data for table \"${entry.name}\" was selected, but renderPlainSql only renders schema objects; use dumpSqlite (or supply onTableData) with a live connection to stream rows.`,\n objectReference: { kind: 'table', schemaName: entry.schemaName, name: entry.name },\n });\n handled = true;\n }\n break;\n }\n\n case 'index':\n case 'trigger':\n case 'view': {\n const object = lookupSchemaObject(entry, indexes, triggers, views);\n if (!object || object.sql === null) {\n handled = missing(entry, entry.objectType, warnings, options);\n break;\n }\n if (options.addDropStatements) {\n await emit(\n renderDrop(\n entry.objectType === 'index'\n ? 'INDEX'\n : entry.objectType === 'trigger'\n ? 'TRIGGER'\n : 'VIEW',\n entry.name,\n ),\n );\n }\n await emit(renderSchemaObject(object.sql));\n handled = true;\n break;\n }\n\n default: {\n const unreachable: never = entry.objectType;\n throw new SqliteDumperError(\n 'unsupported-object',\n `Unhandled archive object type: ${String(unreachable)}`,\n );\n }\n }\n\n if (handled) {\n renderedDumpIds.push(entry.dumpId);\n } else {\n skippedDumpIds.push(entry.dumpId);\n }\n }\n\n if (writableSchema) {\n await emit(WRITABLE_SCHEMA_OFF);\n }\n if (options.includeDatabaseSettings) {\n await emit(renderDatabaseSettings(database.userVersion, database.applicationId));\n }\n if (guards) {\n await emit(SESSION_GUARD_FOOTER);\n }\n\n return {\n bytesWritten: writer.bytesWritten,\n renderedDumpIds,\n skippedDumpIds,\n warnings,\n cancelled: false,\n };\n } catch (error) {\n if (isAbortError(error)) {\n return {\n bytesWritten: writer.bytesWritten,\n renderedDumpIds,\n skippedDumpIds,\n warnings,\n cancelled: true,\n };\n }\n throw error;\n }\n}\n\nfunction lookupSchemaObject(\n entry: ArchiveEntry,\n indexes: ReadonlyMap<string, SqliteIndex>,\n triggers: ReadonlyMap<string, SqliteTrigger>,\n views: ReadonlyMap<string, SqliteView>,\n): { sql: string | null } | undefined {\n const key = foldSqliteName(entry.name);\n switch (entry.objectType) {\n case 'index':\n return indexes.get(key);\n case 'trigger':\n return triggers.get(key);\n default:\n return views.get(key);\n }\n}\n\n/**\n * `user_version` and `application_id` are database settings the native\n * `.dump` does not carry. An application that tracks its schema migrations\n * in `user_version` would restore into a database that looks unmigrated, so\n * a non-zero value that is not being dumped is reported rather than dropped\n * silently.\n */\nfunction reportUnDumpedSettings(\n request: PlainSqlRenderRequest,\n options: ResolvedPlainSqlRenderOptions,\n warnings: SqliteDiagnostic[],\n): void {\n if (options.includeDatabaseSettings) {\n return;\n }\n const { database } = request;\n if (database.userVersion !== 0) {\n warnings.push({\n severity: 'warning',\n code: 'user-version-not-dumped',\n message: `The database's PRAGMA user_version is ${database.userVersion}, which the dump does not carry (the native .dump does not either). Set render.includeDatabaseSettings to include it; applications often track schema migrations in it.`,\n objectReference: {\n kind: 'database',\n schemaName: database.schemaName,\n name: database.schemaName,\n },\n });\n }\n if (database.applicationId !== 0) {\n warnings.push({\n severity: 'warning',\n code: 'application-id-not-dumped',\n message: `The database's PRAGMA application_id is ${database.applicationId}, which the dump does not carry (the native .dump does not either). Set render.includeDatabaseSettings to include it.`,\n objectReference: {\n kind: 'database',\n schemaName: database.schemaName,\n name: database.schemaName,\n },\n });\n }\n}\n\nfunction missing(\n entry: ArchiveEntry,\n kind: string,\n warnings: SqliteDiagnostic[],\n options: ResolvedPlainSqlRenderOptions,\n): boolean {\n const message = `Archive entry references ${kind} \"${entry.name}\", which was not found in the introspected model`;\n if (options.unsupportedFeaturePolicy === 'warn-omit') {\n warnings.push({ severity: 'warning', code: 'model-object-missing', message });\n return false;\n }\n throw new SqliteDumperError('model-object-missing', message);\n}\n","/**\n * Accumulates SQL fragments that may be text *or* raw bytes.\n *\n * A `TEXT` value holding bytes that are not valid UTF-8 is written out raw,\n * exactly as the native `.dump` writes it, so a statement cannot always be\n * assembled as a JavaScript string. Joining through a string would replace\n * every invalid sequence with U+FFFD and corrupt the data silently.\n *\n * The all-text case — which is every row of every ordinary database — stays\n * on the fast path: parts are joined with `String.prototype.join` and no\n * `Buffer` is allocated at all. Only a builder that has actually been handed\n * bytes falls back to `Buffer.concat`.\n */\nexport class SqlChunkBuilder {\n private readonly parts: (string | Buffer)[] = [];\n private byteLength = 0;\n private hasBytes = false;\n\n /** UTF-8 byte length of everything appended so far. */\n get length(): number {\n return this.byteLength;\n }\n\n get isEmpty(): boolean {\n return this.parts.length === 0;\n }\n\n append(part: string | Buffer): this {\n if (typeof part === 'string') {\n if (part.length === 0) {\n return this;\n }\n this.parts.push(part);\n this.byteLength += Buffer.byteLength(part, 'utf8');\n return this;\n }\n if (part.length === 0) {\n return this;\n }\n this.parts.push(part);\n this.byteLength += part.length;\n this.hasBytes = true;\n return this;\n }\n\n /** Appends everything from `other`, leaving `other` untouched. */\n appendBuilder(other: SqlChunkBuilder): this {\n for (const part of other.parts) {\n this.append(part);\n }\n return this;\n }\n\n /** The accumulated content, as a `string` when it is all text and a `Buffer` otherwise. */\n build(): string | Buffer {\n if (!this.hasBytes) {\n return this.parts.join('');\n }\n return Buffer.concat(\n this.parts.map(part => (typeof part === 'string' ? Buffer.from(part, 'utf8') : part)),\n );\n }\n}\n","import type { SqliteColumnValue, SqliteRow } from '../connection/types.js';\nimport { isUtf8 } from 'node:buffer';\nimport { toBuffer } from '../connection/acquire.js';\nimport { renderBlobLiteral, renderTextLiteral } from '../security/literals.js';\nimport type { TextLiteralStyle } from '../security/literals.js';\n\n/**\n * The SQL expression that renders a `REAL` exactly as the native `.dump`\n * renders it, evaluated by SQLite itself. `shell.c` does this:\n *\n * ```c\n * if( ur==0x7ff0000000000000LL ) oputz(\"9.0e+999\");\n * else if( ur==0xfff0000000000000LL ) oputz(\"-9.0e+999\");\n * else {\n * sqlite3_int64 ir = (sqlite3_int64)r;\n * if( r==(double)ir ) sqlite3_snprintf(50,z,\"%lld.0\", ir);\n * else sqlite3_snprintf(50,z,\"%!.20g\", r);\n * }\n * ```\n *\n * Doing it in SQL rather than in JavaScript is the point. The digits\n * `%!.20g` produces come from SQLite's own floating-point formatter, which\n * no JavaScript routine reproduces (and which changed between SQLite\n * releases); asking the database to format the value is the only way to\n * write the same digits the shell of the same SQLite version would. It also\n * means the value never passes through the driver as a JavaScript number.\n *\n * `9e999` is how SQLite spells infinity in SQL: it overflows to `Inf` on\n * parse, which is also why the dump writes it that way.\n */\nfunction realLiteralExpression(column: string): string {\n return (\n `CASE WHEN ${column} = 9e999 THEN '9.0e+999' ` +\n `WHEN ${column} = -9e999 THEN '-9.0e+999' ` +\n `WHEN ${column} >= -9223372036854775808.0 AND ${column} < 9223372036854775808.0 AND ${column} = CAST(${column} AS INTEGER) ` +\n `THEN CAST(CAST(${column} AS INTEGER) AS TEXT) || '.0' ` +\n `ELSE printf('%!.20g', ${column}) END`\n );\n}\n\n/**\n * How the bytes of text and blob values travel from SQLite to this package.\n *\n * Natively they arrive as bytes. Over a transport that cannot carry bytes\n * exactly — JSON, for Cloudflare D1 — SQLite is asked for their `hex()`\n * instead, which any transport carries as plain ASCII text.\n */\nexport interface SqliteValueTransport {\n /** Text values (in a UTF-8 database) are read as `hex()` of their bytes. */\n readonly hexText: boolean;\n /** Blob values are read as `hex()`. */\n readonly hexBlob: boolean;\n}\n\nexport const NATIVE_VALUE_TRANSPORT: SqliteValueTransport = { hexText: false, hexBlob: false };\n\nexport function valueTransport(\n utf8Database: boolean,\n binaryTransport: 'native' | 'hex',\n): SqliteValueTransport {\n return binaryTransport === 'hex'\n ? { hexText: utf8Database, hexBlob: true }\n : NATIVE_VALUE_TRANSPORT;\n}\n\n/**\n * The select-list for one column: its storage class, and a value shaped so\n * that only exact representations cross the driver boundary.\n *\n * - `INTEGER` → decimal text, so a 64-bit value is exact whatever the\n * driver would have done with it;\n * - `REAL` → the literal text, see {@link realLiteralExpression};\n * - `TEXT` → the stored bytes (`CAST(... AS BLOB)`), so text that is not\n * valid UTF-8 is not \"repaired\" by the driver's decoder on the way out.\n * In a UTF-16 database those bytes would be UTF-16, so there the value is\n * read as text instead and the driver's (lossless, for valid UTF-16)\n * conversion is used;\n * - `BLOB` → the bytes; `NULL` → `NULL`.\n *\n * With a hex {@link SqliteValueTransport}, text and blob bytes are read as\n * `hex()` text instead.\n */\nexport function columnValueSelect(\n column: string,\n index: number,\n utf8Database: boolean,\n transport: SqliteValueTransport = NATIVE_VALUE_TRANSPORT,\n): string {\n const textBytes = utf8Database ? `CAST(${column} AS BLOB)` : column;\n const textBranch = transport.hexText ? `hex(${textBytes})` : textBytes;\n return (\n `typeof(${column}) AS \"t${index}\", ` +\n `CASE typeof(${column}) ` +\n `WHEN 'integer' THEN CAST(${column} AS TEXT) ` +\n `WHEN 'real' THEN ${realLiteralExpression(column)} ` +\n `WHEN 'text' THEN ${textBranch} ` +\n (transport.hexBlob ? `WHEN 'blob' THEN hex(${column}) ` : '') +\n `ELSE ${column} END AS \"v${index}\"`\n );\n}\n\nfunction asBytes(value: SqliteColumnValue, hex: boolean): Buffer {\n if (typeof value === 'string') {\n return Buffer.from(value, hex ? 'hex' : 'utf8');\n }\n if (value instanceof Uint8Array || value instanceof ArrayBuffer || Array.isArray(value)) {\n return toBuffer(value as Uint8Array | ArrayBuffer | readonly number[]);\n }\n return Buffer.from(String(value), 'utf8');\n}\n\n/**\n * Renders column `index` of a row produced by {@link columnValueSelect} as\n * the SQL literal the native `.dump` writes for it.\n *\n * Returns a `Buffer` only for text that is not valid UTF-8: the shell writes\n * such bytes out raw, and so does this package, so the dump reproduces the\n * stored value exactly (see `DumpWriter` for why that cannot go through a\n * string).\n */\nexport function renderColumnLiteral(\n row: SqliteRow,\n index: number,\n textStyle: TextLiteralStyle,\n transport: SqliteValueTransport = NATIVE_VALUE_TRANSPORT,\n): string | Buffer {\n const storageClass = row[`t${index}`];\n const value = row[`v${index}`] ?? null;\n switch (storageClass) {\n case 'integer':\n case 'real':\n return String(value);\n case 'text': {\n if (typeof value === 'string' && !transport.hexText) {\n return renderTextLiteral(value, textStyle);\n }\n const bytes = asBytes(value, transport.hexText);\n if (isUtf8(bytes)) {\n return renderTextLiteral(bytes.toString('utf8'), textStyle);\n }\n // Escape as a byte string (one code unit per byte) and hand the exact\n // bytes back; every character the escaping reacts to is ASCII.\n return Buffer.from(renderTextLiteral(bytes.toString('latin1'), textStyle), 'latin1');\n }\n case 'blob':\n return renderBlobLiteral(asBytes(value, transport.hexBlob));\n default:\n return 'NULL';\n }\n}\n","import { connectionFeatures, toBuffer } from '../connection/acquire.js';\nimport type { SqliteConnection, SqliteRow } from '../connection/types.js';\nimport type { SqliteColumn, SqliteIndex, SqliteTable } from '../model/database.js';\nimport type { SqliteDiagnostic } from '../model/diagnostics.js';\nimport {\n quoteIdentifier,\n quoteIdentifierIfNeeded,\n quoteQualifiedIdentifier,\n toAsciiLowerCase,\n} from '../security/identifiers.js';\nimport { quoteStringLiteral } from '../security/literals.js';\nimport { isAbortError, throwIfAborted } from '../utils/errors.js';\nimport { SqlChunkBuilder } from './chunkBuilder.js';\nimport type { TableDataExportRequest, TableDataExportResult } from './types.js';\nimport { columnValueSelect, renderColumnLiteral, valueTransport } from './valueQuery.js';\nimport type { SqliteValueTransport } from './valueQuery.js';\n\nconst DEFAULT_MAX_STATEMENT_BYTES = 1024 * 1024;\nconst DEFAULT_MAX_ROWS_PER_STATEMENT = 500;\n\n/**\n * Output is handed to the writer in chunks of about this size. A native dump\n * is one short `INSERT` per row, and awaiting the writer once per row would\n * cost more than rendering the row did.\n */\nconst OUTPUT_CHUNK_BYTES = 64 * 1024;\n\n/** Names the native shell tries, in order, for a rowid that is not a declared column. */\nconst ROWID_NAMES = ['rowid', '_rowid_', 'oid'] as const;\n\n/**\n * The columns the native `.dump` inserts: those `PRAGMA table_info` lists,\n * which excludes generated columns and the hidden columns of virtual tables.\n * Generated columns cannot be inserted into; SQLite recomputes them.\n */\nexport function insertableColumns(table: SqliteTable): SqliteColumn[] {\n return [...table.columns].sort((a, b) => a.cid - b.cid).filter(column => column.hidden === 0);\n}\n\n/**\n * The name under which `preserveRowids` can address a table's rowid, as\n * `tableColumnList()` in `shell.c` decides it: never for a `WITHOUT ROWID`\n * table or one whose rowid is already a declared `INTEGER PRIMARY KEY`, and\n * otherwise the first of `rowid`, `_rowid_`, `oid` that no column is named.\n */\nexport function preservableRowidName(table: SqliteTable): string | null {\n if (table.withoutRowid || table.rowidAliasColumn !== null || table.kind === 'virtual') {\n return null;\n }\n const names = new Set(insertableColumns(table).map(column => toAsciiLowerCase(column.name)));\n for (const candidate of ROWID_NAMES) {\n if (!names.has(candidate)) {\n return candidate;\n }\n }\n return null;\n}\n\n/**\n * Streams one table's rows as `INSERT` statements in the native `.dump`\n * layout.\n *\n * Requires a live connection; this is deliberately separate from\n * `renderPlainSql`, which renders schema objects from the static model and\n * never touches the database.\n *\n * Rows are read in the table's natural order — no `ORDER BY`, exactly like\n * the native `.dump`. For an ordinary table that is rowid order, and for a\n * `WITHOUT ROWID` table primary-key order, so two dumps of an unchanged\n * database are identical.\n *\n * Memory is bounded by one statement plus a small output buffer: rows are\n * consumed from a stream and written as they are rendered, so a table of any\n * size dumps in constant memory.\n */\nexport async function exportTableDataAsInserts(\n request: TableDataExportRequest,\n): Promise<TableDataExportResult> {\n const { connection, schemaName, table, writer, signal, onProgress } = request;\n const options = request.options ?? {};\n const extendedInsert = options.extendedInsert ?? false;\n const maxRowsPerStatement = extendedInsert\n ? Math.max(1, options.maxRowsPerStatement ?? DEFAULT_MAX_ROWS_PER_STATEMENT)\n : 1;\n const maxStatementBytes = Math.max(\n 1024,\n options.maxStatementBytes ?? DEFAULT_MAX_STATEMENT_BYTES,\n );\n const textStyle = options.rawNewlines ? 'raw-newlines' : 'escaped';\n const utf8Database = (request.encoding ?? 'UTF-8').toUpperCase() === 'UTF-8';\n const features = connectionFeatures(connection);\n const transport = valueTransport(utf8Database, features.binaryTransport);\n\n const warnings: SqliteDiagnostic[] = [];\n const columns = insertableColumns(table);\n const rowidName = options.preserveRowids ? preservableRowidName(table) : null;\n\n for (const column of table.columns) {\n if (column.generated !== 'none') {\n warnings.push({\n severity: 'info',\n code: 'generated-column-not-exported',\n message: `Column \"${table.name}\".\"${column.name}\" is a ${column.generated.toUpperCase()} generated column; SQLite derives its value, so it is excluded from INSERT and recomputed on restore.`,\n objectReference: { kind: 'column', schemaName, name: column.name, parentName: table.name },\n });\n }\n }\n\n if (columns.length === 0) {\n warnings.push({\n severity: 'warning',\n code: 'table-has-no-insertable-columns',\n message: `Table \"${table.name}\" has no insertable columns, so no row data is dumped for it.`,\n objectReference: { kind: 'table', schemaName, name: table.name },\n });\n return {\n rowsExported: 0,\n bytesWritten: writer.bytesWritten,\n statementsWritten: 0,\n cancelled: false,\n warnings,\n };\n }\n\n // `INSERT INTO t` (quoted only when the name needs it) and, only when a\n // rowid is being preserved, the column list — the native shell writes one\n // in no other case, relying on the positional form otherwise.\n const columnList = rowidName\n ? `(${[rowidName, ...columns.map(column => quoteIdentifierIfNeeded(column.name))].join(',')})`\n : '';\n const statementPrefix = `INSERT INTO ${quoteIdentifierIfNeeded(table.name)}${columnList} VALUES`;\n\n const selectList = [\n ...(rowidName ? [columnValueSelect(rowidName, 0, utf8Database, transport)] : []),\n ...columns.map((column, index) =>\n columnValueSelect(\n quoteIdentifier(column.name),\n index + (rowidName ? 1 : 0),\n utf8Database,\n transport,\n ),\n ),\n ].join(', ');\n const valueCount = columns.length + (rowidName ? 1 : 0);\n const from = features.schemaQualifiedNames\n ? quoteQualifiedIdentifier(schemaName, table.name)\n : quoteIdentifier(table.name);\n const filter = systemRowFilterCondition(\n table,\n request.systemRowFilter,\n features.reservedNamePrefixes,\n );\n const rows =\n features.pagedReadSize === undefined\n ? connection.stream<SqliteRow>(\n { sql: `SELECT ${selectList} FROM ${from}${filter === null ? '' : ` WHERE ${filter}`}` },\n {\n ...(signal === undefined ? {} : { signal }),\n ...(options.streamBatchSize === undefined\n ? {}\n : { batchSize: options.streamBatchSize }),\n },\n )\n : readPages({\n connection,\n selectList,\n from,\n filter,\n pageSize: features.pagedReadSize,\n key: pageKey(table, columns, rowidName ? 1 : 0, request.primaryKeyIndex),\n transport,\n signal,\n });\n\n let rowsExported = 0;\n let statementsWritten = 0;\n let output = new SqlChunkBuilder();\n let statement: SqlChunkBuilder | null = null;\n let statementRows = 0;\n\n const flushOutput = async (): Promise<void> => {\n if (output.isEmpty) {\n return;\n }\n const chunk = output.build();\n output = new SqlChunkBuilder();\n await writer.write(chunk, signal);\n };\n\n const closeStatement = async (): Promise<void> => {\n if (!statement || statementRows === 0) {\n return;\n }\n statement.append(';\\n');\n output.appendBuilder(statement);\n statement = null;\n statementRows = 0;\n statementsWritten++;\n if (output.length >= OUTPUT_CHUNK_BYTES) {\n await flushOutput();\n }\n };\n\n const progress = (\n exportState: 'started' | 'progress' | 'finished' | 'failed' | 'cancelled',\n ): void => {\n onProgress?.({\n phase: 'exporting-data',\n section: 'table-data',\n schemaName,\n tableName: table.name,\n objectName: table.name,\n rowsExported,\n bytesWritten: writer.bytesWritten,\n exportState,\n });\n };\n\n progress('started');\n try {\n for await (const row of rows) {\n throwIfAborted(signal);\n\n const tuple = new SqlChunkBuilder();\n tuple.append('(');\n for (let index = 0; index < valueCount; index++) {\n if (index > 0) {\n tuple.append(',');\n }\n tuple.append(renderColumnLiteral(row, index, textStyle, transport));\n }\n tuple.append(')');\n\n // Closing *before* appending keeps the byte cap a true upper bound. A\n // statement always holds at least one row, however large that row is.\n if (\n statement &&\n (statementRows >= maxRowsPerStatement ||\n (statement as SqlChunkBuilder).length + tuple.length + 2 > maxStatementBytes)\n ) {\n await closeStatement();\n }\n if (!statement) {\n statement = new SqlChunkBuilder();\n statement.append(statementPrefix);\n } else {\n statement.append(',');\n }\n statement.appendBuilder(tuple);\n statementRows++;\n rowsExported++;\n\n if (rowsExported % 1000 === 0) {\n progress('progress');\n }\n }\n\n await closeStatement();\n await flushOutput();\n progress('finished');\n return {\n rowsExported,\n bytesWritten: writer.bytesWritten,\n statementsWritten,\n cancelled: false,\n warnings,\n };\n } catch (error) {\n if (isAbortError(error)) {\n // Buffered output is deliberately *not* flushed: a dump cut off at an\n // arbitrary row boundary should look truncated, not complete.\n progress('cancelled');\n return {\n rowsExported,\n bytesWritten: writer.bytesWritten,\n statementsWritten,\n cancelled: true,\n warnings,\n };\n }\n progress('failed');\n throw error;\n }\n}\n\n/**\n * For a partial dump, restricts `sqlite_sequence` to the counters of the\n * dumped tables and `sqlite_stat*` to their statistics. Both key the row by\n * table name in their first column (`name` and `tbl` respectively).\n *\n * The rows of tables with a reserved name (see\n * `SqliteConnectionFeatures.reservedNamePrefixes`) are always left out:\n * those tables are not in the dump, so neither are their counters and\n * statistics.\n */\nfunction systemRowFilterCondition(\n table: SqliteTable,\n filter: readonly string[] | undefined,\n reservedPrefixes: readonly string[],\n): string | null {\n if (table.kind !== 'system' || (filter === undefined && reservedPrefixes.length === 0)) {\n return null;\n }\n const column = table.name === 'sqlite_sequence' ? 'name' : 'tbl';\n const conditions: string[] = [];\n if (filter !== undefined) {\n const names = [...new Set(filter.map(toAsciiLowerCase))].map(quoteStringLiteral);\n if (names.length === 0) {\n return '0';\n }\n conditions.push(`lower(${column}) IN (${names.join(',')})`);\n }\n for (const prefix of reservedPrefixes) {\n const lower = toAsciiLowerCase(prefix);\n conditions.push(\n `coalesce(substr(lower(${column}), 1, ${lower.length}) <> ${quoteStringLiteral(lower)}, 1)`,\n );\n }\n return conditions.join(' AND ');\n}\n\n/**\n * How consecutive pages of a table are delimited:\n *\n * - `rowid` — by the rowid (or the column that aliases it), which every\n * ordinary table has: `WHERE rowid > :last ORDER BY rowid`, an index seek\n * per page in exactly the order an unordered scan returns.\n * - `primaryKey` — by the primary key of a `WITHOUT ROWID` table, in the\n * order of its key index, which is again the natural scan order. The key of\n * the last row is written back as the literals this package renders for it.\n * - `offset` — `LIMIT … OFFSET …` with no order, for what has neither: a\n * virtual table, or a table whose `rowid`, `_rowid_` and `oid` are all\n * shadowed by columns.\n */\ntype PageKey =\n | { readonly kind: 'rowid'; readonly expression: string }\n | {\n readonly kind: 'primaryKey';\n readonly columns: readonly {\n readonly expression: string;\n readonly valueIndex: number;\n readonly descending: boolean;\n }[];\n }\n | { readonly kind: 'offset' };\n\nfunction pageKey(\n table: SqliteTable,\n columns: readonly SqliteColumn[],\n valueOffset: number,\n primaryKeyIndex: SqliteIndex | undefined,\n): PageKey {\n if (table.kind === 'virtual') {\n return { kind: 'offset' };\n }\n if (!table.withoutRowid) {\n if (table.rowidAliasColumn !== null) {\n return { kind: 'rowid', expression: quoteIdentifier(table.rowidAliasColumn) };\n }\n const names = new Set(table.columns.map(column => toAsciiLowerCase(column.name)));\n const name = ROWID_NAMES.find(candidate => !names.has(candidate));\n return name === undefined ? { kind: 'offset' } : { kind: 'rowid', expression: name };\n }\n const valueIndexes = new Map(\n columns.map((column, index) => [toAsciiLowerCase(column.name), index + valueOffset]),\n );\n // The key index lists the key in its own order, with direction and\n // collation; without it (an engine that has no `index_xinfo`), the\n // declared primary-key order, ascending, in each column's own collation.\n const keyColumns =\n primaryKeyIndex && primaryKeyIndex.columns.length > 0\n ? primaryKeyIndex.columns.map(column => ({\n name: column.name,\n descending: column.descending,\n collation: column.collation,\n }))\n : [...table.columns]\n .filter(column => column.primaryKeyPosition > 0)\n .sort((a, b) => a.primaryKeyPosition - b.primaryKeyPosition)\n .map(column => ({ name: column.name, descending: false, collation: null }));\n const result: { expression: string; valueIndex: number; descending: boolean }[] = [];\n for (const column of keyColumns) {\n const valueIndex =\n column.name === null ? undefined : valueIndexes.get(toAsciiLowerCase(column.name));\n if (column.name === null || valueIndex === undefined) {\n return { kind: 'offset' };\n }\n const collation =\n column.collation === null || toAsciiLowerCase(column.collation) === 'binary'\n ? ''\n : ` COLLATE ${quoteIdentifier(column.collation)}`;\n result.push({\n expression: `${quoteIdentifier(column.name)}${collation}`,\n valueIndex,\n descending: column.descending,\n });\n }\n return result.length === 0 ? { kind: 'offset' } : { kind: 'primaryKey', columns: result };\n}\n\n/** Alias of the extra rowid column a `rowid`-keyed page selects. */\nconst PAGE_KEY_ALIAS = 'dbgate_page_key';\n\n/** Reads a table page by page through `query()`; see {@link PageKey}. */\nasync function* readPages(request: {\n readonly connection: SqliteConnection;\n readonly selectList: string;\n readonly from: string;\n readonly filter: string | null;\n readonly pageSize: number;\n readonly key: PageKey;\n readonly transport: SqliteValueTransport;\n readonly signal: AbortSignal | undefined;\n}): AsyncGenerator<SqliteRow> {\n const { connection, selectList, from, filter, pageSize, key, transport, signal } = request;\n let after: string | null = null;\n let offset = 0;\n for (;;) {\n throwIfAborted(signal);\n const conditions = [filter, after].filter(condition => condition !== null);\n const where =\n conditions.length === 0 ? '' : ` WHERE ${conditions.map(c => `(${c})`).join(' AND ')}`;\n let sql: string;\n if (key.kind === 'rowid') {\n sql = `SELECT ${selectList}, CAST(${key.expression} AS TEXT) AS \"${PAGE_KEY_ALIAS}\" FROM ${from}${where} ORDER BY ${key.expression} LIMIT ${pageSize}`;\n } else if (key.kind === 'primaryKey') {\n const order = key.columns\n .map(column => `${column.expression}${column.descending ? ' DESC' : ''}`)\n .join(', ');\n sql = `SELECT ${selectList} FROM ${from}${where} ORDER BY ${order} LIMIT ${pageSize}`;\n } else {\n sql = `SELECT ${selectList} FROM ${from}${where} LIMIT ${pageSize} OFFSET ${offset}`;\n }\n const { rows } = await connection.query<SqliteRow>({ sql }, signal);\n for (const row of rows) {\n yield row;\n }\n if (rows.length < pageSize) {\n return;\n }\n const last = rows[rows.length - 1] as SqliteRow;\n if (key.kind === 'rowid') {\n after = `${key.expression} > ${String(last[PAGE_KEY_ALIAS])}`;\n } else if (key.kind === 'primaryKey') {\n after = keyAfterCondition(key.columns, last, transport);\n } else {\n offset += rows.length;\n }\n }\n}\n\n/**\n * `key > last` in key-index order, expanded column by column\n * (`a > x OR (a = x AND b > y) …`) so that each column compares in its own\n * direction and collation.\n */\nfunction keyAfterCondition(\n columns: readonly {\n readonly expression: string;\n readonly valueIndex: number;\n readonly descending: boolean;\n }[],\n row: SqliteRow,\n transport: SqliteValueTransport,\n): string {\n const literals = columns.map(column => keyLiteral(row, column.valueIndex, transport));\n const alternatives: string[] = [];\n for (let position = 0; position < columns.length; position++) {\n const terms: string[] = [];\n for (let previous = 0; previous < position; previous++) {\n terms.push(\n `${(columns[previous] as { expression: string }).expression} = ${literals[previous]}`,\n );\n }\n const column = columns[position] as { expression: string; descending: boolean };\n terms.push(`${column.expression} ${column.descending ? '<' : '>'} ${literals[position]}`);\n alternatives.push(terms.length === 1 ? (terms[0] as string) : `(${terms.join(' AND ')})`);\n }\n return alternatives.join(' OR ');\n}\n\n/** A key value of the last row of a page, as a literal for the next page's condition. */\nfunction keyLiteral(row: SqliteRow, index: number, transport: SqliteValueTransport): string {\n const literal = renderColumnLiteral(row, index, 'escaped', transport);\n if (typeof literal === 'string') {\n return literal;\n }\n // Text that is not valid UTF-8 is rendered as raw bytes; as a condition it\n // is written as those bytes, cast back to text.\n const value = row[`v${index}`] ?? null;\n const bytes =\n typeof value === 'string'\n ? Buffer.from(value, transport.hexText ? 'hex' : 'utf8')\n : toBuffer(value as Uint8Array | ArrayBuffer | readonly number[]);\n return `CAST(X'${bytes.toString('hex').toUpperCase()}' AS TEXT)`;\n}\n","import type { SqliteDatabase } from '../model/database.js';\nimport type { SqliteDiagnostic } from '../model/diagnostics.js';\nimport { toAsciiLowerCase, toAsciiUpperCase } from '../security/identifiers.js';\nimport { detectSqliteCapabilities } from '../version/capabilities.js';\nimport type { SqliteCapabilities } from '../version/types.js';\n\n/**\n * A restore target's capabilities have the same shape as a source's, but the\n * two stay distinct concepts: a source's describe what introspection may\n * use, a target's what DDL it can accept.\n */\nexport type TargetCapabilities = SqliteCapabilities;\n\nexport { detectSqliteCapabilities as detectTargetCapabilities };\n\nexport interface TargetCompatibilityOptions {\n /**\n * Virtual table modules the target has (`PRAGMA module_list`), when known.\n * Without it, module availability is not checked.\n */\n readonly modules?: ReadonlySet<string>;\n /** The dump names `sqlite_master` rather than `sqlite_schema`; see `PlainSqlRenderOptions`. */\n readonly legacySchemaTableName?: boolean;\n /** The dump uses multi-row `INSERT ... VALUES (...), (...)`. */\n readonly extendedInsert?: boolean;\n}\n\nconst FEATURE_LABELS: Record<keyof TargetCapabilities, string> = {\n supportsWithoutRowid: 'WITHOUT ROWID tables (SQLite 3.8.2+)',\n supportsMultiRowValues: 'multi-row VALUES (SQLite 3.7.11+)',\n supportsPragmaFunctions: 'table-valued pragma functions (SQLite 3.16.0+)',\n supportsTableXinfo: 'PRAGMA table_xinfo (SQLite 3.26.0+)',\n supportsGeneratedColumns: 'generated columns (SQLite 3.31.0+)',\n supportsSqliteSchemaAlias: 'the sqlite_schema table name (SQLite 3.33.0+)',\n supportsWritableSchemaReset: 'PRAGMA writable_schema=RESET (SQLite 3.35.0+)',\n supportsStrictTables: 'STRICT tables (SQLite 3.37.0+)',\n supportsTableList: 'PRAGMA table_list (SQLite 3.37.0+)',\n};\n\n/** Collations every SQLite build has. Any other must be registered by the restoring application. */\nconst BUILT_IN_COLLATIONS: ReadonlySet<string> = new Set(['BINARY', 'NOCASE', 'RTRIM']);\n\n/**\n * Reports what a dump of `database` needs that `target` cannot provide.\n *\n * Feature-level rather than statement-level: the dump carries SQLite's own\n * stored DDL, so what can be checked is which features the source model\n * actually uses — which turns \"restore failed with a syntax error at line\n * 4713\" into \"the target is SQLite 3.31 and this dump contains STRICT\n * tables\".\n *\n * Never throws: callers decide whether an unsupported feature blocks the\n * restore or is merely reported.\n */\nexport function checkTargetCompatibility(\n database: SqliteDatabase,\n target: TargetCapabilities,\n options: TargetCompatibilityOptions = {},\n): SqliteDiagnostic[] {\n const diagnostics: SqliteDiagnostic[] = [];\n const { schemaName } = database;\n const reported = new Set<keyof TargetCapabilities>();\n\n const require = (\n feature: keyof TargetCapabilities,\n detail: string,\n objectReference?: SqliteDiagnostic['objectReference'],\n ): void => {\n if (target[feature] || reported.has(feature)) {\n return;\n }\n reported.add(feature);\n diagnostics.push({\n severity: 'error',\n code: 'unsupported-target-feature',\n message: `Restore target does not support ${FEATURE_LABELS[feature]}, which this dump uses: ${detail}`,\n ...(objectReference === undefined ? {} : { objectReference }),\n });\n };\n\n const missingModules = new Set<string>();\n for (const table of database.tables) {\n const reference = { kind: 'table' as const, schemaName, name: table.name };\n if (table.strict) {\n require('supportsStrictTables', `table \"${table.name}\"`, reference);\n }\n if (table.withoutRowid) {\n require('supportsWithoutRowid', `table \"${table.name}\"`, reference);\n }\n for (const column of table.columns) {\n if (column.generated !== 'none') {\n require('supportsGeneratedColumns', `column \"${table.name}\".\"${column.name}\"`, {\n kind: 'column',\n schemaName,\n name: column.name,\n parentName: table.name,\n });\n }\n }\n if (table.kind === 'virtual') {\n if (!options.legacySchemaTableName) {\n require('supportsSqliteSchemaAlias', `virtual table \"${table.name}\" is recreated through INSERT INTO sqlite_schema`, reference);\n }\n const module =\n table.virtualModule === undefined ? undefined : toAsciiLowerCase(table.virtualModule);\n if (\n options.modules &&\n module !== undefined &&\n !options.modules.has(module) &&\n !missingModules.has(module)\n ) {\n missingModules.add(module);\n diagnostics.push({\n severity: 'error',\n code: 'virtual-table-module-unavailable',\n message: `Restore target has no \"${table.virtualModule}\" module, which virtual table \"${table.name}\" needs. The dump still restores — its schema row and shadow tables are plain SQL — but the table cannot be queried there until the module is loaded.`,\n objectReference: { kind: 'virtualTable', schemaName, name: table.name },\n });\n }\n }\n if (\n table.kind === 'system' &&\n /^sqlite_stat/.test(table.name) &&\n !options.legacySchemaTableName\n ) {\n require('supportsSqliteSchemaAlias', 'the statistics tables are recreated by ANALYZE sqlite_schema', reference);\n }\n }\n\n if (options.extendedInsert) {\n require('supportsMultiRowValues', 'dataExport.extendedInsert is enabled');\n }\n\n const customCollations = new Map<string, string>();\n for (const index of database.indexes) {\n for (const column of index.columns) {\n if (\n column.collation !== null &&\n !BUILT_IN_COLLATIONS.has(toAsciiUpperCase(column.collation))\n ) {\n customCollations.set(toAsciiUpperCase(column.collation), index.name);\n }\n }\n }\n for (const [collation, indexName] of customCollations) {\n diagnostics.push({\n severity: 'warning',\n code: 'custom-collation',\n message: `Index \"${indexName}\" uses the collation ${collation}, which is not built into SQLite. The restoring application must register it (sqlite3_create_collation) before the restore, or the index cannot be created.`,\n objectReference: { kind: 'index', schemaName, name: indexName },\n });\n }\n\n return diagnostics;\n}\n","import type { SqliteDiagnostic } from '../model/diagnostics.js';\n\n/**\n * Database state this package deliberately does not dump.\n *\n * Every one of these is either a property of the database *file* rather\n * than of its contents, or lives outside SQL entirely. Rather than silently\n * omitting them — which would make a dump look complete when it is not —\n * each is described here so `unsupportedFeatureDiagnostics()` can report\n * them, and `docs/known-limitations.md` can list them with the same wording.\n */\nexport const UNSUPPORTED_FEATURES: readonly {\n readonly code: string;\n readonly summary: string;\n readonly detail: string;\n}[] = [\n {\n code: 'file-settings-not-dumped',\n summary: 'file-level settings (page_size, auto_vacuum, journal_mode, encoding)',\n detail:\n 'These describe how the database file is laid out, not what it contains, and most can only be chosen before the first table is created. The native .dump does not carry them either. Set them on the target database before restoring if they matter; the dump restores correctly under any of them.',\n },\n {\n code: 'temp-and-attached-schemas-not-dumped',\n summary: 'the temp schema and attached databases',\n detail:\n 'A dump covers one schema — main by default. Temporary objects belong to one connection, and each attached database is a separate file; dump an attached database on its own by passing its name as schemaName.',\n },\n {\n code: 'application-functions-not-dumped',\n summary: 'application-defined functions, collations and loadable extensions',\n detail:\n 'User-defined SQL functions, collating sequences and virtual table modules are registered by the application (or loaded from a shared library), not stored in the database. The schema that uses them is dumped verbatim; the restoring application must register them first, or objects using them cannot be created or queried.',\n },\n {\n code: 'encryption-not-dumped',\n summary: 'encryption keys',\n detail:\n 'An encrypted database (SQLCipher, SEE) is dumped as plain SQL once it is opened with its key. The dump itself is not encrypted, and no key is ever written into it.',\n },\n];\n\n/** The {@link UNSUPPORTED_FEATURES} as `info` diagnostics, for a UI that lists what a dump does not include. */\nexport function unsupportedFeatureDiagnostics(): SqliteDiagnostic[] {\n return UNSUPPORTED_FEATURES.map(feature => ({\n severity: 'info',\n code: feature.code,\n message: `Not dumped: ${feature.summary}. ${feature.detail}`,\n }));\n}\n","import { acquireSqliteConnection, toNumber, toText } from '../connection/acquire.js';\nimport type { SqliteConnection, SqliteConnectionInput, SqliteRow } from '../connection/types.js';\nimport { checkTargetCompatibility } from '../compatibility/check.js';\nimport type { TargetCompatibilityOptions } from '../compatibility/check.js';\nimport type { SqliteDatabase } from '../model/database.js';\nimport type { SqliteDiagnostic } from '../model/diagnostics.js';\nimport { toAsciiLowerCase } from '../security/identifiers.js';\nimport { isAbortError } from '../utils/errors.js';\nimport { detectSqliteCapabilities } from '../version/capabilities.js';\nimport { detectSqliteVersion } from '../version/detect.js';\nimport type { SqliteCapabilities, SqliteVersion } from '../version/types.js';\n\nexport interface PreflightRestoreRequest {\n readonly connection: SqliteConnectionInput;\n /**\n * The model of the database the dump was taken from (from\n * `introspectSqlite`). With it, the report answers \"what does this dump\n * need that this target cannot do\"; without it, only \"what can this target\n * do\".\n */\n readonly database?: SqliteDatabase;\n readonly options?: TargetCompatibilityOptions & {\n /** The dump was rendered with `addDropStatements`, so existing objects are replaced rather than conflicting. */\n readonly addDropStatements?: boolean;\n };\n readonly signal?: AbortSignal;\n}\n\nexport interface PreflightRestoreReport {\n readonly version: SqliteVersion;\n readonly capabilities: SqliteCapabilities;\n /** `PRAGMA encoding` of the target. */\n readonly encoding: string;\n /** Whether the target enforces foreign keys (`PRAGMA foreign_keys`). */\n readonly foreignKeysEnabled: boolean;\n /** Whether the handle is already inside a transaction. `undefined` when the adapter cannot tell. */\n readonly inTransaction?: boolean;\n /** Whether the adapter can lift defensive mode for a dump that writes `sqlite_schema`. */\n readonly canDisableDefensiveMode: boolean;\n /** Virtual table modules the target has, when `PRAGMA module_list` is available. */\n readonly modules?: readonly string[];\n /** `PRAGMA compile_options` of the target, when readable. */\n readonly compileOptions?: readonly string[];\n /** Tables, views, indexes and triggers already present in the target's `main` schema. */\n readonly existingObjects: readonly { readonly type: string; readonly name: string }[];\n readonly diagnostics: readonly SqliteDiagnostic[];\n}\n\nasync function queryRows(\n connection: SqliteConnection,\n sql: string,\n signal?: AbortSignal,\n): Promise<readonly SqliteRow[] | undefined> {\n try {\n return (await connection.query<SqliteRow>({ sql }, signal)).rows;\n } catch (error) {\n if (isAbortError(error)) throw error;\n return undefined;\n }\n}\n\nfunction firstValue(rows: readonly SqliteRow[] | undefined): unknown {\n const first = rows?.[0];\n return first === undefined ? undefined : Object.values(first)[0];\n}\n\n/**\n * Inspects a restore target before anything is written to it.\n *\n * Turns a failure part-way through a restore — `table t already exists`,\n * `no such module: fts5`, a syntax error on a `STRICT` table — into an\n * up-front, actionable report. Never writes to the target.\n */\nexport async function preflightRestore(\n request: PreflightRestoreRequest,\n): Promise<PreflightRestoreReport> {\n const acquired = await acquireSqliteConnection(request.connection, request.signal);\n const connection = acquired.connection;\n const { signal } = request;\n try {\n const version = await detectSqliteVersion(connection, signal);\n const capabilities = detectSqliteCapabilities(version);\n const encoding =\n toText(firstValue(await queryRows(connection, 'PRAGMA encoding', signal))) ?? 'UTF-8';\n const foreignKeysEnabled =\n toNumber(firstValue(await queryRows(connection, 'PRAGMA foreign_keys', signal))) !== 0;\n const moduleRows = await queryRows(connection, 'SELECT name FROM pragma_module_list', signal);\n const optionRows = await queryRows(connection, 'PRAGMA compile_options', signal);\n const compileOptions = optionRows?.map(row => toText(Object.values(row)[0]) ?? '');\n const modules = moduleRows?.map(row => toText(row.name) ?? '').filter(name => name !== '');\n const existingRows =\n (await queryRows(\n connection,\n \"SELECT type, name FROM main.sqlite_master WHERE sql IS NOT NULL AND name NOT LIKE 'sqlite\\\\_%' ESCAPE '\\\\' ORDER BY rowid\",\n signal,\n )) ?? [];\n const existingObjects = existingRows.map(row => ({\n type: toText(row.type) ?? '',\n name: toText(row.name) ?? '',\n }));\n const inTransaction = connection.isInTransaction?.();\n\n const diagnostics: SqliteDiagnostic[] = [];\n if (inTransaction) {\n diagnostics.push({\n severity: 'warning',\n code: 'target-in-transaction',\n message:\n 'The target handle is already inside a transaction. A full dump\\'s own BEGIN TRANSACTION will fail; commit first, or restore with transaction: \"wrap\".',\n });\n }\n\n const database = request.database;\n if (database) {\n diagnostics.push(\n ...checkTargetCompatibility(database, capabilities, {\n ...request.options,\n ...(modules === undefined ? {} : { modules: new Set(modules.map(toAsciiLowerCase)) }),\n }),\n );\n\n const hasVirtualTables = database.tables.some(table => table.kind === 'virtual');\n if (hasVirtualTables && !connection.setDefensive) {\n diagnostics.push({\n severity: 'warning',\n code: 'defensive-mode-not-controllable',\n message:\n 'This dump recreates virtual tables by writing sqlite_schema directly, which SQLITE_DBCONFIG_DEFENSIVE forbids, and this adapter cannot turn defensive mode off. The restore succeeds only if the connection is not in defensive mode.',\n });\n }\n\n const hasStat4 = database.tables.some(table => table.name === 'sqlite_stat4');\n if (hasStat4 && compileOptions && !compileOptions.includes('ENABLE_STAT4')) {\n diagnostics.push({\n severity: 'error',\n code: 'statistics-table-unsupported',\n message:\n \"The source database has a sqlite_stat4 table, and the target SQLite is not built with SQLITE_ENABLE_STAT4, so ANALYZE there does not create it and the dump's INSERT INTO sqlite_stat4 fails. The native .dump of such a database fails the same way. Dump with objectKinds.includeSystemTables: false, or drop sqlite_stat4 from the source copy first.\",\n });\n }\n\n if (database.encoding.toUpperCase() !== encoding.toUpperCase()) {\n diagnostics.push({\n severity: 'info',\n code: 'encoding-differs',\n message: `The source database is ${database.encoding} and the target is ${encoding}. Text is converted between the two on restore, which is lossless for valid text.`,\n });\n }\n\n if (!request.options?.addDropStatements) {\n const existing = new Map(\n existingObjects.map(object => [toAsciiLowerCase(object.name), object]),\n );\n const created = [\n ...database.tables.filter(table => table.kind !== 'system').map(table => table.name),\n ...database.views.map(view => view.name),\n ...database.indexes.filter(index => index.sql !== null).map(index => index.name),\n ...database.triggers.map(trigger => trigger.name),\n ];\n for (const name of created) {\n const conflict = existing.get(toAsciiLowerCase(name));\n if (conflict) {\n diagnostics.push({\n severity: 'error',\n code: 'object-already-exists',\n message: `The target already has a ${conflict.type} named \"${conflict.name}\", so the dump's CREATE for it will fail. Restore into an empty database, drop it first, or render the dump with addDropStatements.`,\n objectReference: { kind: 'table', schemaName: 'main', name: conflict.name },\n });\n }\n }\n }\n }\n\n return {\n version,\n capabilities,\n encoding,\n foreignKeysEnabled,\n ...(inTransaction === undefined ? {} : { inTransaction }),\n canDisableDefensiveMode: typeof connection.setDefensive === 'function',\n ...(modules === undefined ? {} : { modules }),\n ...(compileOptions === undefined ? {} : { compileOptions }),\n existingObjects,\n diagnostics,\n };\n } finally {\n await acquired.release();\n }\n}\n","import type { SqliteErrorInfo } from '../connection/types.js';\nimport { SqliteDumperError } from '../utils/errors.js';\nimport type { StatementSourceLocation } from './location.js';\n\n/** Common base for every error {@link restoreSqlDump} (or its parser) throws intentionally. */\nexport class RestoreError extends SqliteDumperError {}\n\n/**\n * The input could not be split into statements correctly.\n *\n * Always fatal: unlike a statement that fails when executed, a parse failure\n * means the statement boundaries themselves are not trustworthy, so nothing\n * after the failure point can be safely executed either.\n */\nexport class SqlParseError extends RestoreError {\n readonly line: number;\n\n constructor(code: string, message: string, line: number, options?: { cause?: unknown }) {\n super(code, message, options);\n this.name = 'SqlParseError';\n this.line = line;\n }\n}\n\n/**\n * The input ended while a quoted token — a string, a `\"`/`` ` ``/`[...]`\n * identifier — was still open. The script is structurally incomplete (most\n * often a truncated file) and cannot be split into valid statements.\n *\n * An unterminated `/*` comment is *not* reported: SQLite itself accepts a\n * block comment that runs to the end of the input.\n */\nexport class MalformedSqlDumpError extends SqlParseError {\n readonly openConstruct: string;\n\n constructor(openConstruct: string, line: number) {\n super(\n 'malformed-sql-dump',\n `Unterminated ${openConstruct} starting at line ${line}: the input ends before it is closed`,\n line,\n );\n this.name = 'MalformedSqlDumpError';\n this.openConstruct = openConstruct;\n }\n}\n\n/**\n * One statement's accumulated text exceeded\n * {@link SqlStatementParserOptions.maxStatementBytes} before it was\n * complete.\n *\n * A statement must be sent to SQLite whole, so this bounds how much of a\n * pathological input — a truncated dump, or an unterminated `CREATE TRIGGER`\n * that swallows the rest of the file — the parser will buffer before giving\n * up, instead of growing without limit.\n */\nexport class StatementTooLargeError extends SqlParseError {\n readonly maxStatementBytes: number;\n\n constructor(maxStatementBytes: number, line: number) {\n super(\n 'statement-too-large',\n `Statement starting near line ${line} exceeds the configured limit of ${maxStatementBytes} bytes without being complete; increase options.maxStatementBytes if this statement is genuinely intended to be this large, or check for a CREATE TRIGGER missing its END`,\n line,\n );\n this.name = 'StatementTooLargeError';\n this.maxStatementBytes = maxStatementBytes;\n }\n}\n\n/**\n * A `sqlite3` shell dot-command was found that would change what the script\n * does to the database.\n *\n * The shell executes lines beginning with `.` itself (`.read`, `.import`,\n * `.open`, `.load`, `.shell`, ...) before anything reaches SQLite. Commands\n * that only affect the shell's own presentation (`.mode`, `.headers`,\n * `.print`, ...) are skipped with a warning; the rest are refused with a\n * precise diagnostic rather than being silently ignored, which would corrupt\n * the restore — a `.read` that never runs leaves the referenced file's\n * objects missing, and an `.import` that never runs leaves a table empty.\n */\nexport class UnsupportedClientCommandError extends SqlParseError {\n readonly command: string;\n\n constructor(command: string, line: number) {\n super(\n 'unsupported-client-command',\n `Unsupported sqlite3 shell command \".${command}\" on line ${line}: dbgate-sqlite-dumper executes SQL statements and does not implement shell dot-commands that change the database. Run this script through the sqlite3 shell, or remove the command.`,\n line,\n );\n this.name = 'UnsupportedClientCommandError';\n this.command = command;\n }\n}\n\n/**\n * A statement holds bytes that are not valid UTF-8 outside any string\n * literal, so it cannot be handed to SQLite as text without corrupting them.\n *\n * Invalid UTF-8 *inside* a string literal — which the native `.dump` writes\n * whenever a `TEXT` value holds such bytes — is handled transparently, by\n * rewriting the literal into the equivalent `CAST(X'...' AS TEXT)`. Reaching\n * this error means the bytes are in an identifier or keyword position.\n */\nexport class InvalidTextEncodingError extends SqlParseError {\n constructor(message: string, line: number) {\n super('invalid-text-encoding', `${message} (near line ${line})`, line);\n this.name = 'InvalidTextEncodingError';\n }\n}\n\n/**\n * A statement parsed successfully but failed when executed.\n *\n * Unlike a parse error this is scoped to one statement: with\n * `stopOnError: false`, restoration continues with the next one, and this\n * error's data — never the raw driver error, which can echo back parts of\n * the failing statement — is what is recorded in\n * {@link SqlDumpRestoreResult.errors}.\n */\nexport class RestoreExecutionError extends RestoreError {\n readonly statementIndex: number;\n readonly location: StatementSourceLocation;\n readonly sqlPreview: string;\n readonly sqliteError?: SqliteErrorInfo;\n\n constructor(\n statementIndex: number,\n location: StatementSourceLocation,\n sqlPreview: string,\n message: string,\n sqliteError?: SqliteErrorInfo,\n options?: { cause?: unknown },\n ) {\n super('restore-execution-failed', message, options);\n this.name = 'RestoreExecutionError';\n this.statementIndex = statementIndex;\n this.location = location;\n this.sqlPreview = sqlPreview;\n if (sqliteError) {\n this.sqliteError = sqliteError;\n }\n }\n}\n","import { toAsciiLowerCase, toAsciiUpperCase } from '../security/identifiers.js';\nimport { isIdentifierCharCode } from './complete.js';\n\ninterface LeadingToken {\n readonly kind: 'word' | 'quoted' | 'string' | 'punct' | 'number';\n /** For `word`: the text; for `quoted`/`string`: the unquoted value; else the character(s). */\n readonly value: string;\n}\n\n/**\n * Reads the first `limit` tokens of a statement, skipping whitespace and\n * comments. Enough to recognize what a statement *is* without parsing it.\n */\nfunction leadingTokens(sql: string, limit: number): LeadingToken[] {\n const tokens: LeadingToken[] = [];\n let index = 0;\n const length = sql.length;\n while (index < length && tokens.length < limit) {\n const character = sql[index] as string;\n const code = sql.charCodeAt(index);\n if (/\\s/.test(character) || character === '\\uFEFF') {\n index++;\n continue;\n }\n if (character === '-' && sql[index + 1] === '-') {\n const end = sql.indexOf('\\n', index);\n index = end === -1 ? length : end + 1;\n continue;\n }\n if (character === '/' && sql[index + 1] === '*') {\n const end = sql.indexOf('*/', index + 2);\n index = end === -1 ? length : end + 2;\n continue;\n }\n if (character === '\"' || character === '`' || character === \"'\" || character === '[') {\n const close = character === '[' ? ']' : character;\n let value = '';\n index++;\n while (index < length) {\n if (sql[index] === close) {\n if (close !== ']' && sql[index + 1] === close) {\n value += close;\n index += 2;\n continue;\n }\n index++;\n break;\n }\n value += sql[index];\n index++;\n }\n tokens.push({ kind: character === \"'\" ? 'string' : 'quoted', value });\n continue;\n }\n if (code >= 0x30 && code <= 0x39) {\n let end = index + 1;\n while (end < length && /[0-9A-Za-z_.+-]/.test(sql[end] as string)) {\n end++;\n }\n tokens.push({ kind: 'number', value: sql.slice(index, end) });\n index = end;\n continue;\n }\n if (isIdentifierCharCode(code)) {\n let end = index + 1;\n while (end < length && isIdentifierCharCode(sql.charCodeAt(end))) {\n end++;\n }\n tokens.push({ kind: 'word', value: sql.slice(index, end) });\n index = end;\n continue;\n }\n tokens.push({ kind: 'punct', value: character });\n index++;\n }\n return tokens;\n}\n\n/** What a statement is, as far as restore bookkeeping needs to know. */\nexport interface StatementInfo {\n /** The statement's first keyword, upper-cased: `CREATE`, `INSERT`, `PRAGMA`, `BEGIN`, ... */\n readonly verb: string;\n /** For `CREATE`: the object kind (`TABLE`, `INDEX`, `VIEW`, `TRIGGER`, `VIRTUAL TABLE`). */\n readonly objectKind?: string;\n /** The object the statement creates, fills or changes, when recognizable. */\n readonly objectName?: string;\n /** For `PRAGMA`: the pragma name, lower-cased, without a schema prefix. */\n readonly pragmaName?: string;\n /** For `PRAGMA x = value` / `PRAGMA x(value)`: the value as written, unquoted. */\n readonly pragmaValue?: string;\n /**\n * `begin`, `commit`, `rollback`, `savepoint`, `release` or\n * `rollback-to-savepoint` for transaction-control statements.\n */\n readonly transactionControl?:\n 'begin' | 'commit' | 'rollback' | 'rollback-to-savepoint' | 'savepoint' | 'release';\n}\n\nfunction nameToken(token: LeadingToken | undefined): string | undefined {\n if (!token) {\n return undefined;\n }\n return token.kind === 'word' || token.kind === 'quoted' || token.kind === 'string'\n ? token.value\n : undefined;\n}\n\n/** Skips an optional `schema.` qualifier, returning the unqualified name and the next position. */\nfunction qualifiedName(\n tokens: readonly LeadingToken[],\n position: number,\n): { name?: string; next: number } {\n const first = nameToken(tokens[position]);\n if (first === undefined) {\n return { next: position };\n }\n if (tokens[position + 1]?.kind === 'punct' && tokens[position + 1]?.value === '.') {\n const second = nameToken(tokens[position + 2]);\n return second === undefined\n ? { name: first, next: position + 1 }\n : { name: second, next: position + 3 };\n }\n return { name: first, next: position + 1 };\n}\n\nfunction isWord(token: LeadingToken | undefined, word: string): boolean {\n return token?.kind === 'word' && toAsciiUpperCase(token.value) === word;\n}\n\n/**\n * Classifies a statement from its leading tokens.\n *\n * Used for restore progress (`currentObject`), for following the script's\n * own transaction control, and for noticing the session-level pragmas a dump\n * changes (`foreign_keys`, `writable_schema`) so they can be put back if the\n * restore stops early.\n */\nexport function describeStatement(sql: string): StatementInfo {\n const tokens = leadingTokens(sql, 12);\n const first = tokens[0];\n if (!first || first.kind !== 'word') {\n return { verb: '' };\n }\n const verb = toAsciiUpperCase(first.value);\n\n switch (verb) {\n case 'BEGIN':\n return { verb, transactionControl: 'begin' };\n case 'COMMIT':\n case 'END':\n return { verb, transactionControl: 'commit' };\n case 'ROLLBACK': {\n // ROLLBACK [TRANSACTION] TO [SAVEPOINT] name only unwinds to a savepoint.\n const toPosition = isWord(tokens[1], 'TRANSACTION') ? 2 : 1;\n return isWord(tokens[toPosition], 'TO')\n ? { verb, transactionControl: 'rollback-to-savepoint' }\n : { verb, transactionControl: 'rollback' };\n }\n case 'SAVEPOINT':\n return { verb, transactionControl: 'savepoint' };\n case 'RELEASE':\n return { verb, transactionControl: 'release' };\n case 'PRAGMA': {\n const { name, next } = qualifiedName(tokens, 1);\n if (name === undefined) {\n return { verb };\n }\n const pragmaName = toAsciiLowerCase(name);\n const operator = tokens[next];\n if (operator?.kind === 'punct' && (operator.value === '=' || operator.value === '(')) {\n const valueToken = tokens[next + 1];\n let value = valueToken?.value;\n if (\n valueToken?.kind === 'punct' &&\n (valueToken.value === '-' || valueToken.value === '+')\n ) {\n value = `${valueToken.value}${tokens[next + 2]?.value ?? ''}`;\n }\n return value === undefined\n ? { verb, pragmaName }\n : { verb, pragmaName, pragmaValue: value };\n }\n return { verb, pragmaName };\n }\n case 'INSERT':\n case 'REPLACE': {\n let position = 1;\n if (verb === 'INSERT' && isWord(tokens[1], 'OR')) {\n position = 3;\n }\n if (isWord(tokens[position], 'INTO')) {\n position++;\n }\n const { name } = qualifiedName(tokens, position);\n return name === undefined ? { verb } : { verb, objectName: name };\n }\n case 'DELETE': {\n const position = isWord(tokens[1], 'FROM') ? 2 : 1;\n const { name } = qualifiedName(tokens, position);\n return name === undefined ? { verb } : { verb, objectName: name };\n }\n case 'UPDATE':\n case 'ANALYZE':\n case 'DROP': {\n let position = 1;\n let objectKind: string | undefined;\n if (verb === 'DROP' && tokens[1]?.kind === 'word') {\n objectKind = toAsciiUpperCase(tokens[1].value);\n position = 2;\n if (isWord(tokens[2], 'IF') && isWord(tokens[3], 'EXISTS')) {\n position = 4;\n }\n }\n const { name } = qualifiedName(tokens, position);\n return {\n verb,\n ...(objectKind === undefined ? {} : { objectKind }),\n ...(name === undefined ? {} : { objectName: name }),\n };\n }\n case 'CREATE': {\n let position = 1;\n while (\n isWord(tokens[position], 'TEMP') ||\n isWord(tokens[position], 'TEMPORARY') ||\n isWord(tokens[position], 'UNIQUE')\n ) {\n position++;\n }\n let objectKind =\n tokens[position]?.kind === 'word' ? toAsciiUpperCase(tokens[position]!.value) : '';\n position++;\n if (objectKind === 'VIRTUAL' && isWord(tokens[position], 'TABLE')) {\n objectKind = 'VIRTUAL TABLE';\n position++;\n }\n if (isWord(tokens[position], 'IF') && isWord(tokens[position + 1], 'NOT')) {\n position += 3;\n }\n const { name } = qualifiedName(tokens, position);\n return {\n verb,\n ...(objectKind === '' ? {} : { objectKind }),\n ...(name === undefined ? {} : { objectName: name }),\n };\n }\n default:\n return { verb };\n }\n}\n","import { isUtf8 } from 'node:buffer';\nimport { InvalidTextEncodingError } from './errors.js';\n\n/**\n * Converts a statement's bytes into text SQLite can be handed, preserving\n * every byte.\n *\n * SQLite does not validate the encoding of the text it stores, and the\n * native `.dump` writes a `TEXT` value's bytes exactly as stored — so a value\n * holding bytes that are not valid UTF-8 appears in the dump as a string\n * literal that is not valid UTF-8 either. The `sqlite3` shell passes those\n * bytes straight to `sqlite3_prepare()`, which stores them unchanged. A\n * JavaScript driver cannot: its statement text is a JavaScript string, and\n * every invalid sequence would become U+FFFD on the way in.\n *\n * So a literal that is not valid UTF-8 is rewritten into an expression that\n * yields the identical bytes as text, written entirely in ASCII:\n *\n * ```sql\n * 'caf\\xE9' → (CAST(X'636166e9' AS TEXT))\n * ```\n *\n * In a UTF-8 database (every database the native `.dump` can reproduce\n * exactly) that is byte-for-byte the value the shell would have stored.\n * Invalid bytes inside a comment are dropped along with the comment; invalid\n * bytes anywhere else — in an identifier or keyword position — cannot be\n * represented and raise {@link InvalidTextEncodingError}.\n *\n * `statement` is a byte string: one code unit per byte, as `latin1` decodes\n * it. Returns the statement as ordinary text, plus how many literals were\n * rewritten.\n */\nexport function decodeStatementBytes(\n statement: string,\n startLine: number,\n): { sql: string; literalsRewritten: number } {\n const bytes = Buffer.from(statement, 'latin1');\n if (isUtf8(bytes)) {\n return { sql: bytes.toString('utf8'), literalsRewritten: 0 };\n }\n\n let output = '';\n let literalsRewritten = 0;\n let line = startLine;\n let index = 0;\n const length = statement.length;\n\n const appendPlain = (segment: string): void => {\n const segmentBytes = Buffer.from(segment, 'latin1');\n if (!isUtf8(segmentBytes)) {\n throw new InvalidTextEncodingError(\n 'The statement contains bytes that are not valid UTF-8 outside any string literal, so it cannot be executed as text without corrupting them',\n line,\n );\n }\n output += segmentBytes.toString('utf8');\n };\n\n let plainStart = 0;\n while (index < length) {\n const character = statement[index] as string;\n if (character === '\\n') {\n line++;\n index++;\n continue;\n }\n if (character === \"'\") {\n appendPlain(statement.slice(plainStart, index));\n let end = index + 1;\n for (;;) {\n const close = statement.indexOf(\"'\", end);\n if (close === -1) {\n end = length;\n break;\n }\n if (statement[close + 1] === \"'\") {\n end = close + 2;\n continue;\n }\n end = close + 1;\n break;\n }\n const literal = statement.slice(index, end);\n const literalBytes = Buffer.from(literal, 'latin1');\n if (isUtf8(literalBytes)) {\n output += literalBytes.toString('utf8');\n } else {\n const value = literal.slice(1, literal.endsWith(\"'\") ? -1 : undefined).replace(/''/g, \"'\");\n output += `(CAST(X'${Buffer.from(value, 'latin1').toString('hex')}' AS TEXT))`;\n literalsRewritten++;\n }\n for (let scan = index; scan < end; scan++) {\n if (statement[scan] === '\\n') line++;\n }\n index = end;\n plainStart = end;\n continue;\n }\n if (character === '\"' || character === '`' || character === '[') {\n const close = character === '[' ? ']' : character;\n let end = statement.indexOf(close, index + 1);\n end = end === -1 ? length : end + 1;\n index = end;\n continue;\n }\n if (character === '-' && statement[index + 1] === '-') {\n appendPlain(statement.slice(plainStart, index));\n const end = statement.indexOf('\\n', index);\n const commentEnd = end === -1 ? length : end;\n const comment = statement.slice(index, commentEnd);\n output += isUtf8(Buffer.from(comment, 'latin1'))\n ? Buffer.from(comment, 'latin1').toString('utf8')\n : '--';\n index = commentEnd;\n plainStart = commentEnd;\n continue;\n }\n if (character === '/' && statement[index + 1] === '*') {\n appendPlain(statement.slice(plainStart, index));\n const end = statement.indexOf('*/', index + 2);\n const commentEnd = end === -1 ? length : end + 2;\n const comment = statement.slice(index, commentEnd);\n const commentBytes = Buffer.from(comment, 'latin1');\n output += isUtf8(commentBytes) ? commentBytes.toString('utf8') : ' ';\n for (let scan = index; scan < commentEnd; scan++) {\n if (statement[scan] === '\\n') line++;\n }\n index = commentEnd;\n plainStart = commentEnd;\n continue;\n }\n index++;\n }\n appendPlain(statement.slice(plainStart));\n return { sql: output, literalsRewritten };\n}\n","import { throwIfAborted } from '../utils/errors.js';\nimport {\n classifyWord,\n CompleteToken,\n completeTransition,\n isIdentifierCharCode,\n} from './complete.js';\nimport {\n MalformedSqlDumpError,\n StatementTooLargeError,\n UnsupportedClientCommandError,\n} from './errors.js';\nimport type { StatementSourceLocation } from './location.js';\nimport type { SqlDumpSource } from './source.js';\nimport { describeStatement } from './statementInfo.js';\nimport type { StatementInfo } from './statementInfo.js';\nimport { decodeStatementBytes } from './textEncoding.js';\n\nconst DEFAULT_MAX_STATEMENT_BYTES = 256 * 1024 * 1024;\n\n/**\n * Longest line examined as a possible `GO` / `/` terminator line. A real one\n * is a few bytes; the cap keeps the cross-chunk lookahead bounded on hostile\n * input (a line that long is simply treated as ordinary SQL).\n */\nconst MAX_TERMINATOR_LINE_BYTES = 64 * 1024;\n\n/** Longest dot-command line kept; the rest of an absurdly long one is ignored. */\nconst MAX_DOT_COMMAND_BYTES = 64 * 1024;\n\n/**\n * Shell dot-commands that only affect the `sqlite3` shell's own presentation\n * or diagnostics — never what the script does to the database — and are\n * therefore safe to skip. Anything else is refused.\n */\nconst PRESENTATIONAL_DOT_COMMANDS: ReadonlySet<string> = new Set([\n 'bail',\n 'binary',\n 'changes',\n 'databases',\n 'dbinfo',\n 'echo',\n 'eqp',\n 'explain',\n 'fullschema',\n 'headers',\n 'header',\n 'help',\n 'indexes',\n 'indices',\n 'log',\n 'mode',\n 'nullvalue',\n 'once',\n 'output',\n 'print',\n 'progress',\n 'prompt',\n 'scanstats',\n 'schema',\n 'separator',\n 'show',\n 'stats',\n 'tables',\n 'timeout',\n 'timer',\n 'trace',\n 'width',\n]);\n\n/** Dot-commands that end the shell's input. */\nconst EXIT_DOT_COMMANDS: ReadonlySet<string> = new Set(['exit', 'quit']);\n\n/**\n * What to do with a `sqlite3` shell dot-command (`.mode csv`, `.read x.sql`).\n *\n * - `'skip-presentational'` (default) skips commands that only affect the\n * shell's output (`.mode`, `.headers`, `.print`, ...), reporting each, and\n * refuses every command that would change what the script does to the\n * database (`.read`, `.import`, `.open`, `.load`, ...).\n * - `'error'` refuses every dot-command.\n *\n * `.quit` and `.exit` end the input in both modes, exactly as in the shell.\n */\nexport type DotCommandPolicy = 'skip-presentational' | 'error';\n\nexport interface SqlStatementParserOptions {\n /**\n * Upper bound, in bytes, on one statement's accumulated text.\n *\n * Guards against unbounded memory growth from a truncated dump or a\n * `CREATE TRIGGER` whose `END` is missing. Defaults to 256 MiB — far\n * larger than any statement a real dump contains, while still bounded.\n */\n readonly maxStatementBytes?: number;\n readonly dotCommands?: DotCommandPolicy;\n}\n\nexport interface ParsedStatement {\n readonly statementIndex: number;\n /**\n * Statement text, without its terminating `;` and without the whitespace\n * and comments that preceded it. Never empty.\n */\n readonly sql: string;\n readonly location: StatementSourceLocation;\n /** What the statement is, from its leading tokens. */\n readonly info: StatementInfo;\n /**\n * The object the restore is currently working on: this statement's own\n * object when it names one (`CREATE TABLE t`, `INSERT INTO t`), else the\n * last one seen. Reported through restore progress.\n */\n readonly currentObject?: string;\n /** Bytes of source the parser had consumed when this statement was emitted. */\n readonly bytesConsumed: number;\n /**\n * How many string literals holding bytes that are not valid UTF-8 were\n * rewritten to `CAST(X'...' AS TEXT)` so the statement could be sent as\n * text. See `textEncoding.ts`.\n */\n readonly textLiteralsRewritten: number;\n}\n\n/** A dot-command the parser skipped under `'skip-presentational'`. */\nexport interface SkippedDotCommand {\n readonly command: string;\n readonly line: number;\n}\n\ntype LexState =\n | 'normal'\n | 'singleQuote'\n | 'doubleQuote'\n | 'backtick'\n | 'bracket'\n | 'blockComment'\n | 'lineComment'\n | 'dotCommand'\n | 'hashComment'\n | 'stopped';\n\nconst OPEN_CONSTRUCT_NAME: Partial<Record<LexState, string>> = {\n singleQuote: \"string literal ('...')\",\n doubleQuote: 'double-quoted identifier (\"...\")',\n backtick: 'backtick-quoted identifier (`...`)',\n bracket: 'bracket-quoted identifier ([...])',\n};\n\nconst CLOSING_CHARACTER: Partial<Record<LexState, string>> = {\n singleQuote: \"'\",\n doubleQuote: '\"',\n backtick: '`',\n bracket: ']',\n};\n\n/** Whitespace as `sqlite3_complete()` classifies it. */\nfunction isCompleteWhitespace(character: string): boolean {\n return (\n character === ' ' ||\n character === '\\n' ||\n character === '\\t' ||\n character === '\\r' ||\n character === '\\f'\n );\n}\n\n/** C `isspace()` in the C locale, which the shell's line scanner uses. */\nfunction isCSpace(character: string): boolean {\n return isCompleteWhitespace(character) || character === '\\v';\n}\n\n/**\n * `quickscan(line) == QSS_Start` from `shell.c`: the rest of a line holds\n * only whitespace and complete comments — no SQL, no `;`, no unterminated\n * comment or quote.\n */\nfunction isPlainWhiteLine(text: string): boolean {\n let index = 0;\n while (index < text.length) {\n const character = text[index] as string;\n if (isCSpace(character)) {\n index++;\n continue;\n }\n if (character === '-' && text[index + 1] === '-') {\n return true;\n }\n if (character === '/' && text[index + 1] === '*') {\n const end = text.indexOf('*/', index + 2);\n if (end === -1) {\n return false;\n }\n index = end + 2;\n continue;\n }\n return false;\n }\n return true;\n}\n\n/**\n * `line_is_command_terminator()` from `shell.c`: a line holding only `/`\n * (Oracle's convention) or `GO` (SQL Server's), optionally surrounded by\n * whitespace and comments, ends the pending statement.\n */\nfunction isTerminatorLine(line: string): boolean {\n let index = 0;\n while (index < line.length && isCSpace(line[index] as string)) {\n index++;\n }\n if (line[index] === '/') {\n return isPlainWhiteLine(line.slice(index + 1));\n }\n if ((line[index] ?? '').toLowerCase() === 'g' && (line[index + 1] ?? '').toLowerCase() === 'o') {\n return isPlainWhiteLine(line.slice(index + 2));\n }\n return false;\n}\n\n/** Whether the start of a (possibly incomplete) line could still turn out to be a terminator line. */\nfunction couldBeTerminatorLine(partial: string): boolean {\n let index = 0;\n while (index < partial.length && isCSpace(partial[index] as string)) {\n index++;\n }\n if (index >= partial.length) {\n return true;\n }\n const first = (partial[index] as string).toLowerCase();\n if (first === '/') {\n return true;\n }\n return (\n first === 'g' &&\n (index + 1 >= partial.length || (partial[index + 1] as string).toLowerCase() === 'o')\n );\n}\n\n/**\n * An incremental splitter for `sqlite3` scripts that decides statement\n * boundaries exactly where the `sqlite3` shell does.\n *\n * Two layers, both ported from SQLite's own sources:\n *\n * - **Tokens and completeness** follow `sqlite3_complete()`\n * (see `complete.ts`): `'...'` strings, `\"...\"`, `` `...` `` and `[...]`\n * identifiers, `--` and (non-nesting) `/* *\\/` comments, and the state\n * machine that keeps the `;`-terminated statements inside a\n * `CREATE TRIGGER ... BEGIN ... END;` body in one statement.\n * - **Lines** follow the shell's `process_input()`: a line starting with `.`\n * at column 0, when no SQL is pending, is a dot-command; a line starting\n * with `#` there is a comment; a line holding only `GO` or `/` ends the\n * pending statement; and a carriage return immediately before a newline is\n * dropped, exactly as the shell's line reader drops it.\n *\n * The parser runs on **bytes** — chunks are byte strings, one code unit per\n * byte, as `latin1` decodes them — because a dump is not necessarily valid\n * UTF-8, and decoding up front would replace invalid bytes with U+FFFD\n * before the parser ever saw them. Every character it reacts to is ASCII,\n * and no byte of a multi-byte UTF-8 sequence can be mistaken for one.\n *\n * Correctness across chunk boundaries is not assumed: anything whose\n * meaning depends on what follows — a `-` or `/` that may open a comment, a\n * `*` that may close one, a `\\r` that may precede `\\n`, the start of a line\n * that may be a `GO` line — is carried to the next chunk.\n *\n * Memory is bounded by one statement: only the current statement's text and\n * a few carried bytes are held, and `maxStatementBytes` fails fast on a\n * pathological input rather than growing without limit.\n */\nexport class SqlStatementParser {\n private readonly maxStatementBytes: number;\n private readonly dotCommandPolicy: DotCommandPolicy;\n\n private lex: LexState = 'normal';\n private completeState = 0;\n /** Length and (lower-cased, capped) prefix of the identifier being scanned. */\n private wordLength = 0;\n private wordPrefix = '';\n /** In a block comment: whether the previous byte was `*`. */\n private blockStar = false;\n private openLine = 1;\n\n private carry = '';\n private parts: string[] = [];\n private partsBytes = 0;\n /** True once the pending statement has content other than whitespace and comments. */\n private hasContent = false;\n private statementStartLine = 1;\n\n private line = 1;\n private atLineStart = true;\n private firstChunk = true;\n private dotText = '';\n private dotLine = 1;\n\n private nextStatementIndex = 0;\n private finished = false;\n private bytesConsumedTotal = 0;\n private lastObject: string | undefined;\n private readonly skipped: SkippedDotCommand[] = [];\n\n constructor(options?: SqlStatementParserOptions) {\n this.maxStatementBytes = options?.maxStatementBytes ?? DEFAULT_MAX_STATEMENT_BYTES;\n this.dotCommandPolicy = options?.dotCommands ?? 'skip-presentational';\n }\n\n /** Bytes of source consumed so far. */\n get bytesConsumed(): number {\n return this.bytesConsumedTotal;\n }\n\n /** Dot-commands skipped so far under the `'skip-presentational'` policy. */\n get skippedDotCommands(): readonly SkippedDotCommand[] {\n return this.skipped;\n }\n\n /** `true` once a `.quit`/`.exit` command ended the input. */\n get stopped(): boolean {\n return this.lex === 'stopped';\n }\n\n /**\n * Feeds one chunk of the source, as a **byte string** — one code unit per\n * byte, as produced by `buffer.toString('latin1')`. Callers holding text\n * should use {@link parseSqlStatements} or {@link streamSqlStatements},\n * which convert for them.\n */\n push(chunk: string): ParsedStatement[] {\n if (this.finished) {\n throw new Error('SqlStatementParser.push() called after finish()');\n }\n this.bytesConsumedTotal += chunk.length;\n if (chunk.length === 0) {\n return [];\n }\n return this.scan(this.carry + chunk, false);\n }\n\n finish(): ParsedStatement[] {\n if (this.finished) {\n throw new Error('SqlStatementParser.finish() called more than once');\n }\n this.finished = true;\n const out = this.scan(this.carry, true);\n this.carry = '';\n\n const open = OPEN_CONSTRUCT_NAME[this.lex];\n if (open !== undefined) {\n throw new MalformedSqlDumpError(open, this.openLine);\n }\n if (this.lex === 'dotCommand') {\n this.handleDotCommand();\n }\n if (this.lex !== 'stopped') {\n this.endWord();\n // The shell runs whatever is left at end of input (\"this may be\n // incomplete; let the SQL parser deal with that\"), so a final statement\n // without a `;` is still executed.\n const statement = this.emit();\n if (statement) {\n out.push(statement);\n }\n }\n return out;\n }\n\n private scan(text: string, final: boolean): ParsedStatement[] {\n const out: ParsedStatement[] = [];\n const length = text.length;\n let index = 0;\n /** Start of the run of `text` currently being kept as statement text, or `-1`. */\n let keepFrom = this.hasContent && this.lex !== 'stopped' ? 0 : -1;\n\n const flush = (end: number): void => {\n if (keepFrom >= 0 && end > keepFrom) {\n const part = text.slice(keepFrom, end);\n this.parts.push(part);\n this.partsBytes += part.length;\n if (this.partsBytes > this.maxStatementBytes) {\n throw new StatementTooLargeError(this.maxStatementBytes, this.statementStartLine);\n }\n }\n keepFrom = -1;\n };\n const markContent = (at: number): void => {\n if (!this.hasContent) {\n this.hasContent = true;\n this.statementStartLine = this.line;\n keepFrom = at;\n } else if (keepFrom < 0) {\n keepFrom = at;\n }\n };\n const resume = (at: number): void => {\n if (this.hasContent && keepFrom < 0) {\n keepFrom = at;\n }\n };\n const carryFrom = (at: number): void => {\n flush(at);\n this.carry = text.slice(at);\n };\n\n if (this.firstChunk && length > 0) {\n // A UTF-8 byte-order mark at the very start of the input. SQLite's\n // tokenizer treats one as whitespace anywhere, so the shell never sees\n // it as SQL; it is skipped here so it cannot start a \"statement\".\n if (text.startsWith('\\u00ef\\u00bb\\u00bf')) {\n index = 3;\n this.firstChunk = false;\n } else if (!final && '\\u00ef\\u00bb\\u00bf'.startsWith(text)) {\n this.carry = text;\n return out;\n } else {\n this.firstChunk = false;\n }\n }\n\n while (index < length) {\n const character = text[index] as string;\n\n // The shell's line reader drops a `\\r` that immediately precedes `\\n`,\n // wherever it is — including inside a string literal.\n if (character === '\\r' && this.lex !== 'stopped') {\n if (index + 1 >= length && !final) {\n carryFrom(index);\n return out;\n }\n if (text[index + 1] === '\\n') {\n flush(index);\n index++;\n resume(index);\n continue;\n }\n }\n\n switch (this.lex) {\n case 'stopped':\n index = length;\n continue;\n\n case 'hashComment':\n case 'dotCommand': {\n const newline = text.indexOf('\\n', index);\n const end = newline === -1 ? length : newline;\n if (this.lex === 'dotCommand' && this.dotText.length < MAX_DOT_COMMAND_BYTES) {\n this.dotText += text.slice(index, end);\n }\n if (newline === -1) {\n index = length;\n continue;\n }\n if (this.lex === 'dotCommand') {\n this.handleDotCommand();\n if (this.stopped) {\n index = length;\n continue;\n }\n }\n this.lex = 'normal';\n index = newline;\n continue;\n }\n\n case 'singleQuote':\n case 'doubleQuote':\n case 'backtick':\n case 'bracket': {\n const close = CLOSING_CHARACTER[this.lex] as string;\n if (character === close) {\n // Doubled quotes need no lookahead: `'it''s'` is two adjacent\n // strings to `sqlite3_complete()` as well, which changes nothing.\n this.lex = 'normal';\n this.atLineStart = false;\n index++;\n continue;\n }\n if (character === '\\r') {\n // A lone `\\r`; one followed by `\\n` was already dropped above.\n index++;\n continue;\n }\n // Jump to the next byte that matters: the closing quote, or a `\\r`\n // that may need dropping. Newlines in between are only counted.\n let end = text.indexOf(close, index);\n if (end === -1) end = length;\n const crAt = text.indexOf('\\r', index);\n if (crAt !== -1 && crAt < end) end = crAt;\n this.countNewlines(text, index, end);\n index = end;\n continue;\n }\n\n case 'blockComment': {\n if (this.blockStar && character === '/') {\n this.blockStar = false;\n this.lex = 'normal';\n this.completeState = completeTransition(this.completeState, CompleteToken.Whitespace);\n this.atLineStart = false;\n index++;\n continue;\n }\n const starAt = text.indexOf('*', index);\n const crAt = text.indexOf('\\r', index);\n let end = starAt === -1 ? length : starAt;\n if (crAt !== -1 && crAt < end) {\n end = crAt;\n }\n if (end > index) {\n this.countNewlines(text, index, end);\n this.blockStar = false;\n index = end;\n continue;\n }\n if (character === '*') {\n this.blockStar = true;\n this.atLineStart = false;\n if (index + 1 >= length && !final) {\n // Keep the `*` pending, so a `/` at the start of the next chunk\n // closes the comment.\n index++;\n continue;\n }\n index++;\n continue;\n }\n // A lone `\\r` not followed by `\\n`: ordinary comment text.\n this.blockStar = false;\n index++;\n continue;\n }\n\n case 'lineComment': {\n if (character === '\\n') {\n // The newline itself is whitespace in the normal state.\n this.lex = 'normal';\n continue;\n }\n if (character === '\\r') {\n index++;\n continue;\n }\n let end = text.indexOf('\\n', index);\n if (end === -1) end = length;\n const crAt = text.indexOf('\\r', index);\n if (crAt !== -1 && crAt < end) end = crAt;\n index = end;\n continue;\n }\n\n case 'normal':\n break;\n }\n\n // --- normal state -------------------------------------------------\n\n const code = text.charCodeAt(index);\n\n if (this.wordLength > 0) {\n if (isIdentifierCharCode(code)) {\n const start = index;\n while (index < length && isIdentifierCharCode(text.charCodeAt(index))) {\n index++;\n }\n this.extendWord(text.slice(start, index));\n continue;\n }\n this.endWord();\n }\n\n if (this.atLineStart) {\n this.atLineStart = false;\n if (!this.hasContent && (character === '.' || character === '#')) {\n this.lex = character === '.' ? 'dotCommand' : 'hashComment';\n this.dotText = '';\n this.dotLine = this.line;\n index++;\n continue;\n }\n if (\n this.completeState !== 5 &&\n this.completeState !== 6 &&\n this.mayStartTerminatorLine(text, index, final)\n ) {\n const newline = text.indexOf('\\n', index);\n const lineEnd = newline === -1 ? length : newline;\n const lineText = text.slice(index, lineEnd);\n if (newline === -1 && !final) {\n if (lineText.length < MAX_TERMINATOR_LINE_BYTES && couldBeTerminatorLine(lineText)) {\n this.atLineStart = true;\n carryFrom(index);\n return out;\n }\n } else if (isTerminatorLine(lineText)) {\n // The shell replaces the whole line with `;`.\n flush(index);\n const statement = this.completeWithSemicolon();\n if (statement) {\n out.push(statement);\n }\n index = lineEnd;\n continue;\n }\n }\n }\n\n if (character === ';') {\n const next = completeTransition(this.completeState, CompleteToken.Semi);\n if (next === 1) {\n flush(index);\n this.completeState = next;\n const statement = this.emit();\n if (statement) {\n out.push(statement);\n }\n index++;\n continue;\n }\n // A `;` inside a trigger body is part of the statement.\n this.completeState = next;\n markContent(index);\n index++;\n continue;\n }\n\n if (isCompleteWhitespace(character)) {\n this.completeState = completeTransition(this.completeState, CompleteToken.Whitespace);\n if (character === '\\n') {\n this.line++;\n this.atLineStart = true;\n }\n index++;\n continue;\n }\n\n if (character === '-' || character === '/') {\n if (index + 1 >= length && !final) {\n carryFrom(index);\n return out;\n }\n const next = text[index + 1];\n if ((character === '-' && next === '-') || (character === '/' && next === '*')) {\n this.lex = character === '-' ? 'lineComment' : 'blockComment';\n this.blockStar = false;\n if (character === '-') {\n // `--` behaves as whitespace for `sqlite3_complete()`.\n this.completeState = completeTransition(this.completeState, CompleteToken.Whitespace);\n }\n index += 2;\n continue;\n }\n this.completeState = completeTransition(this.completeState, CompleteToken.Other);\n markContent(index);\n index++;\n continue;\n }\n\n if (character === \"'\" || character === '\"' || character === '`' || character === '[') {\n this.lex =\n character === \"'\"\n ? 'singleQuote'\n : character === '\"'\n ? 'doubleQuote'\n : character === '`'\n ? 'backtick'\n : 'bracket';\n this.openLine = this.line;\n this.completeState = completeTransition(this.completeState, CompleteToken.Other);\n markContent(index);\n index++;\n continue;\n }\n\n if (code === 0xef) {\n // A UTF-8 byte-order mark at the start of a token is whitespace to\n // SQLite's tokenizer (its `CC_BOM` class).\n if (index + 2 >= length && !final) {\n carryFrom(index);\n return out;\n }\n if (text.charCodeAt(index + 1) === 0xbb && text.charCodeAt(index + 2) === 0xbf) {\n flush(index);\n index += 3;\n resume(index);\n continue;\n }\n }\n\n if (isIdentifierCharCode(code)) {\n markContent(index);\n const start = index;\n while (index < length && isIdentifierCharCode(text.charCodeAt(index))) {\n index++;\n }\n this.extendWord(text.slice(start, index));\n continue;\n }\n\n this.completeState = completeTransition(this.completeState, CompleteToken.Other);\n markContent(index);\n index++;\n }\n\n flush(length);\n this.carry = '';\n return out;\n }\n\n /**\n * Cheap pre-check before the terminator-line lookahead: only a line whose\n * first non-blank character is `/` or `g` can be one. Keeps the lookahead —\n * which has to look at the whole line — off the ordinary `INSERT` lines\n * that make up almost all of a dump.\n */\n private mayStartTerminatorLine(text: string, index: number, final: boolean): boolean {\n let probe = index;\n while (probe < text.length && text[probe] !== '\\n' && isCSpace(text[probe] as string)) {\n probe++;\n }\n if (probe >= text.length) {\n return !final;\n }\n const first = text[probe];\n return first === '/' || first === 'g' || first === 'G';\n }\n\n private countNewlines(text: string, start: number, end: number): void {\n let position = text.indexOf('\\n', start);\n while (position !== -1 && position < end) {\n this.line++;\n position = text.indexOf('\\n', position + 1);\n }\n if (end > start) {\n this.atLineStart = text[end - 1] === '\\n';\n }\n }\n\n private extendWord(segment: string): void {\n if (this.wordPrefix.length < 10) {\n this.wordPrefix += segment.slice(0, 10 - this.wordPrefix.length);\n }\n this.wordLength += segment.length;\n }\n\n private endWord(): void {\n if (this.wordLength === 0) {\n return;\n }\n const token = this.wordLength > 9 ? CompleteToken.Other : classifyWord(this.wordPrefix);\n this.completeState = completeTransition(this.completeState, token);\n this.wordLength = 0;\n this.wordPrefix = '';\n }\n\n /** A terminator line: behave as if the line were `;`. */\n private completeWithSemicolon(): ParsedStatement | null {\n this.completeState = completeTransition(this.completeState, CompleteToken.Semi);\n return this.emit();\n }\n\n private emit(): ParsedStatement | null {\n const hadContent = this.hasContent;\n const byteText = this.parts.join('');\n this.parts = [];\n this.partsBytes = 0;\n this.hasContent = false;\n if (!hadContent) {\n return null;\n }\n // Only ASCII whitespace: `\\s` would also match byte 0xA0, which can be the\n // last byte of a multi-byte UTF-8 character.\n const trimmed = byteText.replace(/[ \\t\\n\\r\\f\\v]+$/, '');\n if (trimmed === '') {\n return null;\n }\n const { sql, literalsRewritten } = decodeStatementBytes(trimmed, this.statementStartLine);\n const info = describeStatement(sql);\n if (info.objectName !== undefined) {\n this.lastObject = info.objectName;\n }\n return {\n statementIndex: this.nextStatementIndex++,\n sql,\n location: { startLine: this.statementStartLine, endLine: this.line },\n info,\n ...(this.lastObject === undefined ? {} : { currentObject: this.lastObject }),\n bytesConsumed: this.bytesConsumedTotal,\n textLiteralsRewritten: literalsRewritten,\n };\n }\n\n private handleDotCommand(): void {\n const text = this.dotText;\n this.dotText = '';\n this.lex = 'normal';\n const command = (/^\\S*/.exec(text)?.[0] ?? '').toLowerCase();\n if (EXIT_DOT_COMMANDS.has(command)) {\n this.lex = 'stopped';\n return;\n }\n if (\n this.dotCommandPolicy === 'skip-presentational' &&\n PRESENTATIONAL_DOT_COMMANDS.has(command)\n ) {\n this.skipped.push({ command, line: this.dotLine });\n return;\n }\n throw new UnsupportedClientCommandError(command, this.dotLine);\n }\n}\n\n/** Parses a complete, already-in-memory script. A convenience wrapper over {@link SqlStatementParser}. */\nexport function parseSqlStatements(\n sql: string | Buffer,\n options?: SqlStatementParserOptions,\n): ParsedStatement[] {\n const parser = new SqlStatementParser(options);\n const byteString = (typeof sql === 'string' ? Buffer.from(sql, 'utf8') : sql).toString('latin1');\n return [...parser.push(byteString), ...parser.finish()];\n}\n\n/**\n * Normalizes any {@link SqlDumpSource} into *byte strings*: one JavaScript\n * code unit per input byte, via `latin1`. See {@link SqlStatementParser} for\n * why the parser runs on bytes; a `latin1` decode can also never split a\n * character across chunks, so no `StringDecoder` is needed.\n */\nexport async function* toByteStringChunks(source: SqlDumpSource): AsyncGenerator<string> {\n if (typeof source === 'string') {\n yield Buffer.from(source, 'utf8').toString('latin1');\n return;\n }\n if (source instanceof Uint8Array) {\n // Covers `Buffer` too, which extends `Uint8Array`.\n yield (Buffer.isBuffer(source) ? source : Buffer.from(source)).toString('latin1');\n return;\n }\n for await (const chunk of source as AsyncIterable<string | Buffer | Uint8Array>) {\n if (typeof chunk === 'string') {\n yield Buffer.from(chunk, 'utf8').toString('latin1');\n } else {\n yield (Buffer.isBuffer(chunk) ? chunk : Buffer.from(chunk)).toString('latin1');\n }\n }\n}\n\n/**\n * Streams `source` into {@link ParsedStatement}s without ever buffering the\n * whole input: at most the current statement's text, plus a few carried\n * bytes, is held at a time.\n */\nexport async function* streamSqlStatements(\n source: SqlDumpSource,\n options?: SqlStatementParserOptions,\n signal?: AbortSignal,\n): AsyncGenerator<ParsedStatement> {\n const parser = new SqlStatementParser(options);\n yield* streamWithParser(parser, source, signal);\n}\n\n/** Drives an existing parser over `source`, so a caller can inspect it afterwards. */\nexport async function* streamWithParser(\n parser: SqlStatementParser,\n source: SqlDumpSource,\n signal?: AbortSignal,\n): AsyncGenerator<ParsedStatement> {\n for await (const chunk of toByteStringChunks(source)) {\n throwIfAborted(signal);\n for (const statement of parser.push(chunk)) {\n yield statement;\n }\n if (parser.stopped) {\n break;\n }\n }\n throwIfAborted(signal);\n for (const statement of parser.finish()) {\n yield statement;\n }\n}\n","import { executeStatement, toNumber } from '../connection/acquire.js';\nimport type { SqliteConnection } from '../connection/types.js';\nimport { isAbortError } from '../utils/errors.js';\nimport type { StatementInfo } from './statementInfo.js';\n\nconst TRUTHY_PRAGMA_VALUES: ReadonlySet<string> = new Set(['1', 'on', 'true', 'yes']);\n\n/** Parses a boolean pragma value the way SQLite does (`sqlite3GetBoolean`). */\nexport function isTruthyPragmaValue(value: string | undefined): boolean {\n return value !== undefined && TRUTHY_PRAGMA_VALUES.has(value.trim().toLowerCase());\n}\n\n/**\n * Follows the connection state a restore script changes, so it can be put\n * back when the script stops before undoing it itself — or, for the\n * settings a native dump never undoes, when it finishes.\n *\n * Only statements the parser has classified (see `describeStatement`) are\n * followed: top-level transaction control and the two session pragmas a\n * dump uses. Text inside row values or trigger bodies is never mistaken for\n * one, because a statement is classified from its leading tokens only.\n */\nexport class RestoreSessionState {\n private initialForeignKeys: boolean | undefined;\n private foreignKeysChanged = false;\n private writableSchemaOn = false;\n private schemaRowsWritten = false;\n /** Tracked when the adapter cannot report `isInTransaction()`. */\n private trackedTransaction = false;\n private callerTransaction = false;\n\n /** Records the state to restore to. Call once, before the first statement. */\n async begin(connection: SqliteConnection, signal?: AbortSignal): Promise<void> {\n this.callerTransaction = connection.isInTransaction?.() ?? false;\n try {\n const result = await connection.query({ sql: 'PRAGMA foreign_keys' }, signal);\n const first = result.rows[0];\n if (first !== undefined) {\n this.initialForeignKeys = toNumber(Object.values(first)[0]) !== 0;\n }\n } catch (error) {\n if (isAbortError(error)) throw error;\n }\n }\n\n /** Whether the handle was already inside a transaction the caller opened. */\n get joinedCallerTransaction(): boolean {\n return this.callerTransaction;\n }\n\n /** Whether any statement wrote virtual-table rows into the schema table. */\n get wroteSchemaRows(): boolean {\n return this.schemaRowsWritten;\n }\n\n /** Call after every statement that executed successfully. */\n observe(info: StatementInfo): void {\n if (info.transactionControl === 'begin') {\n this.trackedTransaction = true;\n } else if (info.transactionControl === 'commit' || info.transactionControl === 'rollback') {\n this.trackedTransaction = false;\n } else if (info.transactionControl === 'savepoint' && !this.trackedTransaction) {\n this.trackedTransaction = true;\n }\n if (info.verb === 'PRAGMA' && info.pragmaValue !== undefined) {\n if (info.pragmaName === 'foreign_keys') {\n this.foreignKeysChanged = true;\n } else if (info.pragmaName === 'writable_schema') {\n this.writableSchemaOn = isTruthyPragmaValue(info.pragmaValue);\n }\n }\n if (info.verb === 'INSERT' && isSchemaTableName(info.objectName)) {\n this.schemaRowsWritten = true;\n }\n }\n\n /** Whether a transaction the script (not the caller) opened is still open. */\n scriptTransactionOpen(connection: SqliteConnection): boolean {\n if (this.callerTransaction) {\n return false;\n }\n return connection.isInTransaction?.() ?? this.trackedTransaction;\n }\n\n /**\n * Puts back what the script changed. Runs without the caller's signal on\n * purpose: on the cancellation path that signal is already aborted, and\n * the cleanup must still happen. Returns a description of each change it\n * undid, for the `session-state-restored` warning.\n */\n async restore(\n connection: SqliteConnection,\n options: { readonly rollbackOpenTransaction: boolean },\n ): Promise<{ readonly rolledBack: boolean; readonly restored: readonly string[] }> {\n const restored: string[] = [];\n let rolledBack = false;\n\n if (options.rollbackOpenTransaction && this.scriptTransactionOpen(connection)) {\n await executeStatement(connection, 'ROLLBACK').catch(() => {});\n this.trackedTransaction = false;\n rolledBack = true;\n }\n if (this.writableSchemaOn) {\n await executeStatement(connection, 'PRAGMA writable_schema=OFF').catch(() => {});\n this.writableSchemaOn = false;\n restored.push('writable_schema');\n }\n // `foreign_keys` cannot change inside a transaction, so this has to come\n // after the rollback above. The caller's own open transaction, if any,\n // makes it a no-op — and the value never changed inside it either.\n if (this.foreignKeysChanged && this.initialForeignKeys !== undefined) {\n await executeStatement(\n connection,\n `PRAGMA foreign_keys=${this.initialForeignKeys ? 'ON' : 'OFF'}`,\n ).catch(() => {});\n this.foreignKeysChanged = false;\n }\n return { rolledBack, restored };\n }\n}\n\n/** `sqlite_schema`, `sqlite_master`, and their temp-schema forms. */\nexport function isSchemaTableName(name: string | undefined): boolean {\n if (name === undefined) {\n return false;\n }\n const lower = name.toLowerCase();\n return (\n lower === 'sqlite_schema' ||\n lower === 'sqlite_master' ||\n lower === 'sqlite_temp_schema' ||\n lower === 'sqlite_temp_master'\n );\n}\n","import { acquireSqliteConnection, executeStatement, toText } from '../connection/acquire.js';\nimport type { SqliteConnection, SqliteErrorInfo, SqliteRow } from '../connection/types.js';\nimport { redactSecrets } from '../security/redact.js';\nimport { isAbortError, throwIfAborted } from '../utils/errors.js';\nimport { RestoreExecutionError } from './errors.js';\nimport { safeSqlPreview } from './preview.js';\nimport { isSchemaTableName, isTruthyPragmaValue, RestoreSessionState } from './sessionState.js';\nimport { SqlStatementParser, streamWithParser } from './statementParser.js';\nimport type { ParsedStatement } from './statementParser.js';\nimport type {\n RestoreStatementError,\n RestoreWarning,\n SqlDumpRestoreRequest,\n SqlDumpRestoreResult,\n} from './types.js';\n\nconst WRAP_SAVEPOINT = 'dbgate_sqlite_restore';\n\n/** Most foreign-key violations listed individually before the rest are summarized. */\nconst MAX_REPORTED_FOREIGN_KEY_VIOLATIONS = 20;\n\n/**\n * Restores a plain-SQL dump using only the {@link SqliteConnection}\n * abstraction — no `sqlite3` shell, no external process.\n *\n * The input is split into statements by a streaming parser that reproduces\n * the `sqlite3` shell's own rules (see `statementParser.ts`), so a script is\n * executed as the same statements, in the same order, that\n * `sqlite3 database.db < dump.sql` would execute. Statements run\n * sequentially on one handle.\n *\n * A structural problem with the input — an unterminated string, an\n * unsupported dot-command, bytes that cannot be represented — throws,\n * because the statement boundaries past that point cannot be trusted. A\n * statement that parses but fails in SQLite is recorded in `result.errors`\n * instead, and unless `stopOnError` (the default) is set, the restore\n * continues.\n */\nexport async function restoreSqlDump(\n request: SqlDumpRestoreRequest,\n): Promise<SqlDumpRestoreResult> {\n const options = request.options ?? {};\n const stopOnError = options.stopOnError ?? true;\n const restoreSessionStateOnExit = options.restoreSessionState ?? true;\n const schemaWrites = options.schemaWrites ?? 'allow';\n const wrap = options.transaction === 'wrap';\n const signal = request.signal;\n\n request.progress?.({ phase: 'connecting' });\n const acquired = await acquireSqliteConnection(request.connection, signal);\n const connection = acquired.connection;\n\n let statementsExecuted = 0;\n let statementsFailed = 0;\n let rowsRestored = 0;\n let bytesConsumed = 0;\n const errors: RestoreStatementError[] = [];\n const warnings: RestoreWarning[] = [];\n const sessionState = new RestoreSessionState();\n const parser = new SqlStatementParser(options);\n\n let defensiveDisabled = false;\n let wrapOpen = false;\n let skippedTransactionControl = 0;\n let textLiteralsRewritten = 0;\n\n const result = (cancelled: boolean): SqlDumpRestoreResult => ({\n statementsExecuted,\n statementsFailed,\n rowsRestored,\n bytesConsumed,\n errors,\n warnings,\n cancelled,\n });\n\n const report = (\n phase: 'parsing' | 'executing' | 'finalizing',\n statement?: ParsedStatement,\n executionState?: 'started' | 'finished' | 'failed',\n error?: RestoreStatementError,\n ): void => {\n request.progress?.({\n phase,\n statementsProcessed: statementsExecuted + statementsFailed,\n rowsRestored,\n bytesConsumed,\n ...(statement === undefined\n ? {}\n : {\n statementIndex: statement.statementIndex,\n ...(statement.currentObject === undefined\n ? {}\n : { currentObject: statement.currentObject }),\n }),\n ...(executionState === undefined ? {} : { executionState }),\n ...(error === undefined\n ? {}\n : {\n error: {\n statementIndex: error.statementIndex,\n location: error.location,\n sqlPreview: error.sqlPreview,\n message: error.message,\n },\n }),\n });\n };\n\n /** Ends the restore's own transaction (`transaction: 'wrap'`), committing only on success. */\n const closeWrap = async (commit: boolean): Promise<void> => {\n if (!wrapOpen) {\n return;\n }\n wrapOpen = false;\n if (!commit) {\n await executeStatement(connection, `ROLLBACK TO ${WRAP_SAVEPOINT}`).catch(() => {});\n warnings.push({\n code: 'transaction-rolled-back',\n message:\n 'The restore did not complete, so its transaction (transaction: \"wrap\") was rolled back and the database is unchanged.',\n });\n }\n await executeStatement(connection, `RELEASE ${WRAP_SAVEPOINT}`).catch(() => {});\n };\n\n const finalize = async (completed: boolean): Promise<void> => {\n await closeWrap(completed);\n if (restoreSessionStateOnExit) {\n const { rolledBack, restored } = await sessionState.restore(connection, {\n rollbackOpenTransaction: true,\n });\n if (rolledBack) {\n warnings.push({\n code: 'transaction-rolled-back',\n message: completed\n ? \"The script opened a transaction and never committed it (a truncated dump ends this way), so it was rolled back — as the sqlite3 shell's exit would roll it back.\"\n : 'The restore stopped inside the transaction the script opened, so that transaction was rolled back: nothing it had written so far was kept.',\n });\n }\n if (restored.length > 0) {\n warnings.push({\n code: 'session-state-restored',\n message: `The script left ${restored.join(', ')} changed when the restore ended, so it was reset before the connection was released.`,\n });\n }\n }\n if (sessionState.wroteSchemaRows) {\n // Rows written straight into sqlite_schema only take effect once the\n // schema is re-read. A fresh connection re-reads it anyway; this makes\n // the restored virtual tables usable on the *same* handle too.\n await executeStatement(connection, 'PRAGMA writable_schema=RESET').catch(() => {});\n }\n if (defensiveDisabled && connection.setDefensive) {\n await connection.setDefensive(true).catch(() => {});\n defensiveDisabled = false;\n }\n await acquired.release();\n };\n\n try {\n await sessionState.begin(connection, signal);\n if (options.disableForeignKeys) {\n await executeStatement(connection, 'PRAGMA foreign_keys=OFF', signal);\n sessionState.observe({ verb: 'PRAGMA', pragmaName: 'foreign_keys', pragmaValue: 'OFF' });\n }\n if (sessionState.joinedCallerTransaction && !wrap) {\n warnings.push({\n code: 'caller-transaction-open',\n message:\n 'The connection was already inside a transaction when the restore started. A full dump\\'s own BEGIN TRANSACTION will fail in that state; commit first, or restore with transaction: \"wrap\", which nests.',\n });\n }\n\n for await (const statement of streamWithParser(parser, request.source, signal)) {\n throwIfAborted(signal);\n bytesConsumed = statement.bytesConsumed;\n textLiteralsRewritten += statement.textLiteralsRewritten;\n report('parsing', statement);\n const info = statement.info;\n\n if (wrap) {\n if (\n info.transactionControl === 'begin' ||\n info.transactionControl === 'commit' ||\n info.transactionControl === 'rollback'\n ) {\n skippedTransactionControl++;\n continue;\n }\n // `PRAGMA foreign_keys` is a no-op inside a transaction, so the\n // dump's leading pragmas run before the wrapping transaction opens.\n if (!wrapOpen && info.verb !== 'PRAGMA') {\n await executeStatement(connection, `SAVEPOINT ${WRAP_SAVEPOINT}`, signal);\n wrapOpen = true;\n }\n }\n\n const schemaWriteRefused =\n schemaWrites === 'refuse' &&\n ((info.verb === 'INSERT' && isSchemaTableName(info.objectName)) ||\n (info.pragmaName === 'writable_schema' && isTruthyPragmaValue(info.pragmaValue)));\n\n if (\n !schemaWriteRefused &&\n schemaWrites === 'allow' &&\n !defensiveDisabled &&\n connection.setDefensive &&\n info.pragmaName === 'writable_schema' &&\n isTruthyPragmaValue(info.pragmaValue)\n ) {\n await connection.setDefensive(false);\n defensiveDisabled = true;\n warnings.push({\n code: 'defensive-mode-disabled',\n message:\n 'The dump recreates virtual tables by writing sqlite_schema directly (as every native .dump of such a database does), so SQLITE_DBCONFIG_DEFENSIVE was disabled for the rest of the restore and re-enabled afterwards.',\n statementIndex: statement.statementIndex,\n });\n }\n\n report('executing', statement, 'started');\n try {\n if (schemaWriteRefused) {\n throw new Error(\n 'Statement writes the schema table directly, which schemaWrites: \"refuse\" does not allow',\n );\n }\n const executed = await executeStatement(connection, statement.sql, signal);\n rowsRestored += executed.changes;\n statementsExecuted++;\n sessionState.observe(info);\n report('executing', statement, 'finished');\n } catch (error) {\n if (isAbortError(error)) {\n throw error;\n }\n statementsFailed++;\n const statementError = toStatementError(connection, statement, error);\n errors.push(statementError);\n report('executing', statement, 'failed', statementError);\n if (stopOnError) {\n collectParserWarnings(parser, warnings, textLiteralsRewritten, skippedTransactionControl);\n await finalize(false);\n return result(false);\n }\n }\n }\n\n report('finalizing');\n if (options.verifyForeignKeys) {\n await closeWrap(true);\n warnings.push(...(await checkForeignKeys(connection, signal)));\n }\n collectParserWarnings(parser, warnings, textLiteralsRewritten, skippedTransactionControl);\n await finalize(true);\n return result(false);\n } catch (error) {\n collectParserWarnings(parser, warnings, textLiteralsRewritten, skippedTransactionControl);\n await finalize(false);\n if (isAbortError(error)) {\n return result(true);\n }\n throw error;\n }\n}\n\nfunction collectParserWarnings(\n parser: SqlStatementParser,\n warnings: RestoreWarning[],\n textLiteralsRewritten: number,\n skippedTransactionControl: number,\n): void {\n for (const skipped of parser.skippedDotCommands) {\n warnings.push({\n code: 'dot-command-skipped',\n message: `The sqlite3 shell command \".${skipped.command}\" on line ${skipped.line} only affects the shell's own output, so it was skipped.`,\n });\n }\n if (textLiteralsRewritten > 0) {\n warnings.push({\n code: 'text-literal-rewritten',\n message: `${textLiteralsRewritten} string literal(s) held bytes that are not valid UTF-8 and were executed as CAST(X'...' AS TEXT), which stores the identical bytes.`,\n });\n }\n if (skippedTransactionControl > 0) {\n warnings.push({\n code: 'script-transaction-control-skipped',\n message: `${skippedTransactionControl} BEGIN/COMMIT/ROLLBACK statement(s) in the script were skipped, because transaction: \"wrap\" runs the whole restore in its own transaction.`,\n });\n }\n}\n\n/** Runs `PRAGMA foreign_key_check` over the restored database. */\nasync function checkForeignKeys(\n connection: SqliteConnection,\n signal?: AbortSignal,\n): Promise<RestoreWarning[]> {\n const found: RestoreWarning[] = [];\n let total = 0;\n const byTable = new Map<string, number>();\n for await (const row of connection.stream<SqliteRow>(\n { sql: 'PRAGMA foreign_key_check' },\n signal === undefined ? {} : { signal },\n )) {\n total++;\n const table = toText(row.table) ?? '?';\n byTable.set(table, (byTable.get(table) ?? 0) + 1);\n if (found.length < MAX_REPORTED_FOREIGN_KEY_VIOLATIONS) {\n found.push({\n code: 'foreign-key-violation',\n message: `Row ${toText(row.rowid) ?? '(no rowid)'} of table \"${table}\" references a missing row in \"${toText(row.parent) ?? '?'}\" (foreign key #${toText(row.fkid) ?? '?'}).`,\n });\n }\n }\n if (total > found.length) {\n found.push({\n code: 'foreign-key-violation',\n message: `${total} foreign-key violations in total: ${[...byTable].map(([table, count]) => `${table} (${count})`).join(', ')}.`,\n });\n }\n return found;\n}\n\nfunction toStatementError(\n connection: SqliteConnection,\n statement: ParsedStatement,\n error: unknown,\n): RestoreStatementError {\n const described = connection.describeError?.(error);\n const message = redactSecrets(\n described?.message ?? (error instanceof Error ? error.message : String(error)),\n );\n const sqliteError: SqliteErrorInfo | undefined = described\n ? { ...described, message: redactSecrets(described.message) }\n : undefined;\n const executionError = new RestoreExecutionError(\n statement.statementIndex,\n statement.location,\n safeSqlPreview(statement.sql),\n message,\n sqliteError,\n { cause: error },\n );\n return {\n statementIndex: executionError.statementIndex,\n location: executionError.location,\n sqlPreview: executionError.sqlPreview,\n message: executionError.message,\n ...(executionError.sqliteError === undefined\n ? {}\n : { sqliteError: executionError.sqliteError }),\n };\n}\n","import type { Writable } from 'node:stream';\nimport { inspectDumpArchive } from '../archive/planner.js';\nimport type { ArchiveEntry } from '../archive/types.js';\nimport { acquireSqliteConnection } from '../connection/acquire.js';\nimport { beginSqliteDumpSession } from '../connection/session.js';\nimport type { SqliteConnectionInput } from '../connection/types.js';\nimport { exportTableDataAsInserts } from '../data/insertExport.js';\nimport { introspectSqlite } from '../introspection/introspect.js';\nimport type { SqliteDiagnostic } from '../model/diagnostics.js';\nimport { renderPlainSql } from '../renderer/plainSql.js';\nimport { foldSqliteName, normalizeDumpSelection } from '../selection/normalize.js';\nimport { SqliteDumperError } from '../utils/errors.js';\nimport type { DumpProgressCallback } from '../utils/progress.js';\nimport { StreamDumpWriter } from '../writer/streamWriter.js';\nimport type { DumpResult, DumpSqliteOptions } from './types.js';\n\n/**\n * Runs a complete SQLite dump: acquire one handle, open a read snapshot,\n * introspect, plan, render, and stream row data — writing plain SQL in the\n * native `.dump` layout to `output`.\n *\n * Everything happens on **one** handle inside **one** read transaction, so\n * every table is read from the same state of the database even while other\n * connections write to it. When a source is passed, one handle is acquired\n * for the whole dump and released afterwards; a bare connection is borrowed\n * and never closed.\n */\nexport async function dumpSqlite(\n connectionInput: SqliteConnectionInput,\n options: DumpSqliteOptions,\n output: Writable,\n onProgress?: DumpProgressCallback,\n signal?: AbortSignal,\n): Promise<DumpResult> {\n onProgress?.({ phase: 'connecting' });\n const acquired = await acquireSqliteConnection(connectionInput, signal);\n\n const session = await (async () => {\n onProgress?.({ phase: 'starting-snapshot' });\n try {\n return await beginSqliteDumpSession(\n acquired.connection,\n options.consistency === undefined ? {} : { consistency: options.consistency },\n signal,\n );\n } catch (error) {\n await acquired.release();\n throw error;\n }\n })();\n\n try {\n onProgress?.({ phase: 'introspecting' });\n const introspection = await introspectSqlite(\n acquired.connection,\n options.schemaName === undefined ? {} : { schemaName: options.schemaName },\n signal,\n );\n onProgress?.({\n phase: 'detecting-version',\n message: introspection.version.versionString,\n schemaName: introspection.database.schemaName,\n });\n\n const mode = options.mode ?? 'full';\n const selection = normalizeDumpSelection(options.selection);\n const archive = inspectDumpArchive(introspection.database, {\n mode,\n selection,\n ...(options.objectKinds === undefined ? {} : { objectKinds: options.objectKinds }),\n });\n onProgress?.({ phase: 'planning-archive', objectsTotal: archive.entries.length });\n\n if (!archive.valid) {\n throw new SqliteDumperError(\n 'invalid-archive',\n 'Archive planning failed; inspect the diagnostics, cycles and unsatisfiedDependencies returned by inspectDumpArchive for details',\n );\n }\n\n const writer = new StreamDumpWriter(output);\n const tablesByName = new Map(\n introspection.database.tables.map(table => [foldSqliteName(table.name), table]),\n );\n\n let rowsExported = 0;\n let statementsWritten = 0;\n const dataWarnings: SqliteDiagnostic[] = [];\n\n const onTableData = async (entry: ArchiveEntry): Promise<boolean> => {\n const table = tablesByName.get(foldSqliteName(entry.name));\n if (!table) {\n return false;\n }\n const primaryKeyIndex = table.withoutRowid\n ? introspection.database.indexes.find(\n index =>\n index.origin === 'pk' &&\n foldSqliteName(index.tableName) === foldSqliteName(table.name),\n )\n : undefined;\n const result = await exportTableDataAsInserts({\n connection: acquired.connection,\n schemaName: introspection.database.schemaName,\n table,\n writer,\n encoding: introspection.database.encoding,\n ...(entry.systemRowFilter === undefined ? {} : { systemRowFilter: entry.systemRowFilter }),\n ...(primaryKeyIndex === undefined ? {} : { primaryKeyIndex }),\n ...(options.dataExport === undefined ? {} : { options: options.dataExport }),\n ...(signal === undefined ? {} : { signal }),\n ...(onProgress === undefined ? {} : { onProgress }),\n });\n rowsExported += result.rowsExported;\n statementsWritten += result.statementsWritten;\n dataWarnings.push(...result.warnings);\n if (result.cancelled) {\n throw new DOMException('The operation was aborted.', 'AbortError');\n }\n return true;\n };\n\n const renderResult = await renderPlainSql({\n database: introspection.database,\n archive,\n writer,\n mode,\n sourceVersion: introspection.version,\n ...(options.render === undefined ? {} : { options: options.render }),\n ...(signal === undefined ? {} : { signal }),\n ...(onProgress === undefined ? {} : { onProgress }),\n onTableData,\n });\n\n onProgress?.({ phase: 'finalizing', bytesWritten: renderResult.bytesWritten });\n\n const sessionWarnings: SqliteDiagnostic[] = [];\n if (session.joinedExistingTransaction) {\n sessionWarnings.push({\n severity: 'info',\n code: 'dump-joined-caller-transaction',\n message:\n \"The connection was already inside a transaction, so the dump was read within it and includes that transaction's uncommitted changes.\",\n });\n }\n if (session.snapshotUnavailable) {\n sessionWarnings.push({\n severity: 'warning',\n code: 'snapshot-unavailable',\n message:\n 'The database does not support transactions, so the dump was not read from one snapshot: changes committed while it ran may be partly included.',\n });\n }\n\n return {\n bytesWritten: renderResult.bytesWritten,\n renderedDumpIds: renderResult.renderedDumpIds,\n skippedDumpIds: renderResult.skippedDumpIds,\n warnings: [\n ...introspection.diagnostics,\n ...archive.diagnostics,\n ...sessionWarnings,\n ...renderResult.warnings,\n ...dedupeDiagnostics(dataWarnings),\n ],\n cancelled: renderResult.cancelled,\n rowsExported,\n statementsWritten,\n };\n } finally {\n // The read transaction must end before the handle goes back to a\n // source, or the next borrower inherits it (and its lock).\n await session.finish();\n await acquired.release();\n }\n}\n\nfunction dedupeDiagnostics(diagnostics: readonly SqliteDiagnostic[]): SqliteDiagnostic[] {\n const seen = new Set<string>();\n return diagnostics.filter(diagnostic => {\n const key = `${diagnostic.code}\\u0000${diagnostic.message}`;\n if (seen.has(key)) {\n return false;\n }\n seen.add(key);\n return true;\n });\n}\n"],"mappings":"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","names":["throwIfAborted","structureId","throwIfAborted","throwIfAborted","column","throwIfAborted","throwIfAborted","require","module","import_node_buffer","DEFAULT_MAX_STATEMENT_BYTES","isCompleteWhitespace","throwIfAborted","throwIfAborted"]}
|