@prisma-next/adapter-postgres 0.3.0-dev.40 → 0.3.0-dev.43

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.
@@ -1,82 +1,7 @@
1
1
  import { C as SQL_CHAR_CODEC_ID, E as SQL_VARCHAR_CODEC_ID, S as PG_VARCHAR_CODEC_ID, T as SQL_INT_CODEC_ID, _ as PG_TIMESTAMPTZ_CODEC_ID, a as PG_FLOAT4_CODEC_ID, b as PG_TIME_CODEC_ID, c as PG_INT2_CODEC_ID, d as PG_INTERVAL_CODEC_ID, f as PG_INT_CODEC_ID, g as PG_TEXT_CODEC_ID, h as PG_NUMERIC_CODEC_ID, i as PG_ENUM_CODEC_ID, l as PG_INT4_CODEC_ID, m as PG_JSON_CODEC_ID, n as PG_BOOL_CODEC_ID, o as PG_FLOAT8_CODEC_ID, p as PG_JSONB_CODEC_ID, r as PG_CHAR_CODEC_ID, s as PG_FLOAT_CODEC_ID, t as PG_BIT_CODEC_ID, u as PG_INT8_CODEC_ID, v as PG_TIMESTAMP_CODEC_ID, w as SQL_FLOAT_CODEC_ID, x as PG_VARBIT_CODEC_ID, y as PG_TIMETZ_CODEC_ID } from "./codec-ids-Bsm9c7ns.mjs";
2
+ import { a as validateEnumValueLength, i as quoteIdentifier, n as escapeLiteral, r as qualifyName } from "./sql-utils-CSfAGEwF.mjs";
2
3
  import { arraysEqual } from "@prisma-next/family-sql/schema-verify";
3
4
 
