@happyvertical/sql 0.102.4 → 0.102.6

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.
Files changed (30) hide show
  1. package/README.md +26 -0
  2. package/dist/chunks/{duckdb-LMyfKZGi.js → duckdb-c4vdDzPL.js} +5 -4
  3. package/dist/chunks/{duckdb-LMyfKZGi.js.map → duckdb-c4vdDzPL.js.map} +1 -1
  4. package/dist/chunks/duckdb-resources-DBlvosDo.js +44 -0
  5. package/dist/chunks/duckdb-resources-DBlvosDo.js.map +1 -0
  6. package/dist/chunks/{postgres-dialect-Bfswr4Vs.js → postgres-dialect-CGv6DxSP.js} +3 -775
  7. package/dist/chunks/postgres-dialect-CGv6DxSP.js.map +1 -0
  8. package/dist/chunks/query-RzXJ4B9s.js +353 -0
  9. package/dist/chunks/query-RzXJ4B9s.js.map +1 -0
  10. package/dist/chunks/schema-manager-cxsySSDA.js +777 -0
  11. package/dist/chunks/schema-manager-cxsySSDA.js.map +1 -0
  12. package/dist/chunks/{sqlite-connection-cache-ChWav9iY.js → sqlite-connection-cache-CYThh9l5.js} +2 -2
  13. package/dist/chunks/{sqlite-connection-cache-ChWav9iY.js.map → sqlite-connection-cache-CYThh9l5.js.map} +1 -1
  14. package/dist/chunks/{sqlite-native--z4BnolL.js → sqlite-native-CsJ_BLqN.js} +5 -4
  15. package/dist/chunks/{sqlite-native--z4BnolL.js.map → sqlite-native-CsJ_BLqN.js.map} +1 -1
  16. package/dist/chunks/{sqlite-0PMv1va2.js → sqlite-rILMdW7Z.js} +6 -5
  17. package/dist/chunks/{sqlite-0PMv1va2.js.map → sqlite-rILMdW7Z.js.map} +1 -1
  18. package/dist/index.d.ts +3 -45
  19. package/dist/index.d.ts.map +1 -1
  20. package/dist/index.js +6 -238
  21. package/dist/index.js.map +1 -1
  22. package/dist/pglite.js +2 -1
  23. package/dist/pglite.js.map +1 -1
  24. package/dist/query.d.ts +61 -0
  25. package/dist/query.d.ts.map +1 -0
  26. package/dist/query.js +3 -0
  27. package/package.json +6 -2
  28. package/dist/chunks/duckdb-resources-Cci6Lo6H.js +0 -156
  29. package/dist/chunks/duckdb-resources-Cci6Lo6H.js.map +0 -1
  30. package/dist/chunks/postgres-dialect-Bfswr4Vs.js.map +0 -1
