/** * Postgres introspection — stage 2 of the migration pipeline. * * Produces a SchemaSnapshot from a live Kysely> pointing at a Postgres * (or pg-mem) database. * * Design notes: * - We deliberately avoid Kysely's built-in db.introspection.getTables() because * it uses the `!~` regex operator in its internal query, which pg-mem (v3) does * not support. We read information_schema directly via raw SQL instead. * - Primary keys come from information_schema.table_constraints + * key_column_usage. Real Postgres returns rows; pg-mem (v3) returns empty rows * for both views — so PK tests are gated on MIGRATE_TS_PG_URL in the test file. * - Default values come from information_schema.columns.column_default. pg-mem * always returns null for this column, so default tests are gated too. * - Type normalization (pgTypeToSqlType) is exported so it can be unit-tested * without a live DB. * * pg-mem gaps (documented here, gated in the test file): * - information_schema.columns.character_maximum_length → always null * - information_schema.columns.column_default → always null * - information_schema.table_constraints / key_column_usage → empty rows * - bigserial appears as "integer" (no sequence differentiation) * - array_position() not implemented → pg_index catalog query throws; * readPgIndexes() catches and returns [] on pg-mem * - information_schema.referential_constraints not supported → * readPgForeignKeys() catches and returns [] on pg-mem */ import type { Kysely } from "kysely"; import type { SchemaSnapshot, ColumnDefault } from "../types.js"; import type { SqlType } from "../sql-type.js"; export declare function introspectPostgres(db: Kysely>): Promise; /** * Normalise a PG column data type string into a canonical SqlType. * The `dataType` string comes from information_schema.columns.data_type (or * occasionally from information_schema.columns.udt_name). Both are lower-cased * before matching. * * If character_maximum_length is available, callers should pass `maxLength`. * * `numeric` carries its qualifier OUT-OF-BAND: `data_type` is a bare "numeric" * for both NUMERIC and NUMERIC(9,4), so callers reading information_schema must * pass `numeric.precision` / `numeric.scale` (from numeric_precision / * numeric_scale) or the qualifier is lost. An inline "numeric(9,4)" string is * still parsed — that form arrives from format_type()/pg_catalog callers and * from unit tests — but it is NOT what information_schema produces. * * Only the numeric/decimal branch consults the qualifier: information_schema * also populates numeric_precision for INTEGER columns (int4 → 32, radix 2), * which has nothing to do with a NUMERIC qualifier. */ export declare function pgTypeToSqlType(dataType: string, maxLength?: number | null, udtName?: string, numeric?: { precision: number | null; scale: number | null; }): SqlType; /** * Parse a raw PG column_default string into a ColumnDefault. * Returns undefined if the default is absent or empty. * * Classification rules: * - Expressions: now(), CURRENT_TIMESTAMP, CURRENT_DATE, CURRENT_TIME, and any * bare function-call (e.g. nextval(...), gen_random_uuid(), uuid_generate_v4()), * plus any value that starts with a non-quote character and contains a `::` cast * (i.e. bare identifier with cast, like `NULL::text`). * - Literals: `'value'` (optionally followed by `::type` cast, which PG * commonly appends for clarity). The cast is stripped; the value is unquoted. * * PG stores literal booleans as `'true'::boolean`, integers as `'42'::integer`, * strings as `'hello'::text` — all are literals after stripping the cast. * * The bare function-call rule keeps this in lockstep with the metadata-side * default classifier (expected-schema's EXPR_DEFAULT_PATTERNS, which treats any * `()` default as an expression): without it, a `gen_random_uuid()` column default * round-trips as a literal here but an expression there, producing a spurious * column diff on every uuid-PK table. */ export declare function parsePgDefault(raw: string | null | undefined): ColumnDefault | undefined; //# sourceMappingURL=postgres.d.ts.map