4
- //#region src/core/sql-utils.ts
5
- /**
6
- * Shared SQL utility functions for the Postgres adapter.
7
- *
8
- * These functions handle safe SQL identifier and literal escaping
9
- * with security validations to prevent injection and encoding issues.
10
- */
11
- /**
12
- * Error thrown when an invalid SQL identifier or literal is detected.
13
- * Boundary layers map this to structured envelopes.
14
- */
15
- var SqlEscapeError = class extends Error {
16
- constructor(message, value, kind) {
17
- super(message);
18
- this.value = value;
19
- this.kind = kind;
20
- this.name = "SqlEscapeError";
21
- }
22
- };
23
- /**
24
- * Maximum length for PostgreSQL identifiers (NAMEDATALEN - 1).
25
- */
26
- const MAX_IDENTIFIER_LENGTH$1 = 63;
27
- /**
28
- * Validates and quotes a PostgreSQL identifier (table, column, type, schema names).
29
- *
30
- * Security validations:
31
- * - Rejects null bytes which could cause truncation or unexpected behavior
32
- * - Rejects empty identifiers
33
- * - Warns on identifiers exceeding PostgreSQL's 63-character limit
34
- *
35
- * @throws {SqlEscapeError} If the identifier contains null bytes or is empty
36
- */
37
- function quoteIdentifier(identifier) {
38
- if (identifier.length === 0) throw new SqlEscapeError("Identifier cannot be empty", identifier, "identifier");
39
- if (identifier.includes("\0")) throw new SqlEscapeError("Identifier cannot contain null bytes", identifier.replace(/\0/g, "\\0"), "identifier");
40
- if (identifier.length > MAX_IDENTIFIER_LENGTH$1) console.warn(`Identifier "${identifier.slice(0, 20)}..." exceeds PostgreSQL's ${MAX_IDENTIFIER_LENGTH$1}-character limit and will be truncated`);
41
- return `"${identifier.replace(/"/g, "\"\"")}"`;
42
- }
43
- /**
44
- * Escapes a string literal for safe use in SQL statements.
45
- *
46
- * Security validations:
47
- * - Rejects null bytes which could cause truncation or unexpected behavior
48
- *
49
- * Note: This assumes PostgreSQL's `standard_conforming_strings` is ON (default since PG 9.1).
50
- * Backslashes are treated as literal characters, not escape sequences.
51
- *
52
- * @throws {SqlEscapeError} If the value contains null bytes
53
- */
54
- function escapeLiteral(value) {
55
- if (value.includes("\0")) throw new SqlEscapeError("Literal value cannot contain null bytes", value.replace(/\0/g, "\\0"), "literal");
56
- return value.replace(/'/g, "''");
57
- }
58
- /**
59
- * Builds a qualified name (schema.object) with proper quoting.
60
- */
61
- function qualifyName(schemaName, objectName) {
62
- return `${quoteIdentifier(schemaName)}.${quoteIdentifier(objectName)}`;
63
- }
64
- /**
65
- * Validates that an enum value doesn't exceed PostgreSQL's label length limit.
66
- *
67
- * PostgreSQL enum labels have a maximum length of NAMEDATALEN-1 (63 bytes by default).
68
- * Unlike identifiers, enum labels that exceed this limit cause an error rather than
69
- * silent truncation.
70
- *
71
- * @param value - The enum value to validate
72
- * @param enumTypeName - Name of the enum type (for error messages)
73
- * @throws {SqlEscapeError} If the value exceeds the maximum length
74
- */
75
- function validateEnumValueLength(value, enumTypeName) {
76
- if (value.length > MAX_IDENTIFIER_LENGTH$1) throw new SqlEscapeError(`Enum value "${value.slice(0, 20)}..." for type "${enumTypeName}" exceeds PostgreSQL's ${MAX_IDENTIFIER_LENGTH$1}-character label limit`, value, "literal");
77
- }
78
-
79
- //#endregion
80
5
  //#region src/core/enum-control-hooks.ts
81
6
  const ENUM_INTROSPECT_QUERY = `
82
7
  SELECT
@@ -992,5 +917,5 @@ const postgresAdapterDescriptorMeta = {
992
917
  };
993
918
 
994
919
  //#endregion
995
- export { escapeLiteral as a, SqlEscapeError as i, expandParameterizedNativeType as n, qualifyName as o, pgEnumControlHooks as r, quoteIdentifier as s, postgresAdapterDescriptorMeta as t };
996
- //# sourceMappingURL=descriptor-meta-D7pxo-wo.mjs.map
920
+ export { expandParameterizedNativeType as n, pgEnumControlHooks as r, postgresAdapterDescriptorMeta as t };
921
+ //# sourceMappingURL=descriptor-meta-ilnFI7bx.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"descriptor-meta-ilnFI7bx.mjs","names":["result: string[]","operations: SqlMigrationPlanOperation<unknown>[]","columns: Array<{ table: string; column: string }>","result: Array<{ table: string; column: string }>","pgEnumControlHooks: CodecControlHooks","types: Record<string, StorageTypeInstance>","LENGTH_CODEC_IDS: Set<string>","TEMPORAL_PRECISION_CODEC_IDS: Set<string>","parameterizedTypeHooks: CodecControlHooks"],"sources":["../src/core/enum-control-hooks.ts","../src/core/json-schema-type-expression.ts","../src/core/parameterized-types.ts","../src/core/descriptor-meta.ts"],"sourcesContent":["import type { CodecControlHooks, SqlMigrationPlanOperation } from '@prisma-next/family-sql/control';\nimport { arraysEqual } from '@prisma-next/family-sql/schema-verify';\nimport type { SqlContract, SqlStorage, StorageTypeInstance } from '@prisma-next/sql-contract/types';\nimport type { SqlSchemaIR } from '@prisma-next/sql-schema-ir/types';\nimport { PG_ENUM_CODEC_ID } from './codec-ids';\nimport { escapeLiteral, qualifyName, quoteIdentifier, validateEnumValueLength } from './sql-utils';\n\n/**\n * Postgres enum control hooks.\n *\n * - Plans enum type operations for migrations\n * - Verifies enum types in schema IR\n * - Introspects enum types from the database\n */\ntype EnumRow = {\n schema_name: string;\n type_name: string;\n values: string[];\n};\n\ntype EnumDiff =\n | { kind: 'unchanged' }\n | { kind: 'add_values'; values: readonly string[] }\n | { kind: 'rebuild'; removedValues: readonly string[] };\n\n// ============================================================================\n// Introspection SQL\n// ============================================================================\n\nconst ENUM_INTROSPECT_QUERY = `\n SELECT\n n.nspname AS schema_name,\n t.typname AS type_name,\n array_agg(e.enumlabel ORDER BY e.enumsortorder) AS values\n FROM pg_type t\n JOIN pg_namespace n ON t.typnamespace = n.oid\n JOIN pg_enum e ON t.oid = e.enumtypid\n WHERE n.nspname = $1\n GROUP BY n.nspname, t.typname\n ORDER BY n.nspname, t.typname\n`;\n\n// ============================================================================\n// Schema Helpers (Simplified)\n// ============================================================================\n\n/**\n * Type guard for string arrays. Used for runtime validation of introspected data.\n */\nfunction isStringArray(value: unknown): value is string[] {\n return Array.isArray(value) && value.every((entry) => typeof entry === 'string');\n}\n\n/**\n * Parses a PostgreSQL array value into a JavaScript string array.\n *\n * PostgreSQL's `pg` library may return `array_agg` results either as:\n * - A JavaScript array (when type parsers are configured)\n * - A string in PostgreSQL array literal format: `{value1,value2,...}`\n *\n * Handles PostgreSQL's quoting rules for array elements:\n * - Elements containing commas, double quotes, backslashes, or whitespace are double-quoted\n * - Inside quoted elements, `\\\"` represents `\"` and `\\\\` represents `\\`\n *\n * @param value - The value to parse (array or PostgreSQL array string)\n * @returns A string array, or null if the value cannot be parsed\n */\nexport function parsePostgresArray(value: unknown): string[] | null {\n if (isStringArray(value)) {\n return value;\n }\n if (typeof value === 'string' && value.startsWith('{') && value.endsWith('}')) {\n const inner = value.slice(1, -1);\n if (inner === '') {\n return [];\n }\n return parseArrayElements(inner);\n }\n return null;\n}\n\nfunction parseArrayElements(input: string): string[] {\n const result: string[] = [];\n let i = 0;\n while (i < input.length) {\n if (input[i] === ',') {\n i++;\n continue;\n }\n if (input[i] === '\"') {\n i++;\n let element = '';\n while (i < input.length && input[i] !== '\"') {\n if (input[i] === '\\\\' && i + 1 < input.length) {\n i++;\n element += input[i];\n } else {\n element += input[i];\n }\n i++;\n }\n i++;\n result.push(element);\n } else {\n const nextComma = input.indexOf(',', i);\n if (nextComma === -1) {\n result.push(input.slice(i).trim());\n i = input.length;\n } else {\n result.push(input.slice(i, nextComma).trim());\n i = nextComma;\n }\n }\n }\n return result;\n}\n\n/**\n * Extracts enum values from a StorageTypeInstance.\n * Returns null if values are missing or invalid.\n */\nfunction getEnumValues(typeInstance: StorageTypeInstance): readonly string[] | null {\n const values = typeInstance.typeParams?.['values'];\n return isStringArray(values) ? values : null;\n}\n\n/**\n * Reads existing enum values from the schema IR for a given native type.\n * Uses optional chaining to simplify navigation through the annotations structure.\n */\nfunction readExistingEnumValues(schema: SqlSchemaIR, nativeType: string): readonly string[] | null {\n // Schema annotations.pg.storageTypes is populated by introspection\n const storageTypes = (schema.annotations?.['pg'] as Record<string, unknown> | undefined)?.[\n 'storageTypes'\n ] as Record<string, StorageTypeInstance> | undefined;\n\n const existing = storageTypes?.[nativeType];\n if (!existing || existing.codecId !== PG_ENUM_CODEC_ID) {\n return null;\n }\n return getEnumValues(existing);\n}\n\n/**\n * Determines what changes are needed to transform existing enum values to desired values.\n *\n * Returns one of:\n * - `unchanged`: No changes needed, values match exactly\n * - `add_values`: New values can be safely appended (PostgreSQL supports this)\n * - `rebuild`: Full enum rebuild required (value removal, reordering, or both)\n *\n * Note: PostgreSQL enums can only have values added (not removed or reordered) without\n * a full type rebuild involving temp type creation and column migration.\n *\n * @param existing - Current enum values in the database\n * @param desired - Target enum values from the contract\n * @returns The type of change required\n */\nfunction determineEnumDiff(existing: readonly string[], desired: readonly string[]): EnumDiff {\n if (arraysEqual(existing, desired)) {\n return { kind: 'unchanged' };\n }\n\n // Use Sets for O(1) lookups instead of O(n) array.includes()\n const existingSet = new Set(existing);\n const desiredSet = new Set(desired);\n\n const missingValues = desired.filter((value) => !existingSet.has(value));\n const removedValues = existing.filter((value) => !desiredSet.has(value));\n const orderMismatch =\n missingValues.length === 0 && removedValues.length === 0 && !arraysEqual(existing, desired);\n\n if (removedValues.length > 0 || orderMismatch) {\n return { kind: 'rebuild', removedValues };\n }\n\n return { kind: 'add_values', values: missingValues };\n}\n\n// ============================================================================\n// SQL Helpers\n// ============================================================================\n\nfunction enumTypeExistsCheck(schemaName: string, typeName: string, exists = true): string {\n const existsClause = exists ? 'EXISTS' : 'NOT EXISTS';\n return `SELECT ${existsClause} (\n SELECT 1\n FROM pg_type t\n JOIN pg_namespace n ON t.typnamespace = n.oid\n WHERE n.nspname = '${escapeLiteral(schemaName)}'\n AND t.typname = '${escapeLiteral(typeName)}'\n)`;\n}\n\n// ============================================================================\n// Operation Builders\n// ============================================================================\n\nfunction buildCreateEnumOperation(\n typeName: string,\n nativeType: string,\n schemaName: string,\n values: readonly string[],\n): SqlMigrationPlanOperation<unknown> {\n // Validate all enum values don't exceed PostgreSQL's label length limit\n for (const value of values) {\n validateEnumValueLength(value, typeName);\n }\n const literalValues = values.map((value) => `'${escapeLiteral(value)}'`).join(', ');\n const qualifiedType = qualifyName(schemaName, nativeType);\n return {\n id: `type.${typeName}`,\n label: `Create type ${typeName}`,\n summary: `Creates enum type ${typeName}`,\n operationClass: 'additive',\n target: { id: 'postgres' },\n precheck: [\n {\n description: `ensure type \"${nativeType}\" does not exist`,\n sql: enumTypeExistsCheck(schemaName, nativeType, false),\n },\n ],\n execute: [\n {\n description: `create type \"${nativeType}\"`,\n sql: `CREATE TYPE ${qualifiedType} AS ENUM (${literalValues})`,\n },\n ],\n postcheck: [\n {\n description: `verify type \"${nativeType}\" exists`,\n sql: enumTypeExistsCheck(schemaName, nativeType),\n },\n ],\n };\n}\n\n/**\n * Computes the optimal position for inserting a new enum value to maintain\n * the desired order relative to existing values.\n *\n * PostgreSQL's `ALTER TYPE ADD VALUE` supports BEFORE/AFTER positioning.\n * This function finds the best reference value by:\n * 1. Looking for the nearest preceding value that already exists\n * 2. Falling back to the nearest following value if no preceding exists\n * 3. Defaulting to end-of-list if no reference is found\n *\n * @param options.desired - The target ordered list of all enum values\n * @param options.desiredIndex - Index of the value being inserted in the desired list\n * @param options.current - Current list of enum values (being built up incrementally)\n * @returns SQL clause (e.g., \" AFTER 'x'\") and insert position for tracking\n */\nfunction computeInsertPosition(options: {\n desired: readonly string[];\n desiredIndex: number;\n current: readonly string[];\n}): { clause: string; insertAt: number } {\n const { desired, desiredIndex, current } = options;\n const currentSet = new Set(current);\n const previous = desired\n .slice(0, desiredIndex)\n .reverse()\n .find((candidate) => currentSet.has(candidate));\n const next = desired.slice(desiredIndex + 1).find((candidate) => currentSet.has(candidate));\n const clause = previous\n ? ` AFTER '${escapeLiteral(previous)}'`\n : next\n ? ` BEFORE '${escapeLiteral(next)}'`\n : '';\n const insertAt = previous\n ? current.indexOf(previous) + 1\n : next\n ? current.indexOf(next)\n : current.length;\n\n return { clause, insertAt };\n}\n\n/**\n * Builds operations to add new enum values to an existing PostgreSQL enum type.\n *\n * Each new value is added with `ALTER TYPE ... ADD VALUE IF NOT EXISTS` for idempotency.\n * Values are inserted in the correct order using BEFORE/AFTER positioning to match\n * the desired final order.\n *\n * This is a safe, non-destructive operation - existing data is not affected.\n *\n * @param options.typeName - Contract-level type name (e.g., 'Role')\n * @param options.nativeType - PostgreSQL type name (e.g., 'role')\n * @param options.schemaName - PostgreSQL schema (e.g., 'public')\n * @param options.desired - Target ordered list of all enum values\n * @param options.existing - Current enum values in the database\n * @returns Array of migration operations to add each missing value\n */\nfunction buildAddValueOperations(options: {\n typeName: string;\n nativeType: string;\n schemaName: string;\n desired: readonly string[];\n existing: readonly string[];\n}): SqlMigrationPlanOperation<unknown>[] {\n const { typeName, nativeType, schemaName } = options;\n const current = [...options.existing];\n const currentSet = new Set(current);\n const operations: SqlMigrationPlanOperation<unknown>[] = [];\n for (let index = 0; index < options.desired.length; index += 1) {\n const value = options.desired[index];\n if (value === undefined) {\n continue;\n }\n if (currentSet.has(value)) {\n continue;\n }\n // Validate the new value doesn't exceed PostgreSQL's label length limit\n validateEnumValueLength(value, typeName);\n const { clause, insertAt } = computeInsertPosition({\n desired: options.desired,\n desiredIndex: index,\n current,\n });\n // Use IF NOT EXISTS for idempotency - safe to re-run after partial failures.\n // Supported in PostgreSQL 9.3+, and we require PostgreSQL 12+.\n operations.push({\n id: `type.${typeName}.value.${value}`,\n label: `Add value ${value} to ${typeName}`,\n summary: `Adds enum value ${value} to ${typeName}`,\n operationClass: 'widening',\n target: { id: 'postgres' },\n precheck: [],\n execute: [\n {\n description: `add value \"${value}\" if not exists`,\n sql: `ALTER TYPE ${qualifyName(schemaName, nativeType)} ADD VALUE IF NOT EXISTS '${escapeLiteral(\n value,\n )}'${clause}`,\n },\n ],\n postcheck: [],\n });\n current.splice(insertAt, 0, value);\n currentSet.add(value);\n }\n return operations;\n}\n\n/**\n * Collects columns using the enum type from the contract (desired state).\n * Used for type-safe reference tracking.\n */\nfunction collectEnumColumnsFromContract(\n contract: SqlContract<SqlStorage>,\n typeName: string,\n nativeType: string,\n): ReadonlyArray<{ table: string; column: string }> {\n const columns: Array<{ table: string; column: string }> = [];\n for (const [tableName, table] of Object.entries(contract.storage.tables)) {\n for (const [columnName, column] of Object.entries(table.columns)) {\n if (\n column.typeRef === typeName ||\n (column.nativeType === nativeType && column.codecId === PG_ENUM_CODEC_ID)\n ) {\n columns.push({ table: tableName, column: columnName });\n }\n }\n }\n return columns;\n}\n\n/**\n * Collects columns using the enum type from the schema IR (live database state).\n * This ensures we find ALL dependent columns, including those added outside the contract\n * (e.g., manual DDL), which is critical for safe enum rebuild operations.\n */\nfunction collectEnumColumnsFromSchema(\n schema: SqlSchemaIR,\n nativeType: string,\n): ReadonlyArray<{ table: string; column: string }> {\n const columns: Array<{ table: string; column: string }> = [];\n for (const [tableName, table] of Object.entries(schema.tables)) {\n for (const [columnName, column] of Object.entries(table.columns)) {\n // Match by nativeType since schema IR doesn't have codecId/typeRef\n if (column.nativeType === nativeType) {\n columns.push({ table: tableName, column: columnName });\n }\n }\n }\n return columns;\n}\n\n/**\n * Collects all columns using the enum type from both contract AND live database.\n * Merges and deduplicates to ensure we migrate ALL dependent columns during rebuild.\n *\n * This is critical for data integrity: if a column exists in the database using\n * this enum but is not in the contract (e.g., added via manual DDL), we must\n * still migrate it to avoid DROP TYPE failures.\n */\nfunction collectAllEnumColumns(\n contract: SqlContract<SqlStorage>,\n schema: SqlSchemaIR,\n typeName: string,\n nativeType: string,\n): ReadonlyArray<{ table: string; column: string }> {\n const contractColumns = collectEnumColumnsFromContract(contract, typeName, nativeType);\n const schemaColumns = collectEnumColumnsFromSchema(schema, nativeType);\n\n // Merge and deduplicate using a Set of \"table.column\" keys\n const seen = new Set<string>();\n const result: Array<{ table: string; column: string }> = [];\n\n for (const col of [...contractColumns, ...schemaColumns]) {\n const key = `${col.table}.${col.column}`;\n if (!seen.has(key)) {\n seen.add(key);\n result.push(col);\n }\n }\n\n // Sort for deterministic operation order\n return result.sort((a, b) => {\n const tableCompare = a.table.localeCompare(b.table);\n return tableCompare !== 0 ? tableCompare : a.column.localeCompare(b.column);\n });\n}\n\n/**\n * Builds a SQL check to verify a column's type matches an expected type.\n */\nfunction columnTypeCheck(options: {\n schemaName: string;\n tableName: string;\n columnName: string;\n expectedType: string;\n}): string {\n return `SELECT EXISTS (\n SELECT 1\n FROM information_schema.columns\n WHERE table_schema = '${escapeLiteral(options.schemaName)}'\n AND table_name = '${escapeLiteral(options.tableName)}'\n AND column_name = '${escapeLiteral(options.columnName)}'\n AND udt_name = '${escapeLiteral(options.expectedType)}'\n)`;\n}\n\n/** PostgreSQL maximum identifier length (NAMEDATALEN - 1) */\nconst MAX_IDENTIFIER_LENGTH = 63;\n\n/** Suffix added to enum type names during rebuild operations */\nconst REBUILD_SUFFIX = '__pn_rebuild';\n\n/**\n * Builds an SQL check to verify no rows contain any of the removed enum values.\n * This prevents data loss during enum rebuild operations.\n *\n * @param schemaName - PostgreSQL schema name\n * @param tableName - Table containing the enum column\n * @param columnName - Column using the enum type\n * @param removedValues - Array of enum values being removed\n * @returns SQL query that returns true if no rows contain removed values\n */\nfunction noRemovedValuesExistCheck(\n schemaName: string,\n tableName: string,\n columnName: string,\n removedValues: readonly string[],\n): string {\n if (removedValues.length === 0) {\n // No values being removed, always passes\n return 'SELECT true';\n }\n const valuesList = removedValues.map((v) => `'${escapeLiteral(v)}'`).join(', ');\n return `SELECT NOT EXISTS (\n SELECT 1 FROM ${qualifyName(schemaName, tableName)}\n WHERE ${quoteIdentifier(columnName)}::text IN (${valuesList})\n LIMIT 1\n)`;\n}\n\n/**\n * Builds a migration operation to recreate a PostgreSQL enum type with updated values.\n *\n * This is required when:\n * - Enum values are removed (PostgreSQL doesn't support direct removal)\n * - Enum values are reordered (PostgreSQL doesn't support reordering)\n *\n * The operation:\n * 1. Creates a new enum type with the desired values (temp name)\n * 2. Migrates all columns to use the new type via text cast\n * 3. Drops the original type\n * 4. Renames the temp type to the original name\n *\n * IMPORTANT: If values are being removed and data exists using those values,\n * the operation will fail at the precheck stage with a clear error message.\n * This prevents silent data loss.\n *\n * @param options.typeName - Contract-level type name\n * @param options.nativeType - PostgreSQL type name\n * @param options.schemaName - PostgreSQL schema\n * @param options.values - Desired final enum values\n * @param options.removedValues - Values being removed (for data loss checks)\n * @param options.contract - Full contract for column discovery\n * @param options.schema - Current schema IR for column discovery\n * @returns Migration operation for full enum rebuild\n */\nfunction buildRecreateEnumOperation(options: {\n typeName: string;\n nativeType: string;\n schemaName: string;\n values: readonly string[];\n removedValues: readonly string[];\n contract: SqlContract<SqlStorage>;\n schema: SqlSchemaIR;\n}): SqlMigrationPlanOperation<unknown> {\n const tempTypeName = `${options.nativeType}${REBUILD_SUFFIX}`;\n\n // Validate temp type name length won't exceed PostgreSQL's 63-character limit.\n // If it would, PostgreSQL silently truncates which could cause conflicts.\n if (tempTypeName.length > MAX_IDENTIFIER_LENGTH) {\n const maxBaseLength = MAX_IDENTIFIER_LENGTH - REBUILD_SUFFIX.length;\n throw new Error(\n `Enum type name \"${options.nativeType}\" is too long for rebuild operation. ` +\n `Maximum length is ${maxBaseLength} characters (type name + \"${REBUILD_SUFFIX}\" suffix ` +\n `must fit within PostgreSQL's ${MAX_IDENTIFIER_LENGTH}-character identifier limit).`,\n );\n }\n\n const qualifiedOriginal = qualifyName(options.schemaName, options.nativeType);\n const qualifiedTemp = qualifyName(options.schemaName, tempTypeName);\n const literalValues = options.values.map((value) => `'${escapeLiteral(value)}'`).join(', ');\n\n // CRITICAL: Collect columns from BOTH contract AND live database.\n // This ensures we migrate ALL dependent columns, including those added\n // outside of Prisma Next (e.g., manual DDL). Without this, DROP TYPE\n // would fail if the database has columns not tracked in the contract.\n const columnRefs = collectAllEnumColumns(\n options.contract,\n options.schema,\n options.typeName,\n options.nativeType,\n );\n\n const alterColumns = columnRefs.map((ref) => ({\n description: `alter ${ref.table}.${ref.column} to ${tempTypeName}`,\n sql: `ALTER TABLE ${qualifyName(options.schemaName, ref.table)}\nALTER COLUMN ${quoteIdentifier(ref.column)}\nTYPE ${qualifiedTemp}\nUSING ${quoteIdentifier(ref.column)}::text::${qualifiedTemp}`,\n }));\n\n // Build postchecks to verify:\n // 1. The final type exists with the correct name\n // 2. The temp type was cleaned up (renamed away)\n // 3. All migrated columns now reference the final type\n const postchecks = [\n {\n description: `verify type \"${options.nativeType}\" exists`,\n sql: enumTypeExistsCheck(options.schemaName, options.nativeType),\n },\n {\n description: `verify temp type \"${tempTypeName}\" was removed`,\n sql: enumTypeExistsCheck(options.schemaName, tempTypeName, false),\n },\n // Verify each column was successfully migrated to the final type\n ...columnRefs.map((ref) => ({\n description: `verify ${ref.table}.${ref.column} uses type \"${options.nativeType}\"`,\n sql: columnTypeCheck({\n schemaName: options.schemaName,\n tableName: ref.table,\n columnName: ref.column,\n expectedType: options.nativeType,\n }),\n })),\n ];\n\n return {\n id: `type.${options.typeName}.rebuild`,\n label: `Rebuild type ${options.typeName}`,\n summary: `Recreates enum type ${options.typeName} with updated values`,\n operationClass: 'destructive',\n target: { id: 'postgres' },\n precheck: [\n {\n description: `ensure type \"${options.nativeType}\" exists`,\n sql: enumTypeExistsCheck(options.schemaName, options.nativeType),\n },\n // Note: We don't precheck that temp type doesn't exist because we handle\n // orphaned temp types in the execute step below.\n\n // CRITICAL: If values are being removed, verify no data exists using those values.\n // This prevents silent data loss during the rebuild - the USING cast would fail\n // at runtime if rows contain values that don't exist in the new enum.\n ...(options.removedValues.length > 0\n ? columnRefs.map((ref) => ({\n description: `ensure no rows in ${ref.table}.${ref.column} contain removed values (${options.removedValues.join(', ')})`,\n sql: noRemovedValuesExistCheck(\n options.schemaName,\n ref.table,\n ref.column,\n options.removedValues,\n ),\n }))\n : []),\n ],\n execute: [\n // Clean up any orphaned temp type from a previous failed migration.\n // This makes the operation recoverable without manual intervention.\n // DROP TYPE IF EXISTS is safe - it's a no-op if the type doesn't exist.\n {\n description: `drop orphaned temp type \"${tempTypeName}\" if exists`,\n sql: `DROP TYPE IF EXISTS ${qualifiedTemp}`,\n },\n {\n description: `create temp type \"${tempTypeName}\"`,\n sql: `CREATE TYPE ${qualifiedTemp} AS ENUM (${literalValues})`,\n },\n ...alterColumns,\n {\n description: `drop type \"${options.nativeType}\"`,\n sql: `DROP TYPE ${qualifiedOriginal}`,\n },\n {\n description: `rename type \"${tempTypeName}\" to \"${options.nativeType}\"`,\n sql: `ALTER TYPE ${qualifiedTemp} RENAME TO ${quoteIdentifier(options.nativeType)}`,\n },\n ],\n postcheck: postchecks,\n };\n}\n\n// ============================================================================\n// Codec Control Hooks\n// ============================================================================\n\n/**\n * Postgres enum hooks for planning, verifying, and introspecting `storage.types`.\n */\nexport const pgEnumControlHooks: CodecControlHooks = {\n planTypeOperations: ({ typeName, typeInstance, contract, schema, schemaName }) => {\n const desired = getEnumValues(typeInstance);\n if (!desired || desired.length === 0) {\n return { operations: [] };\n }\n\n const schemaNamespace = schemaName ?? 'public';\n const existing = readExistingEnumValues(schema, typeInstance.nativeType);\n if (!existing) {\n return {\n operations: [\n buildCreateEnumOperation(typeName, typeInstance.nativeType, schemaNamespace, desired),\n ],\n };\n }\n\n const diff = determineEnumDiff(existing, desired);\n if (diff.kind === 'unchanged') {\n return { operations: [] };\n }\n\n if (diff.kind === 'rebuild') {\n return {\n operations: [\n buildRecreateEnumOperation({\n typeName,\n nativeType: typeInstance.nativeType,\n schemaName: schemaNamespace,\n values: desired,\n removedValues: diff.removedValues,\n contract,\n schema,\n }),\n ],\n };\n }\n\n return {\n operations: buildAddValueOperations({\n typeName,\n nativeType: typeInstance.nativeType,\n schemaName: schemaNamespace,\n desired,\n existing,\n }),\n };\n },\n verifyType: ({ typeName, typeInstance, schema }) => {\n const desired = getEnumValues(typeInstance);\n if (!desired) {\n return [];\n }\n const existing = readExistingEnumValues(schema, typeInstance.nativeType);\n if (!existing) {\n return [\n {\n kind: 'type_missing',\n table: '',\n typeName,\n message: `Type \"${typeName}\" is missing from database`,\n },\n ];\n }\n if (!arraysEqual(existing, desired)) {\n return [\n {\n kind: 'type_values_mismatch',\n table: '',\n typeName,\n expected: desired.join(', '),\n actual: existing.join(', '),\n message: `Type \"${typeName}\" values do not match contract`,\n },\n ];\n }\n return [];\n },\n introspectTypes: async ({ driver, schemaName }) => {\n const namespace = schemaName ?? 'public';\n const result = await driver.query<EnumRow>(ENUM_INTROSPECT_QUERY, [namespace]);\n const types: Record<string, StorageTypeInstance> = {};\n for (const row of result.rows) {\n const values = parsePostgresArray(row.values);\n if (!values) {\n throw new Error(\n `Failed to parse enum values for type \"${row.type_name}\": ` +\n `unexpected format: ${JSON.stringify(row.values)}`,\n );\n }\n types[row.type_name] = {\n codecId: PG_ENUM_CODEC_ID,\n nativeType: row.type_name,\n typeParams: { values },\n };\n }\n return types;\n },\n};\n","type JsonSchemaRecord = Record<string, unknown>;\n\nconst MAX_DEPTH = 32;\n\nfunction isRecord(value: unknown): value is JsonSchemaRecord {\n return typeof value === 'object' && value !== null;\n}\n\nfunction escapeStringLiteral(str: string): string {\n return str\n .replace(/\\\\/g, '\\\\\\\\')\n .replace(/'/g, \"\\\\'\")\n .replace(/\\n/g, '\\\\n')\n .replace(/\\r/g, '\\\\r');\n}\n\nfunction quotePropertyKey(key: string): string {\n return /^[A-Za-z_$][A-Za-z0-9_$]*$/.test(key) ? key : `'${escapeStringLiteral(key)}'`;\n}\n\nfunction renderLiteral(value: unknown): string {\n if (typeof value === 'string') {\n return `'${escapeStringLiteral(value)}'`;\n }\n if (typeof value === 'number' || typeof value === 'boolean') {\n return String(value);\n }\n if (value === null) {\n return 'null';\n }\n return 'unknown';\n}\n\nfunction renderUnion(items: readonly unknown[], depth: number): string {\n const rendered = items.map((item) => render(item, depth));\n return rendered.join(' | ');\n}\n\nfunction renderObjectType(schema: JsonSchemaRecord, depth: number): string {\n const properties = isRecord(schema['properties']) ? schema['properties'] : {};\n const required = Array.isArray(schema['required'])\n ? new Set(schema['required'].filter((key): key is string => typeof key === 'string'))\n : new Set<string>();\n const keys = Object.keys(properties).sort((left, right) => left.localeCompare(right));\n\n if (keys.length === 0) {\n const additionalProperties = schema['additionalProperties'];\n if (additionalProperties === true || additionalProperties === undefined) {\n return 'Record<string, unknown>';\n }\n return `Record<string, ${render(additionalProperties, depth)}>`;\n }\n\n const renderedProperties = keys.map((key) => {\n const valueSchema = (properties as JsonSchemaRecord)[key];\n const optionalMarker = required.has(key) ? '' : '?';\n return `${quotePropertyKey(key)}${optionalMarker}: ${render(valueSchema, depth)}`;\n });\n\n return `{ ${renderedProperties.join('; ')} }`;\n}\n\nfunction renderArrayType(schema: JsonSchemaRecord, depth: number): string {\n if (Array.isArray(schema['items'])) {\n return `readonly [${schema['items'].map((item) => render(item, depth)).join(', ')}]`;\n }\n\n if (schema['items'] !== undefined) {\n const itemType = render(schema['items'], depth);\n const needsParens = itemType.includes(' | ') || itemType.includes(' & ');\n return needsParens ? `(${itemType})[]` : `${itemType}[]`;\n }\n\n return 'unknown[]';\n}\n\nfunction render(schema: unknown, depth: number): string {\n if (depth > MAX_DEPTH || !isRecord(schema)) {\n return 'JsonValue';\n }\n\n const nextDepth = depth + 1;\n\n if ('const' in schema) {\n return renderLiteral(schema['const']);\n }\n\n if (Array.isArray(schema['enum'])) {\n return schema['enum'].map((value) => renderLiteral(value)).join(' | ');\n }\n\n if (Array.isArray(schema['oneOf'])) {\n return renderUnion(schema['oneOf'], nextDepth);\n }\n\n if (Array.isArray(schema['anyOf'])) {\n return renderUnion(schema['anyOf'], nextDepth);\n }\n\n if (Array.isArray(schema['allOf'])) {\n return schema['allOf'].map((item) => render(item, nextDepth)).join(' & ');\n }\n\n if (Array.isArray(schema['type'])) {\n return schema['type'].map((item) => render({ ...schema, type: item }, nextDepth)).join(' | ');\n }\n\n switch (schema['type']) {\n case 'string':\n return 'string';\n case 'number':\n case 'integer':\n return 'number';\n case 'boolean':\n return 'boolean';\n case 'null':\n return 'null';\n case 'array':\n return renderArrayType(schema, nextDepth);\n case 'object':\n return renderObjectType(schema, nextDepth);\n default:\n break;\n }\n\n return 'JsonValue';\n}\n\nexport function renderTypeScriptTypeFromJsonSchema(schema: unknown): string {\n return render(schema, 0);\n}\n","/**\n * Shared utility for expanding parameterized Postgres types to their full SQL representation.\n *\n * This module provides a single source of truth for type expansion logic, used by:\n * - Schema verification (verify-sql-schema.ts) via the expandNativeType codec control hook\n * - Migration planner (planner.ts) via direct import\n *\n * @module\n */\n\nimport {\n PG_BIT_CODEC_ID,\n PG_CHAR_CODEC_ID,\n PG_INTERVAL_CODEC_ID,\n PG_NUMERIC_CODEC_ID,\n PG_TIME_CODEC_ID,\n PG_TIMESTAMP_CODEC_ID,\n PG_TIMESTAMPTZ_CODEC_ID,\n PG_TIMETZ_CODEC_ID,\n PG_VARBIT_CODEC_ID,\n PG_VARCHAR_CODEC_ID,\n SQL_CHAR_CODEC_ID,\n SQL_VARCHAR_CODEC_ID,\n} from './codec-ids';\n\n/**\n * Input for expanding parameterized native types.\n */\nexport interface ExpandNativeTypeInput {\n readonly nativeType: string;\n readonly codecId?: string;\n readonly typeParams?: Record<string, unknown>;\n}\n\n/** Set of codec IDs that use the 'length' parameter */\nconst LENGTH_CODEC_IDS: Set<string> = new Set([\n SQL_CHAR_CODEC_ID,\n SQL_VARCHAR_CODEC_ID,\n PG_CHAR_CODEC_ID,\n PG_VARCHAR_CODEC_ID,\n PG_BIT_CODEC_ID,\n PG_VARBIT_CODEC_ID,\n]);\n\n/** Set of codec IDs that use the 'precision' parameter for temporal types */\nconst TEMPORAL_PRECISION_CODEC_IDS: Set<string> = new Set([\n PG_TIMESTAMP_CODEC_ID,\n PG_TIMESTAMPTZ_CODEC_ID,\n PG_TIME_CODEC_ID,\n PG_TIMETZ_CODEC_ID,\n PG_INTERVAL_CODEC_ID,\n]);\n\n/**\n * Validates that a value is a valid type parameter number.\n * Type parameters must be finite, non-negative integers.\n */\nfunction isValidTypeParamNumber(value: unknown): value is number {\n return (\n typeof value === 'number' && Number.isFinite(value) && Number.isInteger(value) && value >= 0\n );\n}\n\n/**\n * Expands a parameterized native type to its full SQL representation.\n *\n * For example:\n * - { nativeType: 'character varying', typeParams: { length: 255 } } -> 'character varying(255)'\n * - { nativeType: 'numeric', typeParams: { precision: 10, scale: 2 } } -> 'numeric(10,2)'\n * - { nativeType: 'timestamp without time zone', typeParams: { precision: 3 } } -> 'timestamp without time zone(3)'\n *\n * Returns the original nativeType if:\n * - No typeParams are provided\n * - No codecId is provided\n * - The codecId is not a known parameterized type\n * - The typeParams values are invalid\n */\nexport function expandParameterizedNativeType(input: ExpandNativeTypeInput): string {\n const { nativeType, codecId, typeParams } = input;\n\n if (!typeParams || !codecId) {\n return nativeType;\n }\n\n // Length-parameterized types: char, varchar, bit, varbit\n if (LENGTH_CODEC_IDS.has(codecId)) {\n const length = typeParams['length'];\n if (isValidTypeParamNumber(length)) {\n return `${nativeType}(${length})`;\n }\n return nativeType;\n }\n\n // Numeric with precision and optional scale\n if (codecId === PG_NUMERIC_CODEC_ID) {\n const precision = typeParams['precision'];\n const scale = typeParams['scale'];\n\n if (isValidTypeParamNumber(precision)) {\n if (isValidTypeParamNumber(scale)) {\n return `${nativeType}(${precision},${scale})`;\n }\n return `${nativeType}(${precision})`;\n }\n return nativeType;\n }\n\n // Temporal types with precision: timestamp, timestamptz, time, timetz, interval\n if (TEMPORAL_PRECISION_CODEC_IDS.has(codecId)) {\n const precision = typeParams['precision'];\n if (isValidTypeParamNumber(precision)) {\n return `${nativeType}(${precision})`;\n }\n return nativeType;\n }\n\n return nativeType;\n}\n","import type { CodecControlHooks } from '@prisma-next/family-sql/control';\nimport {\n PG_BIT_CODEC_ID,\n PG_BOOL_CODEC_ID,\n PG_CHAR_CODEC_ID,\n PG_ENUM_CODEC_ID,\n PG_FLOAT_CODEC_ID,\n PG_FLOAT4_CODEC_ID,\n PG_FLOAT8_CODEC_ID,\n PG_INT_CODEC_ID,\n PG_INT2_CODEC_ID,\n PG_INT4_CODEC_ID,\n PG_INT8_CODEC_ID,\n PG_INTERVAL_CODEC_ID,\n PG_JSON_CODEC_ID,\n PG_JSONB_CODEC_ID,\n PG_NUMERIC_CODEC_ID,\n PG_TEXT_CODEC_ID,\n PG_TIME_CODEC_ID,\n PG_TIMESTAMP_CODEC_ID,\n PG_TIMESTAMPTZ_CODEC_ID,\n PG_TIMETZ_CODEC_ID,\n PG_VARBIT_CODEC_ID,\n PG_VARCHAR_CODEC_ID,\n SQL_CHAR_CODEC_ID,\n SQL_FLOAT_CODEC_ID,\n SQL_INT_CODEC_ID,\n SQL_VARCHAR_CODEC_ID,\n} from './codec-ids';\nimport { pgEnumControlHooks } from './enum-control-hooks';\nimport { renderTypeScriptTypeFromJsonSchema } from './json-schema-type-expression';\nimport { expandParameterizedNativeType } from './parameterized-types';\n\n// ============================================================================\n// Helper functions for reducing boilerplate\n// ============================================================================\n\n/** Creates a type import spec for codec types */\nconst codecTypeImport = (named: string) =>\n ({\n package: '@prisma-next/adapter-postgres/codec-types',\n named,\n alias: named,\n }) as const;\n\n/** Creates a precision-based TypeScript type renderer for temporal types */\nconst precisionRenderer = (typeName: string) =>\n ({\n kind: 'function',\n render: (params: Record<string, unknown>) => {\n const precision = params['precision'];\n return typeof precision === 'number' ? `${typeName}<${precision}>` : typeName;\n },\n }) as const;\n\n/** Creates control hooks with just expandNativeType for parameterized types */\nconst parameterizedTypeHooks: CodecControlHooks = {\n expandNativeType: expandParameterizedNativeType,\n};\n\n/**\n * Validates that a type expression string is safe to embed in generated .d.ts files.\n * Rejects expressions containing patterns that could inject executable code.\n */\nfunction isSafeTypeExpression(expr: string): boolean {\n return !/import\\s*\\(|require\\s*\\(|declare\\s|export\\s|eval\\s*\\(/.test(expr);\n}\n\nfunction renderJsonTypeExpression(params: Record<string, unknown>): string {\n const typeName = params['type'];\n if (typeof typeName === 'string' && typeName.trim().length > 0) {\n const trimmed = typeName.trim();\n if (!isSafeTypeExpression(trimmed)) {\n return 'JsonValue';\n }\n return trimmed;\n }\n const schema = params['schemaJson'];\n if (schema && typeof schema === 'object') {\n const rendered = renderTypeScriptTypeFromJsonSchema(schema);\n if (!isSafeTypeExpression(rendered)) {\n return 'JsonValue';\n }\n return rendered;\n }\n return 'JsonValue';\n}\n\n// ============================================================================\n// Descriptor metadata\n// ============================================================================\n\nexport const postgresAdapterDescriptorMeta = {\n kind: 'adapter',\n familyId: 'sql',\n targetId: 'postgres',\n id: 'postgres',\n version: '0.0.1',\n capabilities: {\n postgres: {\n orderBy: true,\n limit: true,\n lateral: true,\n jsonAgg: true,\n returning: true,\n },\n sql: {\n enums: true,\n },\n },\n types: {\n codecTypes: {\n import: {\n package: '@prisma-next/adapter-postgres/codec-types',\n named: 'CodecTypes',\n alias: 'PgTypes',\n },\n parameterized: {\n [SQL_CHAR_CODEC_ID]: 'Char<{{length}}>',\n [SQL_VARCHAR_CODEC_ID]: 'Varchar<{{length}}>',\n [PG_CHAR_CODEC_ID]: 'Char<{{length}}>',\n [PG_VARCHAR_CODEC_ID]: 'Varchar<{{length}}>',\n [PG_NUMERIC_CODEC_ID]: {\n kind: 'function',\n render: (params: Record<string, unknown>) => {\n const precision = params['precision'];\n if (typeof precision !== 'number') {\n throw new Error('pg/numeric@1 renderer expects precision');\n }\n const scale = params['scale'];\n return typeof scale === 'number'\n ? `Numeric<${precision}, ${scale}>`\n : `Numeric<${precision}>`;\n },\n },\n [PG_BIT_CODEC_ID]: 'Bit<{{length}}>',\n [PG_VARBIT_CODEC_ID]: 'VarBit<{{length}}>',\n [PG_TIMESTAMP_CODEC_ID]: precisionRenderer('Timestamp'),\n [PG_TIMESTAMPTZ_CODEC_ID]: precisionRenderer('Timestamptz'),\n [PG_TIME_CODEC_ID]: precisionRenderer('Time'),\n [PG_TIMETZ_CODEC_ID]: precisionRenderer('Timetz'),\n [PG_INTERVAL_CODEC_ID]: precisionRenderer('Interval'),\n [PG_ENUM_CODEC_ID]: {\n kind: 'function',\n render: (params: Record<string, unknown>) => {\n const values = params['values'];\n if (!Array.isArray(values)) {\n throw new Error('pg/enum@1 renderer expects values array');\n }\n return values.map((value) => `'${String(value).replace(/'/g, \"\\\\'\")}'`).join(' | ');\n },\n },\n [PG_JSON_CODEC_ID]: {\n kind: 'function',\n render: renderJsonTypeExpression,\n },\n [PG_JSONB_CODEC_ID]: {\n kind: 'function',\n render: renderJsonTypeExpression,\n },\n },\n typeImports: [\n {\n package: '@prisma-next/adapter-postgres/codec-types',\n named: 'JsonValue',\n alias: 'JsonValue',\n },\n codecTypeImport('Char'),\n codecTypeImport('Varchar'),\n codecTypeImport('Numeric'),\n codecTypeImport('Bit'),\n codecTypeImport('VarBit'),\n codecTypeImport('Timestamp'),\n codecTypeImport('Timestamptz'),\n codecTypeImport('Time'),\n codecTypeImport('Timetz'),\n codecTypeImport('Interval'),\n ],\n controlPlaneHooks: {\n [SQL_CHAR_CODEC_ID]: parameterizedTypeHooks,\n [SQL_VARCHAR_CODEC_ID]: parameterizedTypeHooks,\n [PG_CHAR_CODEC_ID]: parameterizedTypeHooks,\n [PG_VARCHAR_CODEC_ID]: parameterizedTypeHooks,\n [PG_NUMERIC_CODEC_ID]: parameterizedTypeHooks,\n [PG_BIT_CODEC_ID]: parameterizedTypeHooks,\n [PG_VARBIT_CODEC_ID]: parameterizedTypeHooks,\n [PG_TIMESTAMP_CODEC_ID]: parameterizedTypeHooks,\n [PG_TIMESTAMPTZ_CODEC_ID]: parameterizedTypeHooks,\n [PG_TIME_CODEC_ID]: parameterizedTypeHooks,\n [PG_TIMETZ_CODEC_ID]: parameterizedTypeHooks,\n [PG_INTERVAL_CODEC_ID]: parameterizedTypeHooks,\n [PG_ENUM_CODEC_ID]: pgEnumControlHooks,\n },\n },\n storage: [\n { typeId: PG_TEXT_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'text' },\n { typeId: SQL_CHAR_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'character' },\n {\n typeId: SQL_VARCHAR_CODEC_ID,\n familyId: 'sql',\n targetId: 'postgres',\n nativeType: 'character varying',\n },\n { typeId: SQL_INT_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'int4' },\n { typeId: SQL_FLOAT_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'float8' },\n { typeId: PG_CHAR_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'character' },\n {\n typeId: PG_VARCHAR_CODEC_ID,\n familyId: 'sql',\n targetId: 'postgres',\n nativeType: 'character varying',\n },\n { typeId: PG_INT_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'int4' },\n { typeId: PG_FLOAT_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'float8' },\n { typeId: PG_INT4_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'int4' },\n { typeId: PG_INT2_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'int2' },\n { typeId: PG_INT8_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'int8' },\n { typeId: PG_FLOAT4_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'float4' },\n { typeId: PG_FLOAT8_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'float8' },\n { typeId: PG_NUMERIC_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'numeric' },\n {\n typeId: PG_TIMESTAMP_CODEC_ID,\n familyId: 'sql',\n targetId: 'postgres',\n nativeType: 'timestamp',\n },\n {\n typeId: PG_TIMESTAMPTZ_CODEC_ID,\n familyId: 'sql',\n targetId: 'postgres',\n nativeType: 'timestamptz',\n },\n { typeId: PG_TIME_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'time' },\n { typeId: PG_TIMETZ_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'timetz' },\n { typeId: PG_BOOL_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'bool' },\n { typeId: PG_BIT_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'bit' },\n {\n typeId: PG_VARBIT_CODEC_ID,\n familyId: 'sql',\n targetId: 'postgres',\n nativeType: 'bit varying',\n },\n {\n typeId: PG_INTERVAL_CODEC_ID,\n familyId: 'sql',\n targetId: 'postgres',\n nativeType: 'interval',\n },\n { typeId: PG_JSON_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'json' },\n { typeId: PG_JSONB_CODEC_ID, familyId: 'sql', targetId: 'postgres', nativeType: 'jsonb' },\n ],\n },\n} as const;\n"],"mappings":"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"}
@@ -1,4 +1,4 @@
1
- import { c as PostgresContract, l as PostgresLoweredStatement } from "./types-BY395pUv.mjs";
1
+ import { c as PostgresContract, l as PostgresLoweredStatement } from "./types-CXO7EB60.mjs";
2
2
  import { Adapter, QueryAst } from "@prisma-next/sql-relational-core/ast";