@@ -0,0 +1 @@
1
+ {"version":3,"file":"postgres-dialect-CGv6DxSP.js","names":["#connections","#pending","#evictions","#requests","#clearing","#failedClosures","#registerRequest","#throwIfCancelled","#throwIfFailedClosure","#waitForEviction","#clearError","#finishRequest","#clearKey","#cancelRequests"],"sources":["../../src/shared/alter-utils.ts","../../src/shared/connection-cache.ts","../../src/shared/transaction-lock.ts","../../src/shared/postgres-dialect.ts"],"sourcesContent":["/**\n * Shared utilities for ALTER TABLE operations\n *\n * Provides database-agnostic utilities for generating ALTER TABLE statements,\n * handling column definitions, and creating indexes.\n */\n\nimport type { ColumnDefinitionWithName, IndexDefinition } from './types.js';\n\n/**\n * Database dialect type for SQL generation\n */\nexport type DatabaseDialect = 'sqlite' | 'postgres' | 'duckdb';\n\n/**\n * Generates an ALTER TABLE ADD COLUMN statement\n *\n * @param table - Table name\n * @param column - Column definition with name\n * @param dialect - Database dialect\n * @returns SQL statement string\n *\n * @example\n * ```typescript\n * const sql = generateAddColumnStatement('users', {\n * name: 'email',\n * type: 'TEXT',\n * unique: true,\n * notNull: false\n * }, 'sqlite');\n * // Returns: \"ALTER TABLE users ADD COLUMN email TEXT UNIQUE\"\n * ```\n */\nexport function generateAddColumnStatement(\n table: string,\n column: ColumnDefinitionWithName,\n _dialect: DatabaseDialect,\n): string {\n const parts: string[] = [column.name, column.type];\n\n // Primary key\n if (column.primaryKey) {\n parts.push('PRIMARY KEY');\n }\n\n // NOT NULL constraint\n if (column.notNull) {\n parts.push('NOT NULL');\n }\n\n // UNIQUE constraint\n if (column.unique) {\n parts.push('UNIQUE');\n }\n\n // DEFAULT clause\n if (column.defaultValue !== undefined) {\n const defaultClause = generateDefaultClause(\n column.type,\n column.defaultValue,\n );\n parts.push(`DEFAULT ${defaultClause}`);\n }\n\n // CHECK constraint\n if (column.check) {\n parts.push(`CHECK (${column.check})`);\n }\n\n // Foreign key (inline for some databases)\n if (column.foreignKey) {\n const fk = column.foreignKey;\n const fkParts = [`REFERENCES ${fk.table}(${fk.column})`];\n\n if (fk.onDelete) {\n fkParts.push(`ON DELETE ${fk.onDelete}`);\n }\n\n if (fk.onUpdate) {\n fkParts.push(`ON UPDATE ${fk.onUpdate}`);\n }\n\n parts.push(fkParts.join(' '));\n }\n\n const columnDef = parts.join(' ');\n return `ALTER TABLE ${table} ADD COLUMN ${columnDef}`;\n}\n\n/**\n * Generates a DEFAULT clause for a column definition\n *\n * Handles proper formatting and escaping of default values based on column type.\n *\n * @param columnType - SQL column type (TEXT, INTEGER, BOOLEAN, etc.)\n * @param defaultValue - Default value to format\n * @returns Formatted default value string\n *\n * @example\n * ```typescript\n * generateDefaultClause('TEXT', 'hello'); // Returns: \"'hello'\"\n * generateDefaultClause('INTEGER', 42); // Returns: \"42\"\n * generateDefaultClause('BOOLEAN', true); // Returns: \"true\"\n * generateDefaultClause('TEXT', null); // Returns: \"NULL\"\n * ```\n */\nexport function generateDefaultClause(\n columnType: string,\n defaultValue: any,\n): string {\n if (defaultValue === null) {\n return 'NULL';\n }\n\n const typeUpper = columnType.toUpperCase();\n\n // String types - need quotes\n if (\n typeUpper.includes('TEXT') ||\n typeUpper.includes('CHAR') ||\n typeUpper.includes('VARCHAR') ||\n typeUpper.includes('STRING')\n ) {\n // Handle empty strings\n if (defaultValue === '') {\n return \"''\";\n }\n // Escape single quotes\n const escaped = String(defaultValue).replace(/'/g, \"''\");\n return `'${escaped}'`;\n }\n\n // Boolean types\n if (typeUpper.includes('BOOL')) {\n return defaultValue ? 'true' : 'false';\n }\n\n // Numeric types - no quotes\n if (\n typeUpper.includes('INT') ||\n typeUpper.includes('REAL') ||\n typeUpper.includes('FLOAT') ||\n typeUpper.includes('DOUBLE') ||\n typeUpper.includes('NUMERIC') ||\n typeUpper.includes('DECIMAL')\n ) {\n return String(defaultValue);\n }\n\n // JSON types\n if (typeUpper.includes('JSON')) {\n if (typeof defaultValue === 'string') {\n return `'${defaultValue.replace(/'/g, \"''\")}'`;\n }\n return `'${JSON.stringify(defaultValue).replace(/'/g, \"''\")}'`;\n }\n\n // Date/timestamp types\n if (\n typeUpper.includes('DATE') ||\n typeUpper.includes('TIME') ||\n typeUpper.includes('TIMESTAMP')\n ) {\n if (defaultValue instanceof Date) {\n return `'${defaultValue.toISOString()}'`;\n }\n return `'${String(defaultValue).replace(/'/g, \"''\")}'`;\n }\n\n // Default: treat as string\n if (typeof defaultValue === 'string') {\n return `'${defaultValue.replace(/'/g, \"''\")}'`;\n }\n\n return String(defaultValue);\n}\n\n/**\n * Generates a CREATE INDEX statement\n *\n * @param table - Table name\n * @param index - Index definition\n * @returns SQL CREATE INDEX statement\n *\n * @example\n * ```typescript\n * const sql = generateCreateIndexStatement('users', {\n * name: 'idx_users_email',\n * columns: ['email'],\n * unique: true\n * });\n * // Returns: \"CREATE UNIQUE INDEX idx_users_email ON users (email)\"\n * ```\n */\nexport function generateCreateIndexStatement(\n table: string,\n index: IndexDefinition,\n): string {\n const parts: string[] = ['CREATE'];\n\n // UNIQUE modifier\n if (index.unique) {\n parts.push('UNIQUE');\n }\n\n parts.push('INDEX');\n\n // Index name\n parts.push(index.name);\n\n // ON table\n parts.push(`ON ${table}`);\n\n // Column list\n const columns = index.columns.join(', ');\n parts.push(`(${columns})`);\n\n // WHERE clause (partial index)\n if (index.where) {\n parts.push(`WHERE ${index.where}`);\n }\n\n return parts.join(' ');\n}\n\n/**\n * Validates a table name to prevent SQL injection\n *\n * The argument must be a primitive string. `RegExp.prototype.test` coerces its\n * argument with `toString`, so an object whose `toString` returns a valid name\n * on the call the validator makes and a different one on the call the caller's\n * `${table}` interpolation makes would pass here and then reach SQL. Rejecting\n * non-strings up front closes that gap: the value validated is the value\n * interpolated, because a primitive string cannot observe how many times it is\n * read.\n *\n * @param tableName - Table name to validate\n * @throws Error if the value is not a string or contains invalid characters\n */\nexport function validateTableName(tableName: string): void {\n if (\n typeof tableName !== 'string' ||\n !/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(tableName)\n ) {\n throw new Error(\n `Invalid table name: ${tableName}. Table names must be a string that starts with a letter or underscore and contains only alphanumeric characters and underscores.`,\n );\n }\n}\n\n/**\n * Validates a column name to prevent SQL injection\n *\n * Rejects non-strings for the same reason as {@link validateTableName}: a value\n * whose `toString` differs between the validation read and the interpolation\n * read would otherwise slip a different identifier into SQL than the one\n * checked here.\n *\n * @param columnName - Column name to validate\n * @throws Error if the value is not a string or contains invalid characters\n */\nexport function validateColumnName(columnName: string): void {\n if (\n typeof columnName !== 'string' ||\n !/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(columnName)\n ) {\n throw new Error(\n `Invalid column name: ${columnName}. Column names must be a string that starts with a letter or underscore and contains only alphanumeric characters and underscores.`,\n );\n }\n}\n\n/**\n * Validates every identifier in a column list to prevent SQL injection\n *\n * Column names reaching the CRUD methods come from `Object.keys(data)` and the\n * caller's `conflictColumns`, both of which are interpolated into SQL. The\n * accepted shape has no character that can end an identifier. Adapters may\n * render a validated name bare, or quote it under an adapter-specific contract.\n * PostgreSQL upsert uses {@link quotePostgresColumnName}, which canonicalizes\n * the name before quoting so its established unquoted case-folding semantics\n * do not change.\n *\n * @param columnNames - Column names to validate\n * @throws Error if any column name contains invalid characters\n */\nexport function validateColumnNames(columnNames: string[]): void {\n for (const columnName of columnNames) {\n validateColumnName(columnName);\n }\n}\n\n/**\n * Quotes a validated column name using PostgreSQL's historic case semantics.\n *\n * PostgreSQL folds every unquoted identifier to lowercase. The CRUD API has\n * always accepted mixed-case inputs while rendering them unquoted, so quoting\n * the caller's spelling directly would silently change which physical column\n * is addressed. Validate the existing plain-identifier contract first, then\n * lowercase before quoting: `mixedCase` still addresses `mixedcase`, while a\n * reserved word such as `end` is no longer parsed as SQL syntax.\n *\n * @param columnName - Plain column name to render for PostgreSQL\n * @returns A lowercase, double-quoted PostgreSQL identifier\n * @throws Error if the column name is outside the CRUD identifier contract\n */\nexport function quotePostgresColumnName(columnName: string): string {\n validateColumnName(columnName);\n return `\"${columnName.toLowerCase()}\"`;\n}\n\n/**\n * Escapes an identifier for interpolation inside double quotes\n *\n * For the positions that already quote the identifier — the DuckDB and JSON\n * upsert statements, which quote to match their schema generator — quoting is\n * what makes the identifier safe, so the only thing that has to be handled is\n * a quote character inside the name. Doubling it is the SQL escape.\n *\n * This is deliberately more permissive than {@link validateColumnName}: those\n * adapters accept column names that are not plain identifiers (`Full Name`,\n * `user-id`, `2024_total`), which matters most for the JSON adapter, whose\n * columns come straight from the keys of whatever JSON it was pointed at.\n * Rejecting them would break working code to fix an injection that quoting\n * already prevents.\n *\n * @param identifier - Identifier to place inside double quotes\n * @returns The identifier with embedded quotes doubled\n * @throws Error if the identifier is empty or contains a NUL byte\n */\nexport function escapeQuotedIdentifier(identifier: string): string {\n // Coerce to a primitive string first. The escape's safety rests on\n // `replaceAll`/`includes` being the real `String` methods, but a crafted\n // object could supply its own that return unescaped SQL while its `toString`\n // reads as a benign name elsewhere. Coercing once runs its `toString` here\n // and pins an immutable primitive for the length check and the escape, so the\n // value escaped is the value returned.\n const value = String(identifier);\n if (value.length === 0 || value.includes('\\0')) {\n throw new Error(\n `Invalid column name: ${JSON.stringify(value)}. Column names must be non-empty and must not contain a NUL byte.`,\n );\n }\n return value.replaceAll('\"', '\"\"');\n}\n\n/**\n * Escapes a value for interpolation inside a single-quoted SQL string literal\n *\n * The DuckDB-backed adapters read JSON through `read_json_auto('<path>')`, and\n * a file path is not something an identifier validator can check — paths\n * legitimately contain spaces, dots and, on Linux and macOS, quotes. Doubling\n * the quote is the SQL escape, and it is what keeps a file named `x'.json`\n * from ending the literal and starting a statement.\n *\n * @param value - Value to place inside single quotes\n * @returns The value with embedded single quotes doubled\n * @throws Error if the value contains a NUL byte\n */\nexport function escapeStringLiteral(value: string): string {\n // Coerce to a primitive string first, for the same reason as\n // {@link escapeQuotedIdentifier}: the escape must run on an immutable\n // primitive, not on an object that could supply its own `replaceAll`.\n const text = String(value);\n if (text.includes('\\0')) {\n throw new Error(\n `Invalid SQL string literal: ${JSON.stringify(text)}. Values must not contain a NUL byte.`,\n );\n }\n return text.replaceAll(\"'\", \"''\");\n}\n\n/**\n * Validates an index name to prevent SQL injection\n *\n * @param indexName - Index name to validate\n * @throws Error if index name contains invalid characters\n */\nexport function validateIndexName(indexName: string): void {\n if (\n typeof indexName !== 'string' ||\n !/^[a-zA-Z_][a-zA-Z0-9_]*$/.test(indexName)\n ) {\n throw new Error(\n `Invalid index name: ${indexName}. Index names must be a string that starts with a letter or underscore and contains only alphanumeric characters and underscores.`,\n );\n }\n}\n","import type { DatabaseCacheOptions } from './types';\n\nconst CACHED_VALIDATION_CAPABILITY = Symbol.for(\n '@happyvertical/sql/connection-cache-cached-validation/v1',\n);\n\ntype PendingConnection<T> = {\n invalidated: false | 'clear' | 'evict';\n promise: Promise<T>;\n};\n\ntype EvictionChain<T> = {\n promise: Promise<void>;\n state: {\n invalidated: Set<PendingConnection<T>>;\n invalidation: 'clear' | 'evict';\n };\n};\n\ntype CacheRequest = {\n cancelled: boolean;\n done: Promise<void>;\n finish: () => void;\n};\n\n/** Race-safe async resource cache used by database adapters. */\nexport class ConnectionCache<T> {\n readonly [CACHED_VALIDATION_CAPABILITY] = true;\n readonly #connections = new Map<string, T>();\n readonly #pending = new Map<string, PendingConnection<T>>();\n readonly #evictions = new Map<string, EvictionChain<T>>();\n readonly #requests = new Map<string, Set<CacheRequest>>();\n readonly #clearing = new Map<string, number>();\n readonly #failedClosures = new Map<\n string,\n { error: unknown; resources: Set<T> }\n >();\n\n async getOrCreate(\n key: string | undefined,\n options: DatabaseCacheOptions,\n create: () => Promise<T>,\n close: (connection: T) => Promise<void>,\n validateCached?: (connection: T) => Promise<boolean>,\n ): Promise<T> {\n validateDatabaseCacheOptions(options);\n const request =\n key && options.cache !== false ? this.#registerRequest(key) : undefined;\n try {\n this.#throwIfCancelled(request);\n if (key && options.clearCache) {\n await this.evict(key, close);\n this.#throwIfCancelled(request);\n }\n if (key) this.#throwIfFailedClosure(key);\n\n if (!key || options.cache === false) {\n return create();\n }\n\n while (true) {\n if (this.#evictions.has(key)) {\n await this.#waitForEviction(key);\n this.#throwIfCancelled(request);\n }\n this.#throwIfFailedClosure(key);\n\n const cached = this.#connections.get(key);\n if (cached !== undefined) {\n if (!validateCached) return cached;\n\n // Validation may yield while another caller evicts this entry. Only\n // return the resource when it remains this key's live cache entry.\n const isValid = await validateCached(cached);\n this.#throwIfCancelled(request);\n if (\n isValid &&\n this.#connections.get(key) === cached &&\n !this.#evictions.has(key)\n ) {\n return cached;\n }\n if (\n !isValid &&\n this.#connections.get(key) === cached &&\n !this.#evictions.has(key)\n ) {\n await this.evict(key, close);\n this.#throwIfCancelled(request);\n }\n continue;\n }\n\n let pending = this.#pending.get(key);\n if (!pending) {\n this.#throwIfCancelled(request);\n pending = { invalidated: false, promise: create() };\n this.#pending.set(key, pending);\n }\n\n let connection: T;\n try {\n connection = await pending.promise;\n } catch (error) {\n if (this.#pending.get(key) === pending) {\n this.#pending.delete(key);\n }\n throw error;\n }\n\n if (pending.invalidated || this.#evictions.has(key)) {\n if (this.#evictions.has(key)) {\n await this.#waitForEviction(key);\n }\n this.#throwIfCancelled(request);\n if (pending.invalidated === 'clear') {\n throw this.#clearError();\n }\n continue;\n }\n\n this.#throwIfCancelled(request);\n if (this.#pending.get(key) === pending) {\n this.#pending.delete(key);\n }\n this.#connections.set(key, connection);\n return connection;\n }\n } finally {\n if (request && key) {\n this.#finishRequest(key, request);\n }\n }\n }\n\n async evict(\n key: string,\n close: (connection: T) => Promise<void>,\n invalidation: 'clear' | 'evict' = 'evict',\n ) {\n const previous = this.#evictions.get(key);\n const state = previous?.state ?? {\n invalidated: new Set<PendingConnection<T>>(),\n invalidation,\n };\n if (invalidation === 'clear') {\n state.invalidation = 'clear';\n for (const pending of state.invalidated) {\n pending.invalidated = 'clear';\n }\n }\n\n const eviction = (previous?.promise ?? Promise.resolve()).then(async () => {\n const resources = new Set<T>(\n this.#failedClosures.get(key)?.resources ?? [],\n );\n this.#failedClosures.delete(key);\n const cached = this.#connections.get(key);\n this.#connections.delete(key);\n if (cached) resources.add(cached);\n\n const pending = this.#pending.get(key);\n this.#pending.delete(key);\n if (pending) {\n state.invalidated.add(pending);\n pending.invalidated = state.invalidation;\n // The original initializer caller still observes its rejection. For\n // eviction, a stale failure means there is simply no resource to close.\n const initialized = await pending.promise.catch(() => undefined);\n if (initialized !== undefined) resources.add(initialized);\n }\n\n const closeResults = await Promise.allSettled(\n [...resources].map(async (resource) => {\n await close(resource);\n return resource;\n }),\n );\n const failures = closeResults.filter(\n (result): result is PromiseRejectedResult =>\n result.status === 'rejected',\n );\n if (failures.length) {\n const resourceList = [...resources];\n const failedResources = new Set<T>();\n closeResults.forEach((result, index) => {\n if (result.status === 'rejected') {\n failedResources.add(resourceList[index]);\n }\n });\n const error =\n failures.length === 1\n ? failures[0].reason\n : new AggregateError(\n failures.map((failure) => failure.reason),\n 'Multiple database connections failed to close',\n );\n this.#failedClosures.set(key, {\n error,\n resources: failedResources,\n });\n throw error;\n }\n });\n\n const chain = { promise: eviction, state };\n this.#evictions.set(key, chain);\n try {\n await eviction;\n } finally {\n if (this.#evictions.get(key) === chain) {\n this.#evictions.delete(key);\n }\n }\n }\n\n async clear(close: (connection: T) => Promise<void>) {\n const keys = new Set([\n ...this.#connections.keys(),\n ...this.#pending.keys(),\n ...this.#evictions.keys(),\n ...this.#requests.keys(),\n ...this.#clearing.keys(),\n ...this.#failedClosures.keys(),\n ]);\n const results = await Promise.allSettled(\n [...keys].map((key) => this.#clearKey(key, close)),\n );\n const failures = results.filter(\n (result): result is PromiseRejectedResult => result.status === 'rejected',\n );\n if (failures.length === 1) throw failures[0].reason;\n if (failures.length > 1) {\n throw new AggregateError(\n failures.map((failure) => failure.reason),\n 'Multiple database connection cache entries failed to clear',\n );\n }\n }\n\n forget(connection: T): void {\n for (const [key, cached] of this.#connections) {\n if (cached === connection) {\n this.#connections.delete(key);\n }\n }\n }\n\n /** @internal Test-only visibility; includes every retained namespace. */\n get size(): number {\n return (\n this.#connections.size +\n this.#pending.size +\n this.#evictions.size +\n this.#requests.size +\n this.#clearing.size +\n this.#failedClosures.size\n );\n }\n\n async #clearKey(key: string, close: (connection: T) => Promise<void>) {\n this.#clearing.set(key, (this.#clearing.get(key) ?? 0) + 1);\n try {\n this.#cancelRequests(key);\n await this.evict(key, close, 'clear');\n while (this.#requests.get(key)?.size) {\n this.#cancelRequests(key);\n await Promise.all(\n [...(this.#requests.get(key) ?? [])].map((request) => request.done),\n );\n }\n } finally {\n const remaining = (this.#clearing.get(key) ?? 1) - 1;\n if (remaining === 0) this.#clearing.delete(key);\n else this.#clearing.set(key, remaining);\n }\n }\n\n #cancelRequests(key: string): void {\n for (const request of this.#requests.get(key) ?? []) {\n request.cancelled = true;\n }\n }\n\n #clearError(): Error {\n return new Error(\n 'Database connection initialization was cancelled by cache clear',\n );\n }\n\n #finishRequest(key: string, request: CacheRequest): void {\n const requests = this.#requests.get(key);\n requests?.delete(request);\n if (requests?.size === 0) this.#requests.delete(key);\n request.finish();\n }\n\n #registerRequest(key: string): CacheRequest {\n let finish = () => {};\n const done = new Promise<void>((resolve) => {\n finish = resolve;\n });\n const request = {\n cancelled: this.#clearing.has(key),\n done,\n finish,\n };\n const requests = this.#requests.get(key) ?? new Set<CacheRequest>();\n requests.add(request);\n this.#requests.set(key, requests);\n return request;\n }\n\n #throwIfCancelled(request: CacheRequest | undefined): void {\n if (request?.cancelled) throw this.#clearError();\n }\n\n #throwIfFailedClosure(key: string): void {\n const failure = this.#failedClosures.get(key);\n if (failure) throw failure.error;\n }\n\n async #waitForEviction(key: string): Promise<void> {\n while (true) {\n const eviction = this.#evictions.get(key);\n if (!eviction) return;\n await eviction.promise;\n }\n }\n}\n\n/**\n * Adds cached-resource validation to a shared cache created by an older module.\n *\n * JSON connection caches live on `globalThis`, so a compatible older SDK copy\n * can create the shared object before this module loads. Mutating that object\n * preserves one cache for both module copies while upgrading its four-argument\n * `getOrCreate` method to the current validation contract.\n */\nexport function enableCachedValidation<T>(\n cache: ConnectionCache<T>,\n): ConnectionCache<T> {\n const compatible = cache as ConnectionCache<T> &\n Record<symbol, boolean | undefined>;\n if (compatible[CACHED_VALIDATION_CAPABILITY]) return cache;\n\n const legacyGetOrCreate = cache.getOrCreate.bind(cache) as (\n key: string | undefined,\n options: DatabaseCacheOptions,\n create: () => Promise<T>,\n close: (connection: T) => Promise<void>,\n ) => Promise<T>;\n const legacyClear = cache.clear.bind(cache);\n const locks = new Map<string, Promise<void>>();\n let clearGeneration = 0;\n let activeClear: Promise<void> | undefined;\n\n const runLocked = async <R>(key: string, work: () => Promise<R>) => {\n const previous = locks.get(key) ?? Promise.resolve();\n let release!: () => void;\n const current = new Promise<void>((resolve) => {\n release = resolve;\n });\n const chain = previous.then(\n () => current,\n () => current,\n );\n locks.set(key, chain);\n await previous.catch(() => {});\n try {\n return await work();\n } finally {\n release();\n if (locks.get(key) === chain) locks.delete(key);\n }\n };\n\n Object.defineProperty(cache, 'getOrCreate', {\n configurable: true,\n value: async (\n key: string | undefined,\n options: DatabaseCacheOptions,\n create: () => Promise<T>,\n close: (connection: T) => Promise<void>,\n validateCached?: (connection: T) => Promise<boolean>,\n ): Promise<T> => {\n if (!key || options.cache === false) {\n return legacyGetOrCreate(key, options, create, close);\n }\n const requestGeneration = clearGeneration;\n const throwIfCleared = () => {\n if (activeClear || requestGeneration !== clearGeneration) {\n throw new Error(\n 'Database connection initialization was cancelled by cache clear',\n );\n }\n };\n\n return runLocked(key, async () => {\n throwIfCleared();\n let requestOptions = options;\n while (true) {\n throwIfCleared();\n const candidate = await legacyGetOrCreate(\n key,\n requestOptions,\n create,\n close,\n );\n throwIfCleared();\n if (!validateCached) return candidate;\n\n const isValid = await validateCached(candidate);\n throwIfCleared();\n if (isValid) {\n // Reacquire under the compatibility lock so an explicit eviction\n // that completed during validation cannot make us return its old\n // resource.\n const confirmed = await legacyGetOrCreate(\n key,\n { ...requestOptions, clearCache: false },\n create,\n close,\n );\n throwIfCleared();\n if (confirmed === candidate) return candidate;\n } else {\n await cache.evict(key, close);\n }\n requestOptions = { ...options, clearCache: false };\n }\n });\n },\n writable: true,\n });\n Object.defineProperty(cache, 'clear', {\n configurable: true,\n value: async (close: (connection: T) => Promise<void>): Promise<void> => {\n if (activeClear) return activeClear;\n\n clearGeneration += 1;\n const clearing = (async () => {\n let clearError: unknown;\n let clearFailed = false;\n try {\n await legacyClear(close);\n } catch (error) {\n clearFailed = true;\n clearError = error;\n }\n while (locks.size > 0) {\n await Promise.allSettled([...locks.values()]);\n }\n if (clearFailed) throw clearError;\n })();\n activeClear = clearing;\n try {\n await clearing;\n } finally {\n if (activeClear === clearing) activeClear = undefined;\n }\n },\n writable: true,\n });\n Object.defineProperty(cache, CACHED_VALIDATION_CAPABILITY, {\n configurable: false,\n enumerable: false,\n value: true,\n writable: false,\n });\n return cache;\n}\n\nexport function validateDatabaseCacheOptions(options: DatabaseCacheOptions) {\n if (options.dbid === '') {\n throw new Error('Database cache dbid must be a non-empty string');\n }\n}\n","import { DatabaseError } from '@happyvertical/utils';\n\n/**\n * How long a queued transaction waits for the connection before giving up.\n *\n * A transaction that legitimately runs longer than this will make the ones\n * behind it fail rather than stall indefinitely. Raise it with the adapter's\n * `transactionQueueTimeout` option if that is the wrong trade for a workload.\n */\nexport const DEFAULT_TRANSACTION_QUEUE_TIMEOUT_MS = 30_000;\n\n/**\n * Serializes transactions on a connection that cannot hold more than one.\n */\nexport interface TransactionLock {\n /** Whether one caller currently owns the connection. */\n readonly held: boolean;\n\n /**\n * Takes the connection and returns the function that gives it back.\n *\n * Calling the returned function more than once is a no-op, so a teardown\n * path that runs twice cannot hand the connection to two callers at once.\n */\n acquire(): Promise<() => void>;\n\n /**\n * Runs `work` with exclusive use of the connection, releasing it however\n * `work` finishes.\n */\n run<T>(work: () => Promise<T>): Promise<T>;\n}\n\n/**\n * Creates a lock that serializes transactions on one connection.\n *\n * SQLite, DuckDB and the JSON adapter each drive a single connection, and a\n * connection can only be in one transaction at a time. `transaction()` used to\n * issue `BEGIN` on that shared connection with no serialization and no record\n * of whether one was already open, so two overlapping calls corrupted each\n * other: the second `BEGIN` threw, its `catch` ran `ROLLBACK`, and that\n * rollback landed on the *first* transaction — committing part of its work,\n * discarding the rest, and rejecting its promise. Nesting was not required;\n * two concurrent requests were enough, which made it reachable from any server\n * handling more than one at a time.\n *\n * The lock spans the whole `BEGIN` … `COMMIT`/`ROLLBACK` sequence, so a queued\n * transaction starts only once the previous one has ended. It is a\n * promise-chain mutex, the same shape as the `withNullAwareUpsertLock` the\n * SQLite adapter already used for the narrower upsert case.\n *\n * Re-entrant calls must not come through here. A nested `tx.transaction()`\n * arrives via the transaction-scoped interface, which re-enters under a\n * `SAVEPOINT` (SQLite) or refuses (DuckDB, JSON) without ever reaching the\n * top-level `transaction()`; routing one here instead would make it wait on a\n * lock its own caller is holding.\n *\n * @param adapter - Adapter name, for the timeout error\n * @param timeoutMs - Ceiling on how long to wait for a turn\n */\nexport function createTransactionLock(\n adapter: string,\n timeoutMs: number = DEFAULT_TRANSACTION_QUEUE_TIMEOUT_MS,\n): TransactionLock {\n // The timer is measured from enqueue, not from when the lock frees, so this\n // bounds the total wait rather than any one holder. A caller that expects\n // sustained bursts on one connection should raise it: a hundred queued\n // 400ms transactions exceed 30s even though none of them is stuck.\n if (!Number.isFinite(timeoutMs) || timeoutMs <= 0) {\n throw new DatabaseError(\n 'transactionQueueTimeout must be a positive, finite number of milliseconds',\n { adapter, timeoutMs },\n );\n }\n // Resolves when the transaction currently holding the connection ends.\n let tail: Promise<void> = Promise.resolve();\n let held = false;\n\n const acquire = async (): Promise<() => void> => {\n const previous = tail;\n let release: () => void = () => {};\n const current = new Promise<void>((resolve) => {\n release = resolve;\n });\n\n // Publish our turn before awaiting, so a caller that arrives while we are\n // suspended queues behind us rather than racing us for the connection.\n tail = previous.then(\n () => current,\n () => current,\n );\n\n let timer: ReturnType<typeof setTimeout> | undefined;\n try {\n await new Promise<void>((resolve, reject) => {\n timer = setTimeout(() => {\n reject(\n new DatabaseError(\n `Timed out after ${timeoutMs}ms waiting for the ${adapter} connection's current transaction to finish. This connection runs one transaction at a time. Usually one of: a beginTransaction() handle that was never committed or rolled back; a top-level db.* call that opens its own transaction being made inside a transaction callback, which waits on the connection its own caller holds (use the tx-scoped method instead); or simply more queued transactions than transactionQueueTimeout allows for.`,\n { adapter, timeoutMs },\n ),\n );\n }, timeoutMs);\n previous.then(resolve, resolve);\n });\n } catch (error) {\n // Drop out of the queue rather than wedge it: `tail` still chains through\n // `current`, so resolving it lets the callers behind us take their turn.\n release();\n throw error;\n } finally {\n if (timer) clearTimeout(timer);\n }\n\n let released = false;\n held = true;\n return () => {\n if (released) return;\n released = true;\n held = false;\n release();\n };\n };\n\n const run = async <T>(work: () => Promise<T>): Promise<T> => {\n const release = await acquire();\n try {\n return await work();\n } finally {\n release();\n }\n };\n\n return {\n acquire,\n get held() {\n return held;\n },\n run,\n };\n}\n","/**\n * PostgreSQL dialect logic shared by every adapter that speaks to a Postgres\n * server: the `pg` adapter (`../postgres`) and the PGlite adapter\n * (`../pglite`).\n *\n * Everything here runs on a {@link PostgresQueryExecutor}, so the SQL the two\n * adapters emit is the same code rather than two copies that drift. The module\n * must stay browser-safe: no `node:` built-ins and no import of `pg`, because\n * the PGlite adapter's import graph reaches it.\n */\n\nimport { DatabaseError } from '@happyvertical/utils';\nimport {\n generateAddColumnStatement,\n generateCreateIndexStatement,\n quotePostgresColumnName,\n validateColumnName,\n validateColumnNames,\n validateIndexName,\n validateTableName,\n} from './alter-utils';\nimport type {\n QueryResult as BaseQueryResult,\n ColumnDefinition,\n ColumnDefinitionWithName,\n DatabaseInterface,\n IndexDefinition,\n TableInterface,\n TableSchemaInfo,\n UpsertOptions,\n VectorCapabilities,\n VectorIndexOptions,\n VectorSearchOptions,\n VectorSearchResult,\n} from './types';\nimport {\n buildWhere,\n formatDbError,\n resolveInsertColumns,\n wrapDatabaseError,\n} from './utils';\n\n/** The one method every statement runs through. */\nexport type PostgresQueryExecutor = {\n query: (\n sql: string,\n values?: any[],\n ) => Promise<{ rows: any[]; rowCount: number | null }>;\n};\n\n/**\n * Operator for the given distance metric in pgvector\n */\nfunction vectorOperator(metric: 'cosine' | 'l2' | 'ip'): string {\n switch (metric) {\n case 'cosine':\n return '<=>';\n case 'l2':\n return '<->';\n case 'ip':\n return '<#>';\n default:\n return '<=>';\n }\n}\n\nfunction getMaxPostgresParameterIndex(sql: string): number {\n let maxIndex = 0;\n for (const match of sql.matchAll(/\\$(\\d+)/g)) {\n const index = Number(match[1]);\n if (Number.isSafeInteger(index) && index > maxIndex) {\n maxIndex = index;\n }\n }\n return maxIndex;\n}\n\nfunction usesSingleArrayParameter(sql: string): boolean {\n const identifier = String.raw`(?:\"[^\"]+\"|[a-z_][\\w$]*)`;\n const qualifiedIdentifier = String.raw`${identifier}(?:\\s*\\.\\s*${identifier})?`;\n const arrayType = String.raw`${qualifiedIdentifier}(?:\\s*\\([^)]*\\))?\\s*\\[\\]`;\n\n return (\n new RegExp(String.raw`\\$1\\s*::\\s*${arrayType}`, 'i').test(sql) ||\n new RegExp(\n String.raw`\\bCAST\\s*\\(\\s*\\$1\\s+AS\\s+${arrayType}\\s*\\)`,\n 'i',\n ).test(sql) ||\n /\\b(?:ANY|ALL|SOME)\\s*\\(\\s*\\$1\\s*\\)/i.test(sql)\n );\n}\n\nfunction normalizeRawQueryValues(sql: string, values: any[]): any[] {\n if (values.length !== 1 || !Array.isArray(values[0])) {\n return values;\n }\n\n const valuesArray = values[0];\n const maxParameterIndex = getMaxPostgresParameterIndex(sql);\n\n if (maxParameterIndex === 1 && usesSingleArrayParameter(sql)) {\n return values;\n }\n\n if (maxParameterIndex === 0 || maxParameterIndex === valuesArray.length) {\n return valuesArray;\n }\n\n return values;\n}\n\nfunction rewriteQuestionMarkPlaceholders(sql: string): {\n sql: string;\n count: number;\n} {\n let output = '';\n let count = 0;\n let index = 0;\n\n const copyQuoted = (quote: \"'\" | '\"', escaped = false) => {\n output += quote;\n index += 1;\n\n while (index < sql.length) {\n const char = sql[index];\n output += char;\n index += 1;\n\n if (escaped && char === '\\\\' && index < sql.length) {\n output += sql[index];\n index += 1;\n continue;\n }\n\n if (char === quote) {\n if (sql[index] === quote) {\n output += sql[index];\n index += 1;\n continue;\n }\n break;\n }\n }\n };\n\n const copyUntil = (end: string) => {\n const endIndex = sql.indexOf(end, index + end.length);\n if (endIndex === -1) {\n output += sql.slice(index);\n index = sql.length;\n return;\n }\n\n output += sql.slice(index, endIndex + end.length);\n index = endIndex + end.length;\n };\n\n while (index < sql.length) {\n const char = sql[index];\n const next = sql[index + 1];\n\n if ((char === 'E' || char === 'e') && next === \"'\") {\n output += char;\n index += 1;\n copyQuoted(\"'\", true);\n continue;\n }\n\n if (char === \"'\") {\n copyQuoted(\"'\");\n continue;\n }\n\n if (char === '\"') {\n copyQuoted('\"');\n continue;\n }\n\n if (char === '-' && next === '-') {\n const endIndex = sql.indexOf('\\n', index + 2);\n if (endIndex === -1) {\n output += sql.slice(index);\n index = sql.length;\n } else {\n output += sql.slice(index, endIndex + 1);\n index = endIndex + 1;\n }\n continue;\n }\n\n if (char === '/' && next === '*') {\n copyUntil('*/');\n continue;\n }\n\n if (char === '$') {\n const tag = sql.slice(index).match(/^\\$[A-Za-z_][\\w$]*\\$|^\\$\\$/);\n if (tag) {\n copyUntil(tag[0]);\n continue;\n }\n }\n\n if (char === '?' && next !== '|' && next !== '&') {\n count += 1;\n output += `$${count}`;\n index += 1;\n continue;\n }\n\n output += char;\n index += 1;\n }\n\n return { sql: output, count };\n}\n\nfunction usesSingleQuestionArrayParameter(sql: string): boolean {\n const identifier = String.raw`(?:\"[^\"]+\"|[a-z_][\\w$]*)`;\n const qualifiedIdentifier = String.raw`${identifier}(?:\\s*\\.\\s*${identifier})?`;\n const arrayType = String.raw`${qualifiedIdentifier}(?:\\s*\\([^)]*\\))?\\s*\\[\\]`;\n\n return (\n new RegExp(String.raw`\\?\\s*::\\s*${arrayType}`, 'i').test(sql) ||\n new RegExp(String.raw`\\bCAST\\s*\\(\\s*\\?\\s+AS\\s+${arrayType}\\s*\\)`, 'i').test(\n sql,\n ) ||\n /\\b(?:ANY|ALL|SOME)\\s*\\(\\s*\\?\\s*\\)/i.test(sql)\n );\n}\n\nfunction normalizeQuestionMarkQueryValues(\n sql: string,\n values: any[],\n placeholderCount: number,\n): any[] {\n if (values.length !== 1 || !Array.isArray(values[0])) {\n return values;\n }\n\n if (placeholderCount === 1 && usesSingleQuestionArrayParameter(sql)) {\n return values;\n }\n\n if (placeholderCount === values[0].length) {\n return values[0];\n }\n\n return values;\n}\n\nexport function normalizePostgresRawQuery(\n sql: string,\n values: any[],\n): { sql: string; values: any[] } {\n if (getMaxPostgresParameterIndex(sql) > 0) {\n return { sql, values: normalizeRawQueryValues(sql, values) };\n }\n\n const rewritten = rewriteQuestionMarkPlaceholders(sql);\n const placeholderCount = rewritten.count;\n const queryValues = normalizeQuestionMarkQueryValues(\n sql,\n values,\n placeholderCount,\n );\n\n if (placeholderCount > 0 && placeholderCount === queryValues.length) {\n return {\n sql: rewritten.sql,\n values: queryValues,\n };\n }\n\n return { sql, values: normalizeRawQueryValues(sql, values) };\n}\n\n/**\n * pgvector index operator class for CREATE INDEX\n */\nfunction vectorOpsClass(metric: 'cosine' | 'l2' | 'ip'): string {\n switch (metric) {\n case 'cosine':\n return 'vector_cosine_ops';\n case 'l2':\n return 'vector_l2_ops';\n case 'ip':\n return 'vector_ip_ops';\n default:\n return 'vector_cosine_ops';\n }\n}\n\n/**\n * Convert a number[] to a pgvector literal string: '[0.1,0.2,0.3]'\n */\nfunction toVectorLiteral(embedding: number[]): string {\n if (embedding.length === 0) {\n throw new DatabaseError('Vector embedding must not be empty', {});\n }\n for (let i = 0; i < embedding.length; i++) {\n if (!Number.isFinite(embedding[i])) {\n throw new DatabaseError(\n 'Vector embedding contains invalid value (NaN or Infinity)',\n { index: i, value: embedding[i] },\n );\n }\n }\n return `[${embedding.join(',')}]`;\n}\n\n/**\n * Creates vector capabilities backed by pgvector for a PostgreSQL pool.\n *\n * @param pool - PostgreSQL connection pool\n * @returns VectorCapabilities implementation\n */\n/**\n * `type` is interpolated into `USING <type>`, which cannot be parameterized and\n * is not an identifier the quoting helpers cover. `VectorIndexOptions.type`\n * constrains it at compile time only, so anything reaching this at runtime —\n * a JavaScript caller, or a `filter as VectorIndexOptions` on parsed JSON — has\n * to be checked against the values pgvector actually offers.\n */\nconst VECTOR_INDEX_TYPES = new Set(['hnsw', 'ivfflat']);\n\n/**\n * `metric` needs the same treatment as `type`, for a less obvious reason.\n *\n * It never reaches SQL directly — `vectorOpsClass`/`vectorOperator` map it\n * through a closed switch with a safe default, so an unknown metric produces a\n * valid operator class. But it is also concatenated into the *generated index\n * name*, which is then interpolated into a quoted identifier, so a metric\n * carrying a `\"` still ends that identifier. The safe-default mapping is what\n * makes this easy to miss: the part of the metric that looks dangerous is\n * handled, and the part that is actually dangerous is somewhere else.\n */\nconst VECTOR_METRICS = new Set(['cosine', 'l2', 'ip']);\n\nexport function createVectorCapabilities(\n pool: PostgresQueryExecutor,\n): VectorCapabilities {\n return {\n async ensureColumn(\n table: string,\n column: string,\n dimensions: number,\n ): Promise<void> {\n if (!Number.isInteger(dimensions) || dimensions <= 0) {\n throw new DatabaseError(\n 'Vector dimensions must be a positive integer',\n { dimensions },\n );\n }\n validateTableName(table);\n validateColumnName(column);\n try {\n await pool.query('CREATE EXTENSION IF NOT EXISTS vector');\n await pool.query(\n `ALTER TABLE \"${table}\" ADD COLUMN IF NOT EXISTS \"${column}\" vector(${dimensions})`,\n );\n } catch (e) {\n throw new DatabaseError('Failed to ensure vector column', {\n table,\n column,\n dimensions,\n originalError: formatDbError(e),\n });\n }\n },\n\n async ensureIndex(\n table: string,\n column: string,\n options?: VectorIndexOptions,\n ): Promise<void> {\n validateTableName(table);\n validateColumnName(column);\n const metric = options?.metric || 'cosine';\n const indexType = options?.type || 'hnsw';\n if (!VECTOR_INDEX_TYPES.has(indexType)) {\n throw new DatabaseError('Unsupported vector index type', {\n table,\n column,\n type: indexType,\n supported: [...VECTOR_INDEX_TYPES],\n });\n }\n if (!VECTOR_METRICS.has(metric)) {\n throw new DatabaseError('Unsupported vector metric', {\n table,\n column,\n metric,\n supported: [...VECTOR_METRICS],\n });\n }\n const opsClass = vectorOpsClass(metric);\n // Every part is now either a validated identifier or one of a closed set,\n // so the generated name cannot carry SQL of its own.\n const indexName = `idx_${table}_${column}_${metric}_${indexType}`;\n\n try {\n await pool.query(\n `CREATE INDEX IF NOT EXISTS \"${indexName}\" ON \"${table}\" USING ${indexType} (\"${column}\" ${opsClass})`,\n );\n } catch (e) {\n throw new DatabaseError('Failed to ensure vector index', {\n table,\n column,\n indexName,\n originalError: formatDbError(e),\n });\n }\n },\n\n async upsertVector(\n table: string,\n where: Record<string, any>,\n column: string,\n embedding: number[],\n ): Promise<void> {\n validateTableName(table);\n validateColumnName(column);\n const keys = Object.keys(where);\n validateColumnNames(keys);\n const values = Object.values(where);\n const conditions = keys\n .map((key, i) => `\"${key}\" IS NOT DISTINCT FROM $${i + 1}`)\n .join(' AND ');\n const vectorParam = `$${values.length + 1}`;\n\n try {\n await pool.query(\n `UPDATE \"${table}\" SET \"${column}\" = ${vectorParam}::vector WHERE ${conditions}`,\n [...values, toVectorLiteral(embedding)],\n );\n } catch (e) {\n throw new DatabaseError('Failed to upsert vector', {\n table,\n column,\n where,\n originalError: formatDbError(e),\n });\n }\n },\n\n async search(\n table: string,\n column: string,\n embedding: number[],\n options?: VectorSearchOptions,\n ): Promise<VectorSearchResult[]> {\n validateTableName(table);\n validateColumnName(column);\n const metric = options?.metric || 'cosine';\n const limit = options?.limit || 10;\n const op = vectorOperator(metric);\n\n // $1 is the query vector; user-provided WHERE params use $2, $3, etc.\n const queryParams: any[] = [toVectorLiteral(embedding)];\n\n let whereClause = `\"${column}\" IS NOT NULL`;\n if (options?.where) {\n // `options.where` is raw SQL by design, the same documented\n // developer-controlled boundary as `buildWhere`'s operator-suffix keys.\n // It is not validated here; use `options.params` for anything that came\n // from outside the process.\n whereClause += ` AND (${options.where})`;\n if (options.params) {\n queryParams.push(...options.params);\n }\n }\n\n const limitParam = `$${queryParams.length + 1}`;\n queryParams.push(limit);\n\n const sql = `SELECT *, (\"${column}\" ${op} $1::vector) AS distance FROM \"${table}\" WHERE ${whereClause} ORDER BY \"${column}\" ${op} $1::vector LIMIT ${limitParam}`;\n\n try {\n const result = await pool.query(sql, queryParams);\n\n return result.rows.map((row: Record<string, any>) => ({\n ...row,\n id: row.id as string,\n distance: Number.parseFloat(row.distance),\n }));\n } catch (e) {\n throw new DatabaseError('Failed to execute vector search', {\n table,\n column,\n metric,\n limit,\n originalError: formatDbError(e),\n });\n }\n },\n };\n}\n\n/**\n * Keeps the first PostgreSQL statement failure attached to a transaction.\n *\n * PostgreSQL reports every later statement in an aborted transaction as\n * 25P02. Replacing the first failure with that generic state error hides the\n * actionable code and diagnostics from callers, so the tracker rethrows the\n * first failure whenever PostgreSQL reports 25P02, and exposes the recorded\n * failure so a swallowed statement error cannot make COMMIT's implicit\n * rollback look successful: PostgreSQL answers COMMIT on an aborted\n * transaction with a ROLLBACK tag and no error.\n *\n * @param isStatementError - Recognizes the driver's server-reported error\n * class (`pg`'s or PGlite's `DatabaseError`). Anything else is an\n * unconfirmed failure — it may be the transport, not the statement.\n */\nexport function createTransactionErrorTracker(\n isStatementError: (error: unknown) => boolean,\n) {\n let firstError: unknown;\n let firstUnconfirmedError: unknown;\n const pending = new Set<Promise<unknown>>();\n\n const isRollbackToSavepoint = (query: unknown): boolean => {\n const sql =\n typeof query === 'string'\n ? query\n : typeof query === 'object' &&\n query !== null &&\n 'text' in query &&\n typeof query.text === 'string'\n ? query.text\n : undefined;\n if (sql === undefined) return false;\n\n let statement = sql.trimStart();\n while (statement.startsWith('--') || statement.startsWith('/*')) {\n if (statement.startsWith('--')) {\n const newline = statement.search(/[\\r\\n]/);\n if (newline === -1) return false;\n statement = statement.slice(newline + 1).trimStart();\n continue;\n }\n const commentEnd = statement.indexOf('*/', 2);\n if (commentEnd === -1) return false;\n statement = statement.slice(commentEnd + 2).trimStart();\n }\n return /^ROLLBACK\\s+TO(?:\\s+SAVEPOINT)?\\s+/i.test(statement);\n };\n\n const errorCode = (error: unknown): string | undefined => {\n if (\n typeof error === 'object' &&\n error !== null &&\n 'code' in error &&\n typeof error.code === 'string'\n ) {\n return error.code;\n }\n return undefined;\n };\n\n /** Records a failure and returns the error the caller should see. */\n const preserve = (error: unknown): unknown => {\n if (errorCode(error) === '25P02' && firstError !== undefined) {\n return firstError;\n }\n if (errorCode(error) === '25P02' && firstUnconfirmedError !== undefined) {\n return firstUnconfirmedError;\n }\n if (isStatementError(error)) {\n firstError ??= error;\n } else {\n firstUnconfirmedError ??= error;\n }\n return error;\n };\n\n /**\n * Records that a statement succeeded. A successful rollback to a savepoint\n * restores the transaction to the state at that savepoint, so a recorded\n * statement failure has been contained.\n */\n const confirm = (query: unknown): void => {\n if (isRollbackToSavepoint(query)) firstError = undefined;\n firstUnconfirmedError = undefined;\n };\n\n const track = <T>(operation: Promise<T>, query: unknown): Promise<T> => {\n const tracked = operation\n .then((result) => {\n confirm(query);\n return result;\n })\n .catch((error) => {\n throw preserve(error);\n });\n pending.add(tracked);\n void tracked.finally(() => pending.delete(tracked)).catch(() => {});\n return tracked;\n };\n\n return {\n pending,\n preserve,\n confirm,\n track,\n clearError: () => {\n firstError = undefined;\n },\n drain: async () => {\n while (pending.size > 0) {\n await Promise.allSettled([...pending]);\n }\n },\n getError: () => firstError,\n getUnconfirmedError: () => firstUnconfirmedError,\n };\n}\n\n/**\n * What an adapter supplies to the shared dialect.\n */\nexport interface PostgresDialectHost {\n /** Executor for statements outside any transaction. */\n client: PostgresQueryExecutor;\n\n /**\n * Runs `work` inside a short transaction of its own. Used by a null-aware\n * upsert issued outside a transaction, which needs its advisory lock and the\n * following update/insert to share one.\n */\n runInTransaction<T>(\n work: (executor: PostgresQueryExecutor) => Promise<T>,\n ): Promise<T>;\n\n /**\n * Executor for read-only catalog probes (server version, index flags).\n *\n * A pooled adapter answers with the pool, so a failing probe cannot abort the\n * caller's transaction. A single-connection adapter has no second connection\n * and must answer with the executor it was handed.\n */\n probeExecutor(executor: PostgresQueryExecutor): PostgresQueryExecutor;\n}\n\n/** One level of nested-transaction queueing. */\nexport interface NestedScope {\n tail: Promise<void>;\n}\n\n/**\n * Ambient scope tracking for nested transactions.\n *\n * With one, a nested callback may call the *outer* transaction handle and still\n * be queued under its own scope (the `pg` adapter uses `AsyncLocalStorage`).\n * Without one (browsers have no `AsyncLocalStorage`), each nested callback is\n * handed a handle bound to its own scope instead, so nested work must use the\n * handle it is given.\n */\nexport interface NestedScopeContext {\n getStore(): NestedScope | undefined;\n run<R>(scope: NestedScope, fn: () => R): R;\n}\n\nexport type NestedTransaction = (<T>(\n callback: (tx: DatabaseInterface) => Promise<T>,\n) => Promise<T>) & {\n drain: () => Promise<void>;\n};\n\n/**\n * Creates the dialect: every statement-level method plus nested-transaction\n * and schema-introspection builders, all bound to `host`.\n */\nexport function createPostgresDialect(host: PostgresDialectHost) {\n // Names nested savepoints. Only ever appended to an identifier the adapter\n // generates, never caller input.\n let savepointSequence = 0;\n\n /**\n * Serializes a value for database storage\n * Converts objects and arrays to JSON strings\n * Converts Dates to ISO strings\n * Passes through primitives unchanged\n */\n const serializeValue = (value: any): any => {\n if (value === null || value === undefined) {\n return value;\n }\n if (value instanceof Date) {\n return value.toISOString();\n }\n if (ArrayBuffer.isView(value)) {\n return value;\n }\n if (typeof value === 'object') {\n return JSON.stringify(value);\n }\n return value;\n };\n\n /**\n * Serializes all values in an object for database storage\n */\n const serializeRecord = (\n record: Record<string, any>,\n ): Record<string, any> => {\n const serialized: Record<string, any> = {};\n for (const [key, value] of Object.entries(record)) {\n // Skip undefined values - they cannot be passed to the database\n if (value === undefined) {\n continue;\n }\n serialized[key] = serializeValue(value);\n }\n return serialized;\n };\n let serverVersionNumPromise: Promise<number> | undefined;\n const nullsNotDistinctIndexCache = new Map<string, Promise<boolean>>();\n\n const hasNullConflictValue = (\n conflictColumns: string[],\n data: Record<string, any>,\n ): boolean => conflictColumns.some((col) => data[col] === null);\n\n const validateUpsertConflictColumns = (\n table: string,\n conflictColumns: string[],\n serializedData: Record<string, any>,\n ): void => {\n const missingColumns = conflictColumns.filter(\n (col) => !(col in serializedData),\n );\n\n if (missingColumns.length > 0) {\n throw new DatabaseError('Conflict columns missing from data', {\n table,\n conflictColumns,\n missingColumns,\n availableColumns: Object.keys(serializedData),\n hint: 'All columns specified in ON CONFLICT must be present in the data being inserted. Undefined values should be replaced with null or an appropriate default.',\n });\n }\n };\n\n const getServerVersionNum = async (\n executor: PostgresQueryExecutor,\n ): Promise<number> => {\n serverVersionNumPromise ??= executor\n .query('SHOW server_version_num')\n .then((result) => Number(result.rows[0]?.server_version_num) || 0)\n .catch((error) => {\n // A probe that failed because of the caller's transaction state or a\n // lock wait says nothing about the server; do not remember it.\n serverVersionNumPromise = undefined;\n throw error;\n });\n return serverVersionNumPromise;\n };\n\n const hasNativeNullsNotDistinctIndex = async (\n executor: PostgresQueryExecutor,\n table: string,\n conflictColumns: string[],\n ): Promise<boolean> => {\n const versionNum = await getServerVersionNum(executor);\n if (versionNum < 150000) return false;\n\n const cacheKey = `${table}:${conflictColumns.join(',')}`;\n let cached = nullsNotDistinctIndexCache.get(cacheKey);\n if (!cached) {\n cached = executor\n .query(\n `\n SELECT 1\n FROM pg_index i\n WHERE i.indrelid = to_regclass($1)\n AND i.indisunique\n AND i.indnullsnotdistinct\n AND ARRAY(\n SELECT a.attname::text\n FROM unnest(i.indkey) WITH ORDINALITY AS cols(attnum, ord)\n JOIN pg_attribute a\n ON a.attrelid = i.indrelid\n AND a.attnum = cols.attnum\n ORDER BY cols.ord\n ) = $2::text[]\n LIMIT 1\n `,\n [table, conflictColumns],\n )\n .then((result) => result.rows.length > 0)\n .catch(() => {\n // Same reason: only a successful probe is worth remembering.\n nullsNotDistinctIndexCache.delete(cacheKey);\n return false;\n });\n nullsNotDistinctIndexCache.set(cacheKey, cached);\n }\n\n return cached;\n };\n\n const buildPostgresUpsertParts = (\n conflictColumns: string[],\n serializedData: Record<string, any>,\n ) => {\n const keys = Object.keys(serializedData);\n const columns = keys.map(quotePostgresColumnName);\n const values = Object.values(serializedData);\n const placeholders = keys.map((_, i) => `$${i + 1}`).join(', ');\n const updateSet = columns\n .map((column, i) => `${column} = $${i + 1}`)\n .join(', ');\n const conflict = conflictColumns.map(quotePostgresColumnName).join(', ');\n\n return { columns, values, placeholders, updateSet, conflict };\n };\n\n const executeStandardPostgresUpsert = async (\n executor: PostgresQueryExecutor,\n table: string,\n conflictColumns: string[],\n serializedData: Record<string, any>,\n ): Promise<BaseQueryResult> => {\n const { columns, values, placeholders, updateSet, conflict } =\n buildPostgresUpsertParts(conflictColumns, serializedData);\n const sql = `INSERT INTO ${table} (${columns.join(', ')}) VALUES (${placeholders}) ON CONFLICT(${conflict}) DO UPDATE SET ${updateSet}`;\n const result = await executor.query(sql, values);\n return { operation: 'upsert', affected: result.rowCount ?? 0 };\n };\n\n const executeNullAwarePostgresUpsert = async (\n executor: PostgresQueryExecutor,\n table: string,\n conflictColumns: string[],\n serializedData: Record<string, any>,\n ): Promise<BaseQueryResult> => {\n const { columns, values, placeholders, updateSet } =\n buildPostgresUpsertParts(conflictColumns, serializedData);\n const lockKey = conflictColumns\n .map((col) => `${col}:${JSON.stringify(serializedData[col])}`)\n .join('|');\n\n await executor.query(\n 'SELECT pg_advisory_xact_lock(hashtext($1), hashtext($2))',\n [`@happyvertical/sql.upsert:${table}`, lockKey],\n );\n\n const whereStart = values.length + 1;\n const whereClause = conflictColumns\n .map(\n (col, i) =>\n `${quotePostgresColumnName(col)} IS NOT DISTINCT FROM $${whereStart + i}`,\n )\n .join(' AND ');\n const whereValues = conflictColumns.map((col) => serializedData[col]);\n const updateSql = `UPDATE ${table} SET ${updateSet} WHERE ${whereClause}`;\n const updateResult = await executor.query(updateSql, [\n ...values,\n ...whereValues,\n ]);\n\n if ((updateResult.rowCount ?? 0) > 0) {\n return { operation: 'upsert', affected: updateResult.rowCount ?? 0 };\n }\n\n const insertSql = `INSERT INTO ${table} (${columns.join(', ')}) VALUES (${placeholders})`;\n const insertResult = await executor.query(insertSql, values);\n return { operation: 'upsert', affected: insertResult.rowCount ?? 0 };\n };\n const executePostgresUpsert = async (\n executor: PostgresQueryExecutor,\n table: string,\n conflictColumns: string[],\n serializedData: Record<string, any>,\n options: UpsertOptions | undefined,\n acquireTransaction: boolean,\n ): Promise<BaseQueryResult> => {\n validateUpsertConflictColumns(table, conflictColumns, serializedData);\n\n if (\n options?.nullsDistinct ||\n !hasNullConflictValue(conflictColumns, serializedData)\n ) {\n return executeStandardPostgresUpsert(\n executor,\n table,\n conflictColumns,\n serializedData,\n );\n }\n\n if (\n await hasNativeNullsNotDistinctIndex(\n host.probeExecutor(executor),\n table,\n conflictColumns,\n )\n ) {\n return executeStandardPostgresUpsert(\n executor,\n table,\n conflictColumns,\n serializedData,\n );\n }\n\n if (!acquireTransaction) {\n return executeNullAwarePostgresUpsert(\n executor,\n table,\n conflictColumns,\n serializedData,\n );\n }\n\n return host.runInTransaction((transactionExecutor) =>\n executeNullAwarePostgresUpsert(\n transactionExecutor,\n table,\n conflictColumns,\n serializedData,\n ),\n );\n };\n /**\n * Template and values extracted from a tagged template literal\n */\n interface SqlTemplate {\n /**\n * SQL query with parameter placeholders\n */\n sql: string;\n\n /**\n * Values to use as parameters\n */\n values: any[];\n }\n\n /**\n * Parses a tagged template literal into a SQL query and values\n *\n * @param strings - Template strings\n * @param vars - Variables to interpolate into the query\n * @returns Object with SQL query and values array\n */\n const parseTemplate = (\n strings: TemplateStringsArray,\n ...vars: any[]\n ): SqlTemplate => {\n let sql = strings[0];\n const values = [];\n for (let i = 0; i < vars.length; i++) {\n values.push(vars[i]);\n sql += `$${i + 1}${strings[i + 1]}`;\n }\n return { sql, values };\n };\n /**\n * Builds the complete set of query methods bound to one PostgreSQL client.\n *\n * The pool-backed interface and every transaction-scoped interface are\n * instantiated from this one factory, so there is exactly one implementation\n * of each method. The transaction interfaces used to be hand-maintained\n * copies of these bodies, and both had drifted:\n *\n * - they called the client bare, so a failure inside a transaction threw the\n * raw `pg` error rather than `DatabaseError`, and `instanceof` answered\n * differently depending on whether the call was in a transaction. `pg`\n * exports its own class also named `DatabaseError`, so nothing a developer\n * would check by eye showed the difference (#1115);\n * - they re-exposed `tableExists` and `syncSchema` from the enclosing scope,\n * which close over the *pool*. Both therefore ran on a different connection\n * than the transaction, so `tx.tableExists()` could not see a table created\n * in the same transaction and `tx.syncSchema()` committed its DDL\n * immediately, surviving a rollback (#1111).\n *\n * Binding a client is the only difference between the two, so it is the only\n * thing this factory parameterizes.\n *\n * @param executor - Pool or checked-out client every statement runs on\n * @param inTransaction - Whether `executor` is already inside a transaction\n * @param serialize - Applied to each record before `insert`/`update` builds\n * its SQL\n * @param clearTransactionError - Clears a statement error after a savepoint\n * has successfully restored the transaction to a usable state\n */\n const createClientMethods = (\n executor: PostgresQueryExecutor,\n inTransaction: boolean,\n serialize: (record: Record<string, any>) => Record<string, any>,\n clearTransactionError: () => void = () => {},\n ) => {\n /**\n * Inserts one or more records into a table\n *\n * @param table - Table name\n * @param data - Single record or array of records to insert\n * @returns Promise resolving to operation result\n * @throws Error if the insert operation fails\n *\n * @example Single record insert:\n * ```typescript\n * await db.insert('users', {\n * name: 'John Doe',\n * email: 'john@example.com'\n * });\n * ```\n *\n * @example Multiple record insert:\n * ```typescript\n * await db.insert('users', [\n * { name: 'John', email: 'john@example.com' },\n * { name: 'Jane', email: 'jane@example.com' }\n * ]);\n * ```\n */\n const insert = async (\n table: string,\n data: Record<string, any> | Record<string, any>[],\n ): Promise<BaseQueryResult> => {\n validateTableName(table);\n // If data is an array, we need to handle multiple rows\n if (Array.isArray(data)) {\n if (data.length === 0) {\n return { operation: 'insert', affected: 0 };\n }\n // Serialize all records in the array\n const serializedRecords = data.map((record) => serialize(record));\n const keys = resolveInsertColumns(table, serializedRecords);\n validateColumnNames(keys);\n const placeholders = serializedRecords\n .map(\n (_, i) =>\n `(${keys.map((_, j) => `$${i * keys.length + j + 1}`).join(', ')})`,\n )\n .join(', ');\n const query = `INSERT INTO ${table} (${keys.join(\n ', ',\n )}) VALUES ${placeholders}`;\n // Project through `keys` rather than each record's own key order, so a\n // record whose keys were inserted in a different order still binds each\n // value to its own column.\n const values = serializedRecords.flatMap((row) =>\n keys.map((key) => row[key]),\n );\n const result = await executor.query(query, values);\n return { operation: 'insert', affected: result.rowCount ?? 0 };\n }\n // If data is an object, we handle a single row\n const serializedData = serialize(data);\n const keys = Object.keys(serializedData);\n validateColumnNames(keys);\n const values = Object.values(serializedData);\n const placeholders = keys.map((_, i) => `$${i + 1}`).join(', ');\n const query = `INSERT INTO ${table} (${keys.join(\n ', ',\n )}) VALUES (${placeholders})`;\n const result = await executor.query(query, values);\n return { operation: 'insert', affected: result.rowCount ?? 0 };\n };\n\n /**\n * Retrieves a single record matching the where criteria\n *\n * @param table - Table name\n * @param where - Criteria to match records\n * @returns Promise resolving to query result\n */\n const get = async (\n table: string,\n where: Record<string, any>,\n ): Promise<Record<string, any> | null> => {\n validateTableName(table);\n const { sql: whereClause, values } = buildWhere(where, 1, 'postgres');\n if (!whereClause) {\n throw new DatabaseError(\n 'GET requires at least one WHERE condition to prevent returning an arbitrary record',\n { table },\n );\n }\n\n const query = `SELECT * FROM ${table} ${whereClause}`;\n try {\n const result = await executor.query(query, values);\n return result.rows[0] || null;\n } catch (e) {\n throw new DatabaseError('Failed to retrieve record from table', {\n table,\n sql: query,\n values,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Retrieves multiple records matching the where criteria\n *\n * @param table - Table name\n * @param where - Criteria to match records\n * @returns Promise resolving to array of records\n */\n const list = async (\n table: string,\n where: Record<string, any>,\n ): Promise<Record<string, any>[]> => {\n validateTableName(table);\n const { sql: whereClause, values } = buildWhere(where, 1, 'postgres');\n const query = `SELECT * FROM ${table} ${whereClause}`;\n try {\n const result = await executor.query(query, values);\n return result.rows;\n } catch (e) {\n throw new DatabaseError('Failed to list records from table', {\n table,\n sql: query,\n values,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Updates records matching the where criteria\n *\n * @param table - Table name\n * @param where - Criteria to match records to update\n * @param data - New data to set\n * @returns Promise resolving to operation result\n */\n const update = async (\n table: string,\n where: Record<string, any>,\n data: Record<string, any>,\n ): Promise<BaseQueryResult> => {\n validateTableName(table);\n // Serialize the data to update\n const serializedData = serialize(data);\n const keys = Object.keys(serializedData);\n validateColumnNames(keys);\n const values = Object.values(serializedData);\n const setClause = keys.map((key, i) => `${key} = $${i + 1}`).join(', ');\n const { sql: whereClause, values: whereValues } = buildWhere(\n where,\n values.length + 1,\n 'postgres',\n );\n if (!whereClause) {\n throw new DatabaseError(\n 'UPDATE requires at least one WHERE condition to prevent accidental update of all records',\n { table },\n );\n }\n\n const sql = `UPDATE ${table} SET ${setClause} ${whereClause}`;\n try {\n const result = await executor.query(sql, [...values, ...whereValues]);\n return { operation: 'update', affected: result.rowCount ?? 0 };\n } catch (e) {\n throw new DatabaseError('Failed to update records in table', {\n table,\n sql,\n values: [...values, ...whereValues],\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Inserts a record or updates it if it already exists (UPSERT)\n *\n * @param table - Table name\n * @param conflictColumns - Columns that define the uniqueness constraint\n * @param data - Data to insert or update\n * @returns Promise resolving to operation result\n * @throws Error if the upsert operation fails\n */\n const upsert = async (\n table: string,\n conflictColumns: string[],\n data: Record<string, any>,\n options?: UpsertOptions,\n ): Promise<BaseQueryResult> => {\n validateTableName(table);\n // Snapshot both identifier sources once and validate the snapshots — the\n // exact arrays the executors interpolate — outside the try. `data` is\n // serialized (a plain-object snapshot) and `conflictColumns` is copied,\n // so neither a hostile record nor a hostile conflict-column array can\n // present different identifiers to the check and the SQL renderer. An\n // invalid identifier surfaces by name rather than as the generic wrapper\n // below; PostgreSQL columns are lowercased and quoted after validation.\n const serializedData = serializeRecord(data);\n const conflictCols = [...conflictColumns];\n validateColumnNames([...conflictCols, ...Object.keys(serializedData)]);\n try {\n return await executePostgresUpsert(\n executor,\n table,\n conflictCols,\n serializedData,\n options,\n // A transaction-scoped upsert is already inside a transaction; opening\n // a second one on another pooled connection would deadlock against it.\n !inTransaction,\n );\n } catch (e) {\n if (\n e instanceof DatabaseError &&\n e.message === 'Conflict columns missing from data'\n ) {\n throw e;\n }\n\n throw new DatabaseError('Failed to upsert record into table', {\n table,\n values: data,\n conflictColumns,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Gets a record matching the where criteria or inserts it if not found\n *\n * @param table - Table name\n * @param where - Criteria to match existing record\n * @returns Promise resolving to the query result or insert result\n */\n const getOrInsert = async (\n table: string,\n where: Record<string, any>,\n data: Record<string, any>,\n ): Promise<Record<string, any>> => {\n validateTableName(table);\n const result = await get(table, where);\n if (result) return result;\n await insert(table, data);\n\n const inserted = await get(table, where);\n if (!inserted) {\n throw new DatabaseError('Failed to insert and retrieve record', {\n table,\n where,\n data,\n });\n }\n return inserted;\n };\n\n /**\n * Deletes records from a table matching the where criteria\n *\n * @param table - Table name\n * @param where - Criteria to match records for deletion\n * @returns Promise resolving to operation result with count of deleted rows\n * @throws Error if the delete operation fails\n */\n const deleteRecords = async (\n table: string,\n where: Record<string, any>,\n ): Promise<BaseQueryResult> => {\n validateTableName(table);\n\n const keys = Object.keys(where);\n if (keys.length === 0) {\n throw new DatabaseError(\n 'DELETE requires at least one WHERE condition to prevent accidental deletion of all records',\n { table },\n );\n }\n\n const { sql: whereClause, values } = buildWhere(where, 1, 'postgres');\n\n try {\n const result = await executor.query(\n `DELETE FROM ${table} ${whereClause}`,\n values,\n );\n\n return { operation: 'delete', affected: result.rowCount ?? 0 };\n } catch (e) {\n throw new DatabaseError('Failed to delete records from table', {\n table,\n where,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Counts records in a table matching the where criteria\n *\n * @param table - Table name\n * @param where - Criteria to match records (optional, counts all if omitted)\n * @returns Promise resolving to count of matching records\n * @throws Error if the count operation fails\n */\n const count = async (\n table: string,\n where?: Record<string, any>,\n ): Promise<number> => {\n validateTableName(table);\n\n try {\n if (!where || Object.keys(where).length === 0) {\n // Count all records\n const result = await executor.query(\n `SELECT COUNT(*) as count FROM ${table}`,\n );\n return Number(result.rows[0]?.count) || 0;\n }\n\n // Count with conditions\n const { sql: whereClause, values } = buildWhere(where, 1, 'postgres');\n\n const result = await executor.query(\n `SELECT COUNT(*) as count FROM ${table} ${whereClause}`,\n values,\n );\n\n return Number(result.rows[0]?.count) || 0;\n } catch (e) {\n throw new DatabaseError('Failed to count records in table', {\n table,\n where,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Creates a table-specific interface for simplified table operations\n *\n * @param tableName - Table name\n * @returns TableMethods interface for the specified table\n */\n const table = (tableName: string): TableInterface => {\n return {\n insert: (data) => insert(tableName, data),\n get: (data) => get(tableName, data),\n list: (data) => list(tableName, data),\n };\n };\n\n /**\n * Executes a SQL query using template literals and returns a single value\n *\n * @param strings - Template strings\n * @param vars - Variables to interpolate into the query\n * @returns Promise resolving to a single value (first column of first row)\n */\n const pluck = async (\n strings: TemplateStringsArray,\n ...vars: any[]\n ): Promise<any> => {\n const { sql, values } = parseTemplate(strings, ...vars);\n try {\n const result = await executor.query(sql, values);\n const firstRow = result.rows[0];\n if (!firstRow) return null;\n // Return the first column value from the first row\n return Object.values(firstRow)[0];\n } catch (e) {\n throw new DatabaseError('Failed to execute pluck query', {\n sql,\n values,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Executes a SQL query using template literals and returns a single row\n *\n * @param strings - Template strings\n * @param vars - Variables to interpolate into the query\n * @returns Promise resolving to a single result record or null\n */\n const single = async (\n strings: TemplateStringsArray,\n ...vars: any[]\n ): Promise<Record<string, any> | null> => {\n const { sql, values } = parseTemplate(strings, ...vars);\n try {\n const result = await executor.query(sql, values);\n return result.rows[0] || null;\n } catch (e) {\n throw new DatabaseError('Failed to execute single query', {\n sql,\n values,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Executes a SQL query using template literals and returns multiple rows\n *\n * @param strings - Template strings\n * @param vars - Variables to interpolate into the query\n * @returns Promise resolving to array of result records\n */\n const many = async (\n strings: TemplateStringsArray,\n ...vars: any[]\n ): Promise<Record<string, any>[]> => {\n const { sql, values } = parseTemplate(strings, ...vars);\n try {\n const result = await executor.query(sql, values);\n return result.rows;\n } catch (e) {\n throw new DatabaseError('Failed to execute many query', {\n sql,\n values,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Executes a SQL query using template literals without returning results\n *\n * @param strings - Template strings\n * @param vars - Variables to interpolate into the query\n * @returns Promise that resolves when the query completes\n */\n const execute = async (\n strings: TemplateStringsArray,\n ...vars: any[]\n ): Promise<void> => {\n const { sql, values } = parseTemplate(strings, ...vars);\n try {\n await executor.query(sql, values);\n } catch (e) {\n throw new DatabaseError('Failed to execute query', {\n sql,\n values,\n originalError: formatDbError(e),\n });\n }\n };\n\n /**\n * Executes a raw SQL query with parameterized values\n *\n * Uses PostgreSQL-native placeholders ($1, $2, ...). Legacy ? placeholders\n * are converted only when the placeholder count matches the supplied values,\n * so Postgres operators such as JSONB ? remain intact.\n *\n * @param sql - SQL query string\n * @param values - Variables to use as parameters\n * @returns Promise resolving to query result with rows and count\n */\n const query = async (\n sql: string,\n ...values: any[]\n ): Promise<{ rows: Record<string, any>[]; rowCount: number }> => {\n const query = normalizePostgresRawQuery(sql, values);\n try {\n const result = await executor.query(query.sql, query.values);\n // A successful rollback to a caller-managed savepoint restores the\n // transaction to the state at that savepoint, so any recorded\n // statement failure has been contained and must no longer poison the\n // enclosing commit. This mirrors the adapter-managed savepoint paths.\n return {\n rows: result.rows,\n rowCount: result.rowCount ?? 0,\n };\n } catch (e) {\n throw wrapDatabaseError('Failed to execute raw query', e, {\n sql: query.sql,\n values: query.values,\n });\n }\n };\n\n /**\n * Checks if a table exists in the database\n *\n * @param tableName - Name of the table to check\n * @returns Promise resolving to boolean indicating if the table exists\n */\n const tableExists = async (tableName: string): Promise<boolean> => {\n const result = await executor.query(\n `SELECT EXISTS (\n SELECT 1\n FROM information_schema.tables\n WHERE table_name = $1\n AND table_schema = (\n SELECT namespace.nspname\n FROM pg_catalog.pg_class AS relation\n JOIN pg_catalog.pg_namespace AS namespace\n ON namespace.oid = relation.relnamespace\n WHERE relation.oid = pg_catalog.to_regclass(pg_catalog.quote_ident($1))\n )\n )`,\n [tableName],\n );\n return result.rows[0].exists;\n };\n\n /**\n * Synchronizes database schema with provided SQL DDL\n * Creates tables if they don't exist and adds missing columns\n * Also executes CREATE INDEX statements\n *\n * @param schema - SQL schema definition with CREATE TABLE and CREATE INDEX statements\n * @returns Promise that resolves when schema is synchronized\n */\n /**\n * Runs a step whose failure `syncSchema` deliberately tolerates.\n *\n * Logging and continuing is self-contained on the pool. Inside a\n * transaction it is not: a failed statement puts PostgreSQL in the aborted\n * state, and `COMMIT` on an aborted transaction *succeeds* — it reports a\n * ROLLBACK command tag and no error. The caller is told the transaction\n * committed while every write in it was discarded, which is the silent\n * data loss this whole epic is about, re-entering through the schema path.\n *\n * A savepoint scopes the failure to the step, which is what \"log it and\n * continue\" was always supposed to mean.\n */\n const runTolerated = async <T>(work: () => Promise<T>): Promise<T> => {\n if (!inTransaction) {\n return work();\n }\n savepointSequence += 1;\n const name = `hv_sync_${savepointSequence}`;\n await executor.query(`SAVEPOINT ${name}`);\n try {\n const result = await work();\n await executor.query(`RELEASE SAVEPOINT ${name}`);\n return result;\n } catch (error) {\n // ROLLBACK TO leaves the savepoint defined, so release it too.\n await executor.query(`ROLLBACK TO SAVEPOINT ${name}`);\n clearTransactionError();\n await executor.query(`RELEASE SAVEPOINT ${name}`);\n throw error;\n }\n };\n\n const syncSchema = async (schema: string): Promise<void> => {\n const commands = schema\n .trim()\n .split(';')\n .filter((command) => command.trim() !== '');\n\n // Match CREATE INDEX statements (Issues #867 and #1040).\n // Named groups keep optional clauses from shifting identifier captures.\n const createIndexRegex =\n /CREATE\\s+(?:UNIQUE\\s+)?INDEX\\s+(?:CONCURRENTLY\\s+)?(?:IF\\s+NOT\\s+EXISTS\\s+)?\"?(?<indexName>\\w+)\"?\\s+ON\\s+\"?(?<tableName>\\w+)\"?\\s*(?:USING\\s+\"?\\w+\"?\\s*)?\\([^)]+\\)/i;\n const parseCreateIndex = (\n command: string,\n ): { indexName: string; tableName: string } | null => {\n const { indexName, tableName } =\n command.match(createIndexRegex)?.groups ?? {};\n return indexName && tableName ? { indexName, tableName } : null;\n };\n\n // Pre-scan commands to collect all index names for batch existence check (Issue #798)\n const indexTargets: Array<{ indexName: string; tableName: string }> = [];\n for (const command of commands) {\n const indexMatch = parseCreateIndex(command.trim());\n if (indexMatch) {\n indexTargets.push(indexMatch);\n }\n }\n\n // Resolve each table through the executor's search_path. Index names are\n // only unique within a schema, so a name-only public lookup can suppress\n // a needed index when another schema has the same name.\n const existingIndexes = new Set<string>();\n if (indexTargets.length > 0) {\n const result = await executor.query(\n `SELECT target.table_name, target.index_name\n FROM unnest($1::text[], $2::text[])\n AS target(table_name, index_name)\n JOIN pg_catalog.pg_class AS relation\n ON relation.oid = pg_catalog.to_regclass(pg_catalog.quote_ident(target.table_name))\n JOIN pg_catalog.pg_namespace AS namespace\n ON namespace.oid = relation.relnamespace\n JOIN pg_catalog.pg_indexes AS existing\n ON existing.schemaname = namespace.nspname\n AND existing.tablename = target.table_name\n AND existing.indexname = target.index_name`,\n [\n indexTargets.map((target) => target.tableName),\n indexTargets.map((target) => target.indexName),\n ],\n );\n for (const row of result.rows) {\n existingIndexes.add(`${row.table_name}\\u0000${row.index_name}`);\n }\n }\n\n for (const command of commands) {\n const trimmedCommand = command.trim();\n\n // Match CREATE TABLE with optional quotes around table name\n // Supports: CREATE TABLE foo, CREATE TABLE \"foo\", CREATE TABLE IF NOT EXISTS \"foo\"\n const createTableRegex =\n /CREATE TABLE (IF NOT EXISTS )?\"?(\\w+)\"? \\(([\\s\\S]+)\\)/i;\n const tableMatch = trimmedCommand.match(createTableRegex);\n\n if (tableMatch) {\n const tableName = tableMatch[2];\n const columns = tableMatch[3].trim().split(',\\n');\n\n // Check if table exists\n const exists = await tableExists(tableName);\n\n if (!exists) {\n // Table doesn't exist, create it\n await executor.query(trimmedCommand);\n } else {\n // Table exists, check for missing columns\n for (const column of columns) {\n const columnDef = column.trim();\n // Table constraints are not column definitions. In particular,\n // a quoted constraint name would otherwise let the unanchored\n // column matcher start at that name and generate an invalid\n // ADD COLUMN statement.\n if (\n /^(?:CONSTRAINT\\s+(?:\"(?:[^\"]|\"\")*\"|\\w+)\\s+)?(?:(?:PRIMARY\\s+KEY|FOREIGN\\s+KEY|UNIQUE|CHECK)\\b|EXCLUDE(?=\\s+(?:USING\\b|\\()))/i.test(\n columnDef,\n )\n ) {\n continue;\n }\n // Match column name with optional quotes: \"id\" or id\n const columnMatch = columnDef.match(\n /^(\"(?:[^\"]|\"\")*\"|\\w+)\\s+\\w+[^,]*/,\n );\n\n if (columnMatch) {\n const identifier = columnMatch[1];\n const columnName = identifier.startsWith('\"')\n ? identifier.slice(1, -1).replace(/\"\"/g, '\"')\n : identifier;\n\n // Skip constraint definitions\n if (\n columnName.toUpperCase() === 'PRIMARY' ||\n columnName.toUpperCase() === 'FOREIGN' ||\n columnName.toUpperCase() === 'UNIQUE' ||\n columnName.toUpperCase() === 'CHECK' ||\n columnName.toUpperCase() === 'CONSTRAINT'\n ) {\n continue;\n }\n\n try {\n await runTolerated(async () => {\n // Check if column exists\n const columnExists = await executor.query(\n `SELECT EXISTS (\n SELECT 1 FROM information_schema.columns\n WHERE table_name = $1\n AND column_name = $2\n AND table_schema = (\n SELECT namespace.nspname\n FROM pg_catalog.pg_class AS relation\n JOIN pg_catalog.pg_namespace AS namespace\n ON namespace.oid = relation.relnamespace\n WHERE relation.oid = pg_catalog.to_regclass(pg_catalog.quote_ident($1))\n )\n )`,\n [tableName, columnName],\n );\n\n if (!columnExists.rows[0].exists) {\n // Column doesn't exist, add it\n // Quote the table name for safety\n const alterCommand = `ALTER TABLE \"${tableName}\" ADD COLUMN ${columnDef}`;\n await executor.query(alterCommand);\n }\n });\n } catch (error) {\n // If there's an error checking/adding the column, log it but continue\n console.error(\n `Error adding column ${columnName} to ${tableName}:`,\n error,\n );\n }\n }\n }\n }\n continue;\n }\n\n const indexMatch = parseCreateIndex(trimmedCommand);\n\n if (indexMatch) {\n const { indexName, tableName: indexTableName } = indexMatch;\n\n // Use pre-fetched batch result instead of per-index query\n const indexKey = `${indexTableName}\\u0000${indexName}`;\n if (!existingIndexes.has(indexKey)) {\n try {\n await runTolerated(() => executor.query(trimmedCommand));\n // Track newly created index for idempotency within this call\n existingIndexes.add(indexKey);\n } catch (error) {\n // Log error but continue - index creation failures shouldn't block schema sync\n console.warn(\n `Warning: Failed to create index ${indexName} on ${indexTableName}:`,\n error instanceof Error ? error.message : String(error),\n );\n }\n }\n continue;\n }\n\n // For any other DDL statements (like other CREATE commands), try to execute them\n // This provides forward compatibility for future DDL types\n if (\n trimmedCommand.toUpperCase().startsWith('CREATE ') &&\n !trimmedCommand.toUpperCase().includes('CREATE TABLE')\n ) {\n try {\n await runTolerated(() => executor.query(trimmedCommand));\n } catch (error) {\n // Log but don't fail - the statement may have already been executed\n console.warn(\n `Warning: DDL statement may have failed:`,\n error instanceof Error ? error.message : String(error),\n );\n }\n }\n }\n };\n\n // Shorthand aliases for query methods\n const oo = many; // (o)bjective-(o)bjects: returns multiple rows\n const oO = single; // (o)bjective-(O)bject: returns a single row\n const ox = pluck; // (o)bjective-(x): returns a single value\n const xx = execute; // (x)ecute-(x)ecute: executes without returning\n\n return {\n insert,\n get,\n list,\n update,\n upsert,\n getOrInsert,\n delete: deleteRecords,\n count,\n table,\n many,\n single,\n pluck,\n execute,\n query,\n oo,\n oO,\n ox,\n xx,\n tableExists,\n syncSchema,\n };\n };\n /**\n * Builds the `transaction` exposed on a transaction-scoped interface.\n *\n * Re-entering runs the callback under a SAVEPOINT on the *same* connection,\n * which is what callers assume nesting already did. Re-exposing the top-level\n * `transaction` here (the previous behaviour) checked out a second pooled\n * connection and began an independent transaction, so the nested work could\n * not see the enclosing transaction's uncommitted rows, and if the enclosing\n * transaction held a lock the nested one needed, the two deadlocked in a way\n * PostgreSQL cannot detect: the outer connection is blocked on a promise\n * rather than on a lock, so `deadlock_timeout` never fires and the process\n * hangs until some unrelated timeout.\n *\n * @param executor - Error-preserving executor bound to the enclosing client\n * @param scopeFor - Builds the interface handed to the nested callback\n */\n const createNestedTransaction = (\n executor: PostgresQueryExecutor,\n scopeFor: (override?: NestedTransaction) => DatabaseInterface,\n clearTransactionError: () => void,\n scopes?: NestedScopeContext,\n ) => {\n // PostgreSQL permits nested savepoints, but a sibling savepoint cannot be\n // released while a later sibling is still open: releasing the earlier one\n // implicitly discards the later savepoint. Each scope gets its own queue:\n // child scopes are queued behind their parent, while work inside a child\n // gets a fresh queue for its own children.\n const rootScope: NestedScope = { tail: Promise.resolve() };\n\n const runScope = async <T>(\n scope: NestedScope,\n callback: (tx: DatabaseInterface) => Promise<T>,\n ): Promise<T> => {\n savepointSequence += 1;\n const name = `hv_sp_${savepointSequence}`;\n await executor.query(`SAVEPOINT ${name}`);\n try {\n // Without an ambient scope store the callback gets a handle bound to\n // this scope, which is what routes its own nested work under it.\n const result = await callback(\n scopes ? scopeFor() : scopeFor(bind(scope)),\n );\n // A callback may start nested work without awaiting it. Its savepoint\n // must remain open until that work is finished.\n await scope.tail;\n await executor.query(`RELEASE SAVEPOINT ${name}`);\n return result;\n } catch (error) {\n // Promise.all rejects as soon as one sibling fails, but queued siblings\n // are still tied to this savepoint. Let them finish before unwinding.\n await scope.tail;\n try {\n // ROLLBACK TO leaves the savepoint defined, so release it too or it\n // accumulates for the life of the transaction.\n await executor.query(`ROLLBACK TO SAVEPOINT ${name}`);\n clearTransactionError();\n await executor.query(`RELEASE SAVEPOINT ${name}`);\n } catch {\n // The enclosing transaction is already unwinding; its own teardown\n // owns the connection from here.\n }\n throw error;\n }\n };\n\n const bind = (bound?: NestedScope): NestedTransaction => {\n const nested: NestedTransaction = async <T>(\n callback: (tx: DatabaseInterface) => Promise<T>,\n ): Promise<T> => {\n const parentScope = bound ?? scopes?.getStore() ?? rootScope;\n const scope: NestedScope = { tail: Promise.resolve() };\n const current = parentScope.tail.then(() =>\n scopes\n ? scopes.run(scope, () => runScope(scope, callback))\n : runScope(scope, callback),\n );\n parentScope.tail = current.then(\n () => undefined,\n () => undefined,\n );\n return current;\n };\n nested.drain = () => rootScope.tail;\n return nested;\n };\n return bind();\n };\n\n return { serializeRecord, createClientMethods, createNestedTransaction };\n}\n\n/**\n * Builds `getTableSchema` on top of a dialect's statement methods.\n */\nexport function createGetTableSchema(methods: {\n many: (\n strings: TemplateStringsArray,\n ...vars: any[]\n ) => Promise<Record<string, any>[]>;\n tableExists: (tableName: string) => Promise<boolean>;\n}) {\n const { many, tableExists } = methods;\n /**\n * Retrieves the schema information for a table\n *\n * @param table - Table name\n * @returns Promise resolving to table schema info or null if table doesn't exist\n * @throws Error if the query fails\n */\n const getTableSchema = async (\n table: string,\n ): Promise<TableSchemaInfo | null> => {\n validateTableName(table);\n\n try {\n // Check if table exists\n const exists = await tableExists(table);\n if (!exists) {\n return null;\n }\n\n // Get column information from information_schema\n const columnRows = await many`\n SELECT\n column_name,\n data_type,\n is_nullable,\n column_default\n FROM information_schema.columns\n WHERE table_name = ${table}\n AND table_schema = (\n SELECT namespace.nspname\n FROM pg_catalog.pg_class AS relation\n JOIN pg_catalog.pg_namespace AS namespace\n ON namespace.oid = relation.relnamespace\n WHERE relation.oid = pg_catalog.to_regclass(pg_catalog.quote_ident(${table}))\n )\n ORDER BY ordinal_position\n `;\n\n // Get primary key columns\n const pkRows = await many`\n SELECT kcu.column_name\n FROM information_schema.table_constraints tc\n JOIN information_schema.key_column_usage kcu\n ON tc.constraint_name = kcu.constraint_name\n AND tc.table_schema = kcu.table_schema\n WHERE tc.table_name = ${table}\n AND tc.table_schema = (\n SELECT namespace.nspname\n FROM pg_catalog.pg_class AS relation\n JOIN pg_catalog.pg_namespace AS namespace\n ON namespace.oid = relation.relnamespace\n WHERE relation.oid = pg_catalog.to_regclass(pg_catalog.quote_ident(${table}))\n )\n AND tc.constraint_type = 'PRIMARY KEY'\n `;\n\n const pkColumns = new Set(pkRows.map((row) => row.column_name));\n\n const columns: Record<string, ColumnDefinition> = {};\n for (const row of columnRows) {\n const colName = row.column_name as string;\n columns[colName] = {\n type: row.data_type as string,\n primaryKey: pkColumns.has(colName),\n notNull: row.is_nullable === 'NO',\n defaultValue: row.column_default,\n };\n }\n\n // Get index information from pg_indexes\n const indexRows = await many`\n SELECT\n indexname,\n indexdef\n FROM pg_indexes\n WHERE tablename = ${table}\n AND schemaname = (\n SELECT namespace.nspname\n FROM pg_catalog.pg_class AS relation\n JOIN pg_catalog.pg_namespace AS namespace\n ON namespace.oid = relation.relnamespace\n WHERE relation.oid = pg_catalog.to_regclass(pg_catalog.quote_ident(${table}))\n )\n AND indexname NOT LIKE '%_pkey'\n `;\n\n const indexes: IndexDefinition[] = [];\n for (const row of indexRows) {\n const indexName = row.indexname as string;\n const indexDef = row.indexdef as string;\n\n // Parse column names from index definition\n // Example: CREATE INDEX idx_name ON table (col1, col2)\n const colMatch = indexDef.match(/\\(([^)]+)\\)/);\n const indexColumns = colMatch\n ? colMatch[1].split(',').map((col) => col.trim())\n : [];\n\n const isUnique = indexDef.toUpperCase().includes('UNIQUE');\n\n indexes.push({\n name: indexName,\n columns: indexColumns,\n unique: isUnique,\n });\n }\n\n // Get foreign key information\n const fkRows = await many`\n SELECT\n kcu.column_name,\n ccu.table_name AS foreign_table_name,\n ccu.column_name AS foreign_column_name,\n rc.delete_rule,\n rc.update_rule\n FROM information_schema.table_constraints AS tc\n JOIN information_schema.key_column_usage AS kcu\n ON tc.constraint_name = kcu.constraint_name\n AND tc.table_schema = kcu.table_schema\n JOIN information_schema.constraint_column_usage AS ccu\n ON ccu.constraint_name = tc.constraint_name\n AND ccu.table_schema = tc.table_schema\n JOIN information_schema.referential_constraints AS rc\n ON rc.constraint_name = tc.constraint_name\n AND rc.constraint_schema = tc.table_schema\n WHERE tc.constraint_type = 'FOREIGN KEY'\n AND tc.table_name = ${table}\n AND tc.table_schema = (\n SELECT namespace.nspname\n FROM pg_catalog.pg_class AS relation\n JOIN pg_catalog.pg_namespace AS namespace\n ON namespace.oid = relation.relnamespace\n WHERE relation.oid = pg_catalog.to_regclass(pg_catalog.quote_ident(${table}))\n )\n `;\n\n const foreignKeys: Array<{\n column: string;\n referencesTable: string;\n referencesColumn: string;\n onDelete?: string;\n onUpdate?: string;\n }> = [];\n\n for (const fkRow of fkRows) {\n foreignKeys.push({\n column: fkRow.column_name as string,\n referencesTable: fkRow.foreign_table_name as string,\n referencesColumn: fkRow.foreign_column_name as string,\n onDelete: fkRow.delete_rule as string | undefined,\n onUpdate: fkRow.update_rule as string | undefined,\n });\n }\n\n return {\n tableName: table,\n columns,\n indexes,\n foreignKeys,\n };\n } catch (e) {\n throw new DatabaseError('Failed to retrieve table schema', {\n table,\n originalError: formatDbError(e),\n });\n }\n };\n\n return getTableSchema;\n}\n\n/**\n * Builds the `alterTable` operations on top of a statement executor.\n */\nexport function createAlterTable(client: PostgresQueryExecutor) {\n return {\n /**\n * Adds a new column to an existing table\n *\n * @param table - Table name\n * @param column - Column definition with name\n * @returns Promise that resolves when column is added\n * @throws Error if the alter operation fails\n */\n addColumn: async (\n table: string,\n column: ColumnDefinitionWithName,\n ): Promise<void> => {\n validateTableName(table);\n validateColumnName(column.name);\n\n let sql: string | undefined;\n try {\n sql = generateAddColumnStatement(table, column, 'postgres');\n await client.query(sql);\n } catch (e) {\n throw wrapDatabaseError('Failed to add column to table', e, {\n table,\n column: column.name,\n ...(sql ? { sql } : {}),\n });\n }\n },\n\n /**\n * Adds a new index to an existing table\n *\n * @param table - Table name\n * @param index - Index definition\n * @returns Promise that resolves when index is created\n * @throws Error if the create index operation fails\n */\n addIndex: async (table: string, index: IndexDefinition): Promise<void> => {\n validateTableName(table);\n validateIndexName(index.name);\n\n for (const col of index.columns) {\n validateColumnName(col);\n }\n\n let sql: string | undefined;\n try {\n sql = generateCreateIndexStatement(table, index);\n await client.query(sql);\n } catch (e) {\n throw wrapDatabaseError('Failed to create index on table', e, {\n table,\n index: index.name,\n ...(sql ? { sql } : {}),\n });\n }\n },\n };\n}\n"],"mappings":"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"}