3
3
  import { RuntimeAdapterInstance } from "@prisma-next/core-execution-plane/types";
4
4
  import { SqlRuntimeAdapterDescriptor } from "@prisma-next/sql-runtime";
package/dist/runtime.mjs CHANGED
@@ -1,7 +1,7 @@
1
1
  import { m as PG_JSON_CODEC_ID, p as PG_JSONB_CODEC_ID } from "./codec-ids-Bsm9c7ns.mjs";
2
- import { t as codecDefinitions } from "./codecs-DcC1nPzh.mjs";
3
- import { t as createPostgresAdapter } from "./adapter-DB1CK2jM.mjs";
4
- import { t as postgresAdapterDescriptorMeta } from "./descriptor-meta-D7pxo-wo.mjs";
2
+ import { t as codecDefinitions } from "./codecs-BfC_5c-4.mjs";
3
+ import { t as createPostgresAdapter } from "./adapter-B5uYhMy7.mjs";
4
+ import { t as postgresAdapterDescriptorMeta } from "./descriptor-meta-ilnFI7bx.mjs";
5
5
  import { createCodecRegistry } from "@prisma-next/sql-relational-core/ast";
6
6
  import { type } from "arktype";
7
7
  import Ajv from "ajv";
@@ -0,0 +1,78 @@
1
+ //#region src/core/sql-utils.ts
2
+ /**
3
+ * Shared SQL utility functions for the Postgres adapter.
4
+ *
5
+ * These functions handle safe SQL identifier and literal escaping
6
+ * with security validations to prevent injection and encoding issues.
7
+ */
8
+ /**
9
+ * Error thrown when an invalid SQL identifier or literal is detected.
10
+ * Boundary layers map this to structured envelopes.
11
+ */
12
+ var SqlEscapeError = class extends Error {
13
+ constructor(message, value, kind) {
14
+ super(message);
15
+ this.value = value;
16
+ this.kind = kind;
17
+ this.name = "SqlEscapeError";
18
+ }
19
+ };
20
+ /**
21
+ * Maximum length for PostgreSQL identifiers (NAMEDATALEN - 1).
22
+ */
23
+ const MAX_IDENTIFIER_LENGTH = 63;
24
+ /**
25
+ * Validates and quotes a PostgreSQL identifier (table, column, type, schema names).
26
+ *
27
+ * Security validations:
28
+ * - Rejects null bytes which could cause truncation or unexpected behavior
29
+ * - Rejects empty identifiers
30
+ * - Warns on identifiers exceeding PostgreSQL's 63-character limit
31
+ *
32
+ * @throws {SqlEscapeError} If the identifier contains null bytes or is empty
33
+ */
34
+ function quoteIdentifier(identifier) {
35
+ if (identifier.length === 0) throw new SqlEscapeError("Identifier cannot be empty", identifier, "identifier");
36
+ if (identifier.includes("\0")) throw new SqlEscapeError("Identifier cannot contain null bytes", identifier.replace(/\0/g, "\\0"), "identifier");
37
+ if (identifier.length > MAX_IDENTIFIER_LENGTH) console.warn(`Identifier "${identifier.slice(0, 20)}..." exceeds PostgreSQL's ${MAX_IDENTIFIER_LENGTH}-character limit and will be truncated`);
38
+ return `"${identifier.replace(/"/g, "\"\"")}"`;
39
+ }
40
+ /**
41
+ * Escapes a string literal for safe use in SQL statements.
42
+ *
43
+ * Security validations:
44
+ * - Rejects null bytes which could cause truncation or unexpected behavior
45
+ *
46
+ * Note: This assumes PostgreSQL's `standard_conforming_strings` is ON (default since PG 9.1).
47
+ * Backslashes are treated as literal characters, not escape sequences.
48
+ *
49
+ * @throws {SqlEscapeError} If the value contains null bytes
50
+ */
51
+ function escapeLiteral(value) {
52
+ if (value.includes("\0")) throw new SqlEscapeError("Literal value cannot contain null bytes", value.replace(/\0/g, "\\0"), "literal");
53
+ return value.replace(/'/g, "''");
54
+ }
55
+ /**
56
+ * Builds a qualified name (schema.object) with proper quoting.
57
+ */
58
+ function qualifyName(schemaName, objectName) {
59
+ return `${quoteIdentifier(schemaName)}.${quoteIdentifier(objectName)}`;
60
+ }
61
+ /**
62
+ * Validates that an enum value doesn't exceed PostgreSQL's label length limit.
63
+ *
64
+ * PostgreSQL enum labels have a maximum length of NAMEDATALEN-1 (63 bytes by default).
65
+ * Unlike identifiers, enum labels that exceed this limit cause an error rather than
66
+ * silent truncation.
67
+ *
68
+ * @param value - The enum value to validate
69
+ * @param enumTypeName - Name of the enum type (for error messages)
70
+ * @throws {SqlEscapeError} If the value exceeds the maximum length
71
+ */
72
+ function validateEnumValueLength(value, enumTypeName) {
73
+ if (value.length > MAX_IDENTIFIER_LENGTH) throw new SqlEscapeError(`Enum value "${value.slice(0, 20)}..." for type "${enumTypeName}" exceeds PostgreSQL's ${MAX_IDENTIFIER_LENGTH}-character label limit`, value, "literal");
74
+ }
75
+
76
+ //#endregion
77
+ export { validateEnumValueLength as a, quoteIdentifier as i, escapeLiteral as n, qualifyName as r, SqlEscapeError as t };
78
+ //# sourceMappingURL=sql-utils-CSfAGEwF.mjs.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sql-utils-CSfAGEwF.mjs","names":["value: string","kind: 'identifier' | 'literal'"],"sources":["../src/core/sql-utils.ts"],"sourcesContent":["/**\n * Shared SQL utility functions for the Postgres adapter.\n *\n * These functions handle safe SQL identifier and literal escaping\n * with security validations to prevent injection and encoding issues.\n */\n\n/**\n * Error thrown when an invalid SQL identifier or literal is detected.\n * Boundary layers map this to structured envelopes.\n */\nexport class SqlEscapeError extends Error {\n constructor(\n message: string,\n public readonly value: string,\n public readonly kind: 'identifier' | 'literal',\n ) {\n super(message);\n this.name = 'SqlEscapeError';\n }\n}\n\n/**\n * Maximum length for PostgreSQL identifiers (NAMEDATALEN - 1).\n */\nconst MAX_IDENTIFIER_LENGTH = 63;\n\n/**\n * Validates and quotes a PostgreSQL identifier (table, column, type, schema names).\n *\n * Security validations:\n * - Rejects null bytes which could cause truncation or unexpected behavior\n * - Rejects empty identifiers\n * - Warns on identifiers exceeding PostgreSQL's 63-character limit\n *\n * @throws {SqlEscapeError} If the identifier contains null bytes or is empty\n */\nexport function quoteIdentifier(identifier: string): string {\n if (identifier.length === 0) {\n throw new SqlEscapeError('Identifier cannot be empty', identifier, 'identifier');\n }\n if (identifier.includes('\\0')) {\n throw new SqlEscapeError(\n 'Identifier cannot contain null bytes',\n identifier.replace(/\\0/g, '\\\\0'),\n 'identifier',\n );\n }\n // PostgreSQL will truncate identifiers longer than 63 characters.\n // We don't throw here because it's not a security issue, but callers should be aware.\n if (identifier.length > MAX_IDENTIFIER_LENGTH) {\n // Log warning in development, but don't fail - PostgreSQL handles truncation\n console.warn(\n `Identifier \"${identifier.slice(0, 20)}...\" exceeds PostgreSQL's ${MAX_IDENTIFIER_LENGTH}-character limit and will be truncated`,\n );\n }\n return `\"${identifier.replace(/\"/g, '\"\"')}\"`;\n}\n\n/**\n * Escapes a string literal for safe use in SQL statements.\n *\n * Security validations:\n * - Rejects null bytes which could cause truncation or unexpected behavior\n *\n * Note: This assumes PostgreSQL's `standard_conforming_strings` is ON (default since PG 9.1).\n * Backslashes are treated as literal characters, not escape sequences.\n *\n * @throws {SqlEscapeError} If the value contains null bytes\n */\nexport function escapeLiteral(value: string): string {\n if (value.includes('\\0')) {\n throw new SqlEscapeError(\n 'Literal value cannot contain null bytes',\n value.replace(/\\0/g, '\\\\0'),\n 'literal',\n );\n }\n return value.replace(/'/g, \"''\");\n}\n\n/**\n * Builds a qualified name (schema.object) with proper quoting.\n */\nexport function qualifyName(schemaName: string, objectName: string): string {\n return `${quoteIdentifier(schemaName)}.${quoteIdentifier(objectName)}`;\n}\n\n/**\n * Validates that an enum value doesn't exceed PostgreSQL's label length limit.\n *\n * PostgreSQL enum labels have a maximum length of NAMEDATALEN-1 (63 bytes by default).\n * Unlike identifiers, enum labels that exceed this limit cause an error rather than\n * silent truncation.\n *\n * @param value - The enum value to validate\n * @param enumTypeName - Name of the enum type (for error messages)\n * @throws {SqlEscapeError} If the value exceeds the maximum length\n */\nexport function validateEnumValueLength(value: string, enumTypeName: string): void {\n // PostgreSQL uses byte length, not character length. For simplicity, we use\n // character length as a conservative approximation (multi-byte chars would fail earlier).\n if (value.length > MAX_IDENTIFIER_LENGTH) {\n throw new SqlEscapeError(\n `Enum value \"${value.slice(0, 20)}...\" for type \"${enumTypeName}\" exceeds PostgreSQL's ` +\n `${MAX_IDENTIFIER_LENGTH}-character label limit`,\n value,\n 'literal',\n );\n }\n}\n"],"mappings":";;;;;;;;;;;AAWA,IAAa,iBAAb,cAAoC,MAAM;CACxC,YACE,SACA,AAAgBA,OAChB,AAAgBC,MAChB;AACA,QAAM,QAAQ;EAHE;EACA;AAGhB,OAAK,OAAO;;;;;;AAOhB,MAAM,wBAAwB;;;;;;;;;;;AAY9B,SAAgB,gBAAgB,YAA4B;AAC1D,KAAI,WAAW,WAAW,EACxB,OAAM,IAAI,eAAe,8BAA8B,YAAY,aAAa;AAElF,KAAI,WAAW,SAAS,KAAK,CAC3B,OAAM,IAAI,eACR,wCACA,WAAW,QAAQ,OAAO,MAAM,EAChC,aACD;AAIH,KAAI,WAAW,SAAS,sBAEtB,SAAQ,KACN,eAAe,WAAW,MAAM,GAAG,GAAG,CAAC,4BAA4B,sBAAsB,wCAC1F;AAEH,QAAO,IAAI,WAAW,QAAQ,MAAM,OAAK,CAAC;;;;;;;;;;;;;AAc5C,SAAgB,cAAc,OAAuB;AACnD,KAAI,MAAM,SAAS,KAAK,CACtB,OAAM,IAAI,eACR,2CACA,MAAM,QAAQ,OAAO,MAAM,EAC3B,UACD;AAEH,QAAO,MAAM,QAAQ,MAAM,KAAK;;;;;AAMlC,SAAgB,YAAY,YAAoB,YAA4B;AAC1E,QAAO,GAAG,gBAAgB,WAAW,CAAC,GAAG,gBAAgB,WAAW;;;;;;;;;;;;;AActE,SAAgB,wBAAwB,OAAe,cAA4B;AAGjF,KAAI,MAAM,SAAS,sBACjB,OAAM,IAAI,eACR,eAAe,MAAM,MAAM,GAAG,GAAG,CAAC,iBAAiB,aAAa,yBAC3D,sBAAsB,yBAC3B,OACA,UACD"}
@@ -16,4 +16,4 @@ interface OrderClause {
16
16
  type PostgresLoweredStatement = LoweredStatement;
17
17
  //#endregion
18
18
  export { OrderClause as a, PostgresContract as c, StorageColumn as d, StorageTable as f, Expr as i, PostgresLoweredStatement as l, ColumnRef as n, ParamRef as o, Direction as r, PostgresAdapterOptions as s, BinaryExpr as t, SelectAst as u };
19
- //# sourceMappingURL=types-BY395pUv.d.mts.map
19
+ //# sourceMappingURL=types-CXO7EB60.d.mts.map
@@ -1 +1 @@
1
- {"version":3,"file":"types-BY395pUv.d.mts","names":[],"sources":["../src/core/types.ts"],"sourcesContent":[],"mappings":";;;;UAsBiB,sBAAA;;AAAjB;AAIY,KAAA,gBAAA,GAAmB,WAAY,CAAA,UAAZ,CAAA,GAAA;EAEnB,SAAI,MAAA,EAAA,UAAG;AAEnB,CAAA;AAKY,KAPA,IAAA,GAAO,SAOP,GAPmB,QAOK;UALnB,WAAA;iBACA;gBACD;;KAGJ,wBAAA,GAA2B"}
1
+ {"version":3,"file":"types-CXO7EB60.d.mts","names":[],"sources":["../src/core/types.ts"],"sourcesContent":[],"mappings":";;;;UAsBiB,sBAAA;;AAAjB;AAIY,KAAA,gBAAA,GAAmB,WAAY,CAAA,UAAZ,CAAA,GAAA;EAEnB,SAAI,MAAA,EAAA,UAAG;AAEnB,CAAA;AAKY,KAPA,IAAA,GAAO,SAOP,GAPmB,QAOK;UALnB,WAAA;iBACA;gBACD;;KAGJ,wBAAA,GAA2B"}
package/dist/types.d.mts CHANGED
@@ -1,2 +1,2 @@
1
- import { a as OrderClause, c as PostgresContract, d as StorageColumn, f as StorageTable, i as Expr, l as PostgresLoweredStatement, n as ColumnRef, o as ParamRef, r as Direction, s as PostgresAdapterOptions, t as BinaryExpr, u as SelectAst } from "./types-BY395pUv.mjs";
1
+ import { a as OrderClause, c as PostgresContract, d as StorageColumn, f as StorageTable, i as Expr, l as PostgresLoweredStatement, n as ColumnRef, o as ParamRef, r as Direction, s as PostgresAdapterOptions, t as BinaryExpr, u as SelectAst } from "./types-CXO7EB60.mjs";
2
2
  export { type BinaryExpr, type ColumnRef, type Direction, type Expr, type OrderClause, type ParamRef, type PostgresAdapterOptions, type PostgresContract, type PostgresLoweredStatement, type SelectAst, type StorageColumn, type StorageTable };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@prisma-next/adapter-postgres",
3
- "version": "0.3.0-dev.40",
3
+ "version": "0.3.0-dev.43",
4
4
  "type": "module",
5
5
  "sideEffects": false,
6
6
  "files": [
@@ -10,19 +10,19 @@
10
10
  "dependencies": {
11
11
  "ajv": "^8.17.1",
12
12
  "arktype": "^2.0.0",
13
- "@prisma-next/cli": "0.3.0-dev.40",
14
- "@prisma-next/contract": "0.3.0-dev.40",
15
- "@prisma-next/contract-authoring": "0.3.0-dev.40",
16
- "@prisma-next/core-control-plane": "0.3.0-dev.40",
17
- "@prisma-next/core-execution-plane": "0.3.0-dev.40",
18
- "@prisma-next/family-sql": "0.3.0-dev.40",
19
- "@prisma-next/sql-operations": "0.3.0-dev.40",
20
- "@prisma-next/sql-relational-core": "0.3.0-dev.40",
21
- "@prisma-next/sql-runtime": "0.3.0-dev.40",
22
- "@prisma-next/sql-schema-ir": "0.3.0-dev.40",
23
- "@prisma-next/utils": "0.3.0-dev.40",
24
- "@prisma-next/sql-contract-ts": "0.3.0-dev.40",
25
- "@prisma-next/sql-contract": "0.3.0-dev.40"
13
+ "@prisma-next/cli": "0.3.0-dev.43",
14
+ "@prisma-next/contract": "0.3.0-dev.43",
15
+ "@prisma-next/contract-authoring": "0.3.0-dev.43",
16
+ "@prisma-next/core-control-plane": "0.3.0-dev.43",
17
+ "@prisma-next/core-execution-plane": "0.3.0-dev.43",
18
+ "@prisma-next/sql-contract": "0.3.0-dev.43",
19
+ "@prisma-next/sql-operations": "0.3.0-dev.43",
20
+ "@prisma-next/sql-relational-core": "0.3.0-dev.43",
21
+ "@prisma-next/sql-runtime": "0.3.0-dev.43",
22
+ "@prisma-next/sql-schema-ir": "0.3.0-dev.43",
23
+ "@prisma-next/utils": "0.3.0-dev.43",
24
+ "@prisma-next/sql-contract-ts": "0.3.0-dev.43",
25
+ "@prisma-next/family-sql": "0.3.0-dev.43"
26
26
  },
27
27
  "devDependencies": {
28
28
  "tsdown": "0.18.4",
@@ -22,6 +22,7 @@ import { createCodecRegistry, isOperationExpr } from '@prisma-next/sql-relationa
22
22
  import { ifDefined } from '@prisma-next/utils/defined';
23
23
  import { PG_JSON_CODEC_ID, PG_JSONB_CODEC_ID } from './codec-ids';
24
24
  import { codecDefinitions } from './codecs';
25
+ import { escapeLiteral } from './sql-utils';
25
26
  import type { PostgresAdapterOptions, PostgresContract, PostgresLoweredStatement } from './types';
26
27
 
27
28
  const VECTOR_CODEC_ID = 'pg/vector@1' as const;
@@ -285,7 +286,7 @@ function renderParam(
285
286
 
286
287
  function renderLiteral(expr: LiteralExpr): string {
287
288
  if (typeof expr.value === 'string') {
288
- return `'${expr.value.replace(/'/g, "''")}'`;
289
+ return `'${escapeLiteral(expr.value)}'`;
289
290
  }
290
291
  if (typeof expr.value === 'number' || typeof expr.value === 'boolean') {
291
292
  return String(expr.value);
@@ -465,7 +466,10 @@ function renderInsert(ast: InsertAst, contract: PostgresContract): string {
465
466
  throw new Error(`Unsupported value kind in INSERT: ${(val as { kind: string }).kind}`);
466
467
  });
467
468
 
468
- const insertClause = `INSERT INTO ${table} (${columns.join(', ')}) VALUES (${values.join(', ')})`;
469
+ const insertClause =
470
+ columns.length === 0
471
+ ? `INSERT INTO ${table} DEFAULT VALUES`
472
+ : `INSERT INTO ${table} (${columns.join(', ')}) VALUES (${values.join(', ')})`;
469
473
  const returningClause = ast.returning?.length
470
474
  ? ` RETURNING ${ast.returning.map((col) => `${quoteIdentifier(col.table)}.${quoteIdentifier(col.column)}`).join(', ')}`
471
475
  : '';
@@ -273,9 +273,8 @@ const pgTimestampCodec = codec<typeof PG_TIMESTAMP_CODEC_ID, string | Date, stri
273
273
  return String(value);
274
274
  },
275
275
  decode: (wire: string | Date): string => {
276
- if (typeof wire === 'string') return wire;
277
276
  if (wire instanceof Date) return wire.toISOString();
278
- return String(wire);
277
+ return wire;
279
278
  },
280
279
  paramsSchema: precisionParamsSchema,
281
280
  meta: {
@@ -298,9 +297,8 @@ const pgTimestamptzCodec = codec<typeof PG_TIMESTAMPTZ_CODEC_ID, string | Date,
298
297
  return String(value);
299
298
  },
300
299
  decode: (wire: string | Date): string => {
301
- if (typeof wire === 'string') return wire;
302
300
  if (wire instanceof Date) return wire.toISOString();
303
- return String(wire);
301
+ return wire;
304
302
  },
305
303
  paramsSchema: precisionParamsSchema,
306
304
  meta: {
@@ -405,11 +403,18 @@ const pgEnumCodec = codec<typeof PG_ENUM_CODEC_ID, string, string>({
405
403
  decode: (wire) => wire,
406
404
  });
407
405
 
408
- const pgIntervalCodec = codec<typeof PG_INTERVAL_CODEC_ID, string, string>({
406
+ const pgIntervalCodec = codec<
407
+ typeof PG_INTERVAL_CODEC_ID,
408
+ string | Record<string, unknown>,
409
+ string
410
+ >({
409
411
  typeId: PG_INTERVAL_CODEC_ID,
410
412
  targetTypes: ['interval'],
411
413
  encode: (value: string): string => value,
412
- decode: (wire: string): string => wire,
414
+ decode: (wire: string | Record<string, unknown>): string => {
415
+ if (typeof wire === 'string') return wire;
416
+ return JSON.stringify(wire);
417
+ },
413
418
  paramsSchema: precisionParamsSchema,
414
419
  meta: {
415
420
  db: {
@@ -5,6 +5,7 @@ import type {
5
5
  SqlColumnIR,
6
6
  SqlForeignKeyIR,
7
7
  SqlIndexIR,
8
+ SqlReferentialAction,
8
9
  SqlSchemaIR,
9
10
  SqlTableIR,
10
11
  SqlUniqueIR,
@@ -137,7 +138,10 @@ export class PostgresControlAdapter implements SqlControlAdapter<'postgres'> {
137
138
  ORDER BY tc.table_name, kcu.ordinal_position`,
138
139
  [schema],
139
140
  ),
140
- // Query all foreign keys for all tables in schema
141
+ // Query all foreign keys for all tables in schema, including referential actions.
142
+ // Uses pg_catalog for correct positional pairing of composite FK columns
143
+ // (information_schema.constraint_column_usage lacks ordinal_position,
144
+ // which causes Cartesian products for multi-column FKs).
141
145
  driver.query<{
142
146
  table_name: string;
143
147
  constraint_name: string;
@@ -146,23 +150,39 @@ export class PostgresControlAdapter implements SqlControlAdapter<'postgres'> {
146
150
  referenced_table_schema: string;
147
151
  referenced_table_name: string;
148
152
  referenced_column_name: string;
153
+ delete_rule: string;
154
+ update_rule: string;
149
155
  }>(
150
156
  `SELECT
151
157
  tc.table_name,
152
158
  tc.constraint_name,
153
159
  kcu.column_name,
154
160
  kcu.ordinal_position,
155
- ccu.table_schema AS referenced_table_schema,
156
- ccu.table_name AS referenced_table_name,
157
- ccu.column_name AS referenced_column_name
161
+ ref_ns.nspname AS referenced_table_schema,
162
+ ref_cl.relname AS referenced_table_name,
163
+ ref_att.attname AS referenced_column_name,
164
+ rc.delete_rule,
165
+ rc.update_rule
158
166
  FROM information_schema.table_constraints tc
159
167
  JOIN information_schema.key_column_usage kcu
160
168
  ON tc.constraint_name = kcu.constraint_name
161
169
  AND tc.table_schema = kcu.table_schema
162
170
  AND tc.table_name = kcu.table_name
163
- JOIN information_schema.constraint_column_usage ccu
164
- ON ccu.constraint_name = tc.constraint_name
165
- AND ccu.table_schema = tc.table_schema
171
+ JOIN pg_catalog.pg_constraint pgc
172
+ ON pgc.conname = tc.constraint_name
173
+ AND pgc.connamespace = (
174
+ SELECT oid FROM pg_catalog.pg_namespace WHERE nspname = tc.table_schema
175
+ )
176
+ JOIN pg_catalog.pg_class ref_cl
177
+ ON ref_cl.oid = pgc.confrelid
178
+ JOIN pg_catalog.pg_namespace ref_ns
179
+ ON ref_ns.oid = ref_cl.relnamespace
180
+ JOIN pg_catalog.pg_attribute ref_att
181
+ ON ref_att.attrelid = pgc.confrelid
182
+ AND ref_att.attnum = pgc.confkey[kcu.ordinal_position]
183
+ JOIN information_schema.referential_constraints rc
184
+ ON rc.constraint_name = tc.constraint_name
185
+ AND rc.constraint_schema = tc.table_schema
166
186
  WHERE tc.table_schema = $1
167
187
  AND tc.constraint_type = 'FOREIGN KEY'
168
188
  ORDER BY tc.table_name, tc.constraint_name, kcu.ordinal_position`,
@@ -305,7 +325,14 @@ export class PostgresControlAdapter implements SqlControlAdapter<'postgres'> {
305
325
  // Process foreign keys
306
326
  const foreignKeysMap = new Map<
307
327
  string,
308
- { columns: string[]; referencedTable: string; referencedColumns: string[]; name: string }
328
+ {
329
+ columns: string[];
330
+ referencedTable: string;
331
+ referencedColumns: string[];
332
+ name: string;
333
+ deleteRule: string;
334
+ updateRule: string;
335
+ }
309
336
  >();
310
337
  for (const fkRow of fksByTable.get(tableName) ?? []) {
311
338
  const existing = foreignKeysMap.get(fkRow.constraint_name);
@@ -318,6 +345,8 @@ export class PostgresControlAdapter implements SqlControlAdapter<'postgres'> {
318
345
  referencedTable: fkRow.referenced_table_name,
319
346
  referencedColumns: [fkRow.referenced_column_name],
320
347
  name: fkRow.constraint_name,
348
+ deleteRule: fkRow.delete_rule,
349
+ updateRule: fkRow.update_rule,
321
350
  });
322
351
  }
323
352
  }
@@ -327,6 +356,8 @@ export class PostgresControlAdapter implements SqlControlAdapter<'postgres'> {
327
356
  referencedTable: fk.referencedTable,
328
357
  referencedColumns: Object.freeze([...fk.referencedColumns]) as readonly string[],
329
358
  name: fk.name,
359
+ ...ifDefined('onDelete', mapReferentialAction(fk.deleteRule)),
360
+ ...ifDefined('onUpdate', mapReferentialAction(fk.updateRule)),
330
361
  }),
331
362
  );
332
363
 
@@ -517,6 +548,36 @@ function normalizeFormattedType(formattedType: string, dataType: string, udtName
517
548
  return formattedType;
518
549
  }
519
550
 
551
+ /**
552
+ * The five standard PostgreSQL referential action rules as returned by
553
+ * `information_schema.referential_constraints.delete_rule` / `update_rule`.
554
+ */
555
+ type PgReferentialActionRule = 'NO ACTION' | 'RESTRICT' | 'CASCADE' | 'SET NULL' | 'SET DEFAULT';
556
+
557
+ const PG_REFERENTIAL_ACTION_MAP: Record<PgReferentialActionRule, SqlReferentialAction> = {
558
+ 'NO ACTION': 'noAction',
559
+ RESTRICT: 'restrict',
560
+ CASCADE: 'cascade',
561
+ 'SET NULL': 'setNull',
562
+ 'SET DEFAULT': 'setDefault',
563
+ };
564
+
565
+ /**
566
+ * Maps a Postgres referential action rule to the canonical SqlReferentialAction.
567
+ * Returns undefined for 'NO ACTION' (the database default) to keep the IR sparse.
568
+ * Throws for unrecognized rules to prevent silent data loss.
569
+ */
570
+ function mapReferentialAction(rule: string): SqlReferentialAction | undefined {
571
+ const mapped = PG_REFERENTIAL_ACTION_MAP[rule as PgReferentialActionRule];
572
+ if (mapped === undefined) {
573
+ throw new Error(
574
+ `Unknown PostgreSQL referential action rule: "${rule}". Expected one of: NO ACTION, RESTRICT, CASCADE, SET NULL, SET DEFAULT.`,
575
+ );
576
+ }
577
+ if (mapped === 'noAction') return undefined;
578
+ return mapped;
579
+ }
580
+
520
581
  /**
521
582
  * Groups an array of objects by a specified key.
522
583
  * Returns a Map for O(1) lookup by group key.