qubu 0.6.0 → 0.6.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (65) hide show
  1. package/README.md +112 -0
  2. package/dist/codegen.d.mts +1 -1
  3. package/dist/codegen.mjs +1 -1
  4. package/dist/{column-r1Y4ivwt.mjs → column-BzN8KFJa.mjs} +39 -2
  5. package/dist/{column-Da37jYSD.mjs → column-CFvSbil0.mjs} +1 -1
  6. package/dist/{complete-types-CY0KbzNw.d.mts → complete-types-CNMWBWap.d.mts} +1 -1
  7. package/dist/{constraints-YGyNPQ_z.mjs → constraints-DM_tarXc.mjs} +2 -2
  8. package/dist/core.d.mts +1 -1
  9. package/dist/core.mjs +2 -3
  10. package/dist/diagnostics-I9vVtXkc.mjs +40 -0
  11. package/dist/diff.d.mts +2 -2
  12. package/dist/expressions-BCjc08zw.mjs +129 -0
  13. package/dist/{index-B2rZf3-2.d.mts → index-CGui70hi.d.mts} +2 -2
  14. package/dist/index.d.mts +2 -2
  15. package/dist/index.mjs +58 -15
  16. package/dist/introspection/mysql.d.mts +26 -0
  17. package/dist/introspection/mysql.mjs +1145 -0
  18. package/dist/introspection/postgres.d.mts +40 -0
  19. package/dist/introspection/postgres.mjs +1554 -0
  20. package/dist/introspection/sqlite.d.mts +15 -0
  21. package/dist/introspection/sqlite.mjs +986 -0
  22. package/dist/introspection.d.mts +3 -78
  23. package/dist/introspection.mjs +5 -3683
  24. package/dist/mysql.d.mts +1 -1
  25. package/dist/mysql.mjs +2 -2
  26. package/dist/{on-conflict-DZQ85f1t.mjs → on-conflict-CnaY5qso.mjs} +76 -4
  27. package/dist/postgres-Dey7QXPL.mjs +69 -0
  28. package/dist/postgres.d.mts +3 -3
  29. package/dist/postgres.mjs +3 -52
  30. package/dist/registry-oWDiqD7i.mjs +127 -0
  31. package/dist/{relational-CxnLCqZQ.mjs → relational-DSAJ-l58.mjs} +1 -2
  32. package/dist/schema.d.mts +1 -1
  33. package/dist/schema.mjs +7 -6
  34. package/dist/{serialize-BN07IK0v.mjs → serialize-CE-gw5_s.mjs} +3 -3
  35. package/dist/{serialize-CEIIlWhC.d.mts → serialize-OvXCLzjm.d.mts} +1 -1
  36. package/dist/snapshot/mysql.d.mts +2 -2
  37. package/dist/snapshot/mysql.mjs +28 -28
  38. package/dist/snapshot/postgres.d.mts +4 -4
  39. package/dist/snapshot/postgres.mjs +21 -21
  40. package/dist/snapshot/sqlite.d.mts +4 -4
  41. package/dist/snapshot/sqlite.mjs +27 -27
  42. package/dist/{snapshot-Xam8-q0j.mjs → snapshot-DgsOhf_8.mjs} +4 -42
  43. package/dist/snapshot.d.mts +4 -4
  44. package/dist/snapshot.mjs +1 -1
  45. package/dist/{source-SqrKWjFJ.mjs → source-BDuUXmAk.mjs} +2 -2
  46. package/dist/sqlite.d.mts +1 -1
  47. package/dist/sqlite.mjs +6 -6
  48. package/dist/{table-BwflqeAj.mjs → table-C1QGNe4P.mjs} +3 -3
  49. package/dist/{types-CTCqtFlS.d.mts → types-BEn0N_al.d.mts} +1 -1
  50. package/dist/{types-BIJsj2fJ.mjs → types-BLNRatG_.mjs} +2 -4
  51. package/dist/{types-C0VkiwpR.d.mts → types-DUe6eeI0.d.mts} +57 -28
  52. package/docs/guides/compose-queries.md +22 -0
  53. package/docs/guides/drizzle.md +11 -11
  54. package/docs/guides/mutations.md +89 -0
  55. package/docs/guides/valtio-sync.md +113 -0
  56. package/docs/migrations/index.md +50 -12
  57. package/docs/migrations/operations.md +20 -6
  58. package/docs/reference/supported-surface.md +17 -6
  59. package/docs/schema/code-generation.md +3 -2
  60. package/docs/schema/introspection.md +3 -2
  61. package/docs/sql-semantic-types.md +8 -0
  62. package/package.json +13 -1
  63. package/dist/registry-BRcUuazJ.mjs +0 -256
  64. package/dist/standard-DfcZEVOj.mjs +0 -12
  65. package/dist/value-D14I_XgL.mjs +0 -29
@@ -0,0 +1,1554 @@
1
+ import { n as createIntrospectionDiagnostic } from "../diagnostics-I9vVtXkc.mjs";
2
+ //#region src/introspection/postgres.ts
3
+ /** Fixed server metadata query used by the PostgreSQL catalog reader. */
4
+ const postgresServerQuery = `
5
+ SELECT
6
+ current_setting('server_version_num') AS server_version_num,
7
+ current_setting('server_version') AS server_version
8
+ `;
9
+ /** Read one PostgreSQL schema into the normalized catalog contract. */
10
+ async function readCatalog(connection, options) {
11
+ const diagnostics = [];
12
+ if (connection.dialect !== "postgresql") {
13
+ diagnostics.push(createIntrospectionDiagnostic({
14
+ severity: "error",
15
+ code: "dialect-mismatch",
16
+ message: `PostgreSQL catalog reader received a ${connection.dialect} connection`,
17
+ path: ["connection", "dialect"],
18
+ remediation: "Use a PostgreSQL CatalogConnection with this reader."
19
+ }));
20
+ return emptyCatalog(options.namespace, diagnostics);
21
+ }
22
+ const server = serverInfo((await query(connection, postgresServerQuery, [], options, diagnostics, "server"))[0], diagnostics);
23
+ const relationObjects = (await query(connection, postgresRelationsQuery, [options.namespace], options, diagnostics, "relations")).filter((row) => {
24
+ const kind = text(row.relkind);
25
+ return kind !== "i" && kind !== "I";
26
+ });
27
+ const tables = relationObjects.filter((row) => row.relkind === "r" || row.relkind === "p").map((row) => relationTable(row));
28
+ const tableByOid = new Map(tables.map((table) => [table.reference?.catalog?.value, table]));
29
+ const viewRows = await query(connection, postgresViewsQuery, [options.namespace], options, diagnostics, "views");
30
+ const views = [];
31
+ for (const row of viewRows) {
32
+ const view = viewObject(row, options.namespace, diagnostics);
33
+ if (view.kind === "deferred-object") continue;
34
+ views.push(view);
35
+ }
36
+ const relationReferences = /* @__PURE__ */ new Map();
37
+ for (const table of tables) relationReferences.set(table.reference?.catalog?.value, {
38
+ kind: "table",
39
+ id: table.id
40
+ });
41
+ for (const view of views) relationReferences.set(view.reference?.catalog?.value, {
42
+ kind: view.kind,
43
+ id: view.id
44
+ });
45
+ const columnRows = await query(connection, postgresColumnsQuery, [options.namespace], options, diagnostics, "columns");
46
+ const identityRows = await query(connection, postgresIdentitiesQuery, [options.namespace], options, diagnostics, "identities");
47
+ const identityOptionsByColumn = /* @__PURE__ */ new Map();
48
+ for (const row of identityRows) identityOptionsByColumn.set(columnKey(row.table_oid, row.ordinal_position), identityOptions(row));
49
+ const columnsByTable = groupBy(columnRows, (row) => row.table_oid);
50
+ for (const table of tables) table.columns = (columnsByTable.get(table.reference?.catalog?.value) ?? []).sort(compareOrdinal).map((row) => column(row, table, options.namespace, identityOptionsByColumn.get(columnKey(row.table_oid, row.ordinal_position))));
51
+ for (const view of views) view.columns = (columnsByTable.get(view.reference?.catalog?.value) ?? []).sort(compareOrdinal).map((row) => column(row, view, options.namespace));
52
+ const indexRows = await query(connection, postgresIndexesQuery, [options.namespace], options, diagnostics, "indexes");
53
+ const indexReferences = /* @__PURE__ */ new Map();
54
+ for (const row of indexRows) {
55
+ const indexOid = text(row.index_oid);
56
+ const physicalName = text(row.physical_name);
57
+ if (indexOid && physicalName) indexReferences.set(`pg_class:${indexOid}`, {
58
+ kind: "index",
59
+ id: stableId(physicalName),
60
+ physicalName,
61
+ reference: reference("index", physicalName, options.namespace, "pg_class", "oid", row.index_oid)
62
+ });
63
+ }
64
+ const constraintsByTable = groupBy(await query(connection, postgresConstraintsQuery, [options.namespace], options, diagnostics, "constraints"), (row) => row.table_oid);
65
+ for (const table of tables) {
66
+ const rows = constraintsByTable.get(table.reference?.catalog?.value) ?? [];
67
+ const columnsByNumber = new Map(table.columns.map((column) => [column.ordinalPosition, column.physicalName]));
68
+ table.constraints = rows.map((row) => constraint(row, table, columnsByNumber, tableByOid, options.namespace, diagnostics, indexReferences)).filter((value) => value !== void 0);
69
+ }
70
+ const indexesByTable = groupBy(indexRows, (row) => row.table_oid);
71
+ for (const table of tables) table.indexes = mapIndexes(indexesByTable.get(table.reference?.catalog?.value) ?? [], table, new Map(table.columns.map((column) => [column.ordinalPosition, column.physicalName])), options.namespace);
72
+ const sequences = (await query(connection, postgresSequencesQuery, [options.namespace], options, diagnostics, "sequences")).map((row) => sequenceObject(row, options.namespace, tableByOid, diagnostics));
73
+ const enums = mapEnums(await query(connection, postgresEnumsQuery, [options.namespace], options, diagnostics, "enums"), options.namespace);
74
+ const domains = mapDomains(await query(connection, postgresDomainsQuery, [options.namespace], options, diagnostics, "domains"), await query(connection, postgresDomainConstraintsQuery, [options.namespace], options, diagnostics, "domain-constraints"), options.namespace);
75
+ const collations = (await query(connection, postgresCollationsQuery, [options.namespace], options, diagnostics, "collations")).map((row) => collationObject(row, options.namespace));
76
+ const triggerRows = await query(connection, postgresTriggersQuery, [options.namespace], options, diagnostics, "triggers");
77
+ const triggers = [];
78
+ const triggerDeferredObjects = [];
79
+ for (const row of triggerRows) {
80
+ const value = triggerObject(row, options.namespace, relationReferences, diagnostics);
81
+ if (value.kind === "deferred-object") triggerDeferredObjects.push(value);
82
+ else triggers.push(value);
83
+ }
84
+ const routines = mapRoutines(await query(connection, postgresRoutinesQuery, [options.namespace], options, diagnostics, "routines"), await query(connection, postgresRoutineParametersQuery, [options.namespace], options, diagnostics, "routine-parameters"), options.namespace, diagnostics);
85
+ const partitions = (await query(connection, postgresPartitionsQuery, [options.namespace], options, diagnostics, "partitions")).map((row) => partitionObject(row, options.namespace, tableByOid, diagnostics)).filter((value) => value !== void 0);
86
+ const policies = (await query(connection, postgresPoliciesQuery, [options.namespace], options, diagnostics, "policies")).map((row) => policyObject(row, options.namespace, tableByOid, diagnostics)).filter((value) => value !== void 0);
87
+ const extensionObjects = (await query(connection, postgresExtensionsQuery, [options.namespace], options, diagnostics, "extensions")).map((row) => extensionObject(row, options.namespace));
88
+ const typedRelationOids = new Set([...views, ...sequences].map((object) => object.reference?.catalog?.value));
89
+ const deferredObjects = relationObjects.filter((row) => {
90
+ const relkind = text(row.relkind);
91
+ return relkind === "f" || (relkind === "v" || relkind === "m" || relkind === "S") && !typedRelationOids.has(row.oid === void 0 ? void 0 : text(row.oid));
92
+ }).map((row) => deferredObject(row, text(row.relkind) === "f" ? "foreign-table" : text(row.relkind) === "v" ? "view" : text(row.relkind) === "m" ? "materialized-view" : "sequence"));
93
+ deferredObjects.push(...triggerDeferredObjects);
94
+ const opaqueObjects = relationObjects.filter((row) => {
95
+ const kind = text(row.relkind);
96
+ return kind !== "r" && kind !== "p" && kind !== "v" && kind !== "m" && kind !== "S" && kind !== "f";
97
+ }).map((row) => opaqueRelationObject(row, options.namespace, diagnostics));
98
+ const metadata = mapMetadataRows(await query(connection, postgresMetadataQuery, [options.namespace], options, diagnostics, "comments-and-ownership"), options.namespace, tables, views, sequences, enums, domains, collations, routines, triggers, policies, extensionObjects, deferredObjects, opaqueObjects, indexReferences, relationReferences, diagnostics);
99
+ opaqueObjects.push(...metadata.opaqueObjects);
100
+ return Object.freeze({
101
+ dialect: "postgresql",
102
+ server,
103
+ namespace: {
104
+ kind: "postgres-schema",
105
+ name: options.namespace,
106
+ reference: reference("namespace", options.namespace, options.namespace, "pg_namespace", "nspname")
107
+ },
108
+ tables: Object.freeze(tables),
109
+ views: Object.freeze(views),
110
+ sequences: Object.freeze(sequences),
111
+ enums: Object.freeze(enums),
112
+ domains: Object.freeze(domains),
113
+ collations: Object.freeze(collations),
114
+ triggers: Object.freeze(triggers),
115
+ routines: Object.freeze(routines),
116
+ partitions: Object.freeze(partitions),
117
+ policies: Object.freeze(policies),
118
+ extensionObjects: Object.freeze(extensionObjects),
119
+ deferredObjects: Object.freeze(deferredObjects),
120
+ opaqueObjects: Object.freeze(opaqueObjects),
121
+ comments: Object.freeze(metadata.comments),
122
+ ownership: Object.freeze(metadata.ownership),
123
+ capabilities: server.capabilities,
124
+ diagnostics: Object.freeze(diagnostics)
125
+ });
126
+ }
127
+ const postgresRelationsQuery = `
128
+ SELECT c.oid::text AS oid, n.nspname AS namespace, c.relname,
129
+ c.relkind, c.relispartition
130
+ FROM pg_class c
131
+ JOIN pg_namespace n ON n.oid = c.relnamespace
132
+ WHERE n.nspname = $1
133
+ AND c.relkind NOT IN ('i', 'I')
134
+ ORDER BY c.relname
135
+ `;
136
+ /** Fixed view and materialized-view definitions from PostgreSQL's decompiler. */
137
+ const postgresViewsQuery = `
138
+ SELECT c.oid::text AS oid, n.nspname AS namespace, c.relname AS physical_name,
139
+ c.relkind, pg_get_viewdef(c.oid, true) AS definition,
140
+ v.check_option, c.reloptions
141
+ FROM pg_catalog.pg_class c
142
+ JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
143
+ LEFT JOIN information_schema.views v
144
+ ON v.table_schema = n.nspname AND v.table_name = c.relname
145
+ WHERE n.nspname = $1 AND c.relkind IN ('v', 'm')
146
+ ORDER BY c.oid
147
+ `;
148
+ const postgresColumnsQuery = `
149
+ SELECT a.attrelid::text AS table_oid, a.attnum::int AS ordinal_position,
150
+ a.attname AS physical_name, NOT a.attnotnull AS nullable,
151
+ format_type(a.atttypid, a.atttypmod) AS native_type,
152
+ a.attidentity, a.attgenerated,
153
+ pg_get_expr(ad.adbin, ad.adrelid) AS default_expression
154
+ FROM pg_attribute a
155
+ JOIN pg_class c ON c.oid = a.attrelid
156
+ JOIN pg_namespace n ON n.oid = c.relnamespace
157
+ LEFT JOIN pg_attrdef ad ON ad.adrelid = a.attrelid AND ad.adnum = a.attnum
158
+ WHERE n.nspname = $1
159
+ AND c.relkind IN ('r', 'p', 'v', 'm')
160
+ AND a.attnum > 0
161
+ AND NOT a.attisdropped
162
+ ORDER BY a.attrelid, a.attnum
163
+ `;
164
+ const postgresConstraintsQuery = `
165
+ SELECT con.oid::text AS oid, con.conrelid::text AS table_oid,
166
+ con.conname AS physical_name, con.contype,
167
+ con.conkey, con.confrelid::text AS target_table_oid, con.confkey,
168
+ con.confupdtype, con.confdeltype, con.confmatchtype,
169
+ con.condeferrable, con.condeferred, con.convalidated,
170
+ con.conindid::text AS backing_index_oid,
171
+ i.indnullsnotdistinct,
172
+ pg_get_constraintdef(con.oid, true) AS definition
173
+ FROM pg_constraint con
174
+ JOIN pg_class c ON c.oid = con.conrelid
175
+ JOIN pg_namespace n ON n.oid = c.relnamespace
176
+ LEFT JOIN pg_index i ON i.indexrelid = con.conindid
177
+ WHERE n.nspname = $1
178
+ AND con.contype IN ('p', 'u', 'f', 'c', 'x')
179
+ ORDER BY con.conrelid, con.oid
180
+ `;
181
+ const postgresIndexesQuery = `
182
+ SELECT i.indexrelid::text AS index_oid, i.indrelid::text AS table_oid,
183
+ c.relname AS physical_name, i.indisunique, i.indnkeyatts::int,
184
+ i.indnatts::int, am.amname AS method,
185
+ pg_get_expr(i.indpred, i.indrelid, true) AS predicate,
186
+ s.position::int,
187
+ (i.indkey[s.position])::int AS attnum,
188
+ (i.indoption[s.position])::int AS indoption,
189
+ opc.opcname AS operator_class,
190
+ pg_get_indexdef(i.indexrelid, s.position, true) AS term_definition
191
+ FROM pg_index i
192
+ JOIN pg_class c ON c.oid = i.indexrelid
193
+ JOIN pg_class t ON t.oid = i.indrelid
194
+ JOIN pg_namespace n ON n.oid = t.relnamespace
195
+ JOIN pg_am am ON am.oid = c.relam
196
+ CROSS JOIN LATERAL generate_series(1, i.indnatts) AS s(position)
197
+ LEFT JOIN pg_opclass opc ON opc.oid = i.indclass[s.position]
198
+ WHERE n.nspname = $1
199
+ ORDER BY i.indrelid, i.indexrelid, s.position
200
+ `;
201
+ /** Identity sequence options joined to each generated identity column. */
202
+ const postgresIdentitiesQuery = `
203
+ SELECT a.attrelid::text AS table_oid, a.attnum::int AS ordinal_position,
204
+ s.seqstart, s.seqincrement, s.seqmin, s.seqmax, s.seqcache,
205
+ s.seqcycle, format_type(s.seqtypid, -1) AS sequence_type
206
+ FROM pg_catalog.pg_attribute a
207
+ JOIN pg_catalog.pg_class c ON c.oid = a.attrelid
208
+ JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
209
+ JOIN pg_catalog.pg_depend d
210
+ ON d.refclassid = 'pg_catalog.pg_class'::regclass
211
+ AND d.refobjid = a.attrelid AND d.refobjsubid = a.attnum
212
+ AND d.classid = 'pg_catalog.pg_class'::regclass
213
+ AND d.deptype = 'i'
214
+ JOIN pg_catalog.pg_sequence s ON s.seqrelid = d.objid
215
+ WHERE n.nspname = $1 AND a.attidentity <> ''
216
+ ORDER BY a.attrelid, a.attnum
217
+ `;
218
+ /** Sequence metadata, including serial/identity ownership dependencies. */
219
+ const postgresSequencesQuery = `
220
+ SELECT c.oid::text AS oid, n.nspname AS namespace, c.relname AS physical_name,
221
+ format_type(s.seqtypid, -1) AS native_type,
222
+ s.seqstart, s.seqincrement, s.seqmin, s.seqmax, s.seqcache,
223
+ s.seqcycle, dep.refobjid::text AS owned_table_oid,
224
+ dep.refobjsubid::int AS owned_column_position
225
+ FROM pg_catalog.pg_sequence s
226
+ JOIN pg_catalog.pg_class c ON c.oid = s.seqrelid
227
+ JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
228
+ LEFT JOIN pg_catalog.pg_depend dep
229
+ ON dep.classid = 'pg_catalog.pg_class'::regclass
230
+ AND dep.objid = c.oid AND dep.refclassid = 'pg_catalog.pg_class'::regclass
231
+ AND dep.deptype IN ('a', 'i')
232
+ WHERE n.nspname = $1
233
+ ORDER BY c.oid
234
+ `;
235
+ /** PostgreSQL enum labels in their declared order. */
236
+ const postgresEnumsQuery = `
237
+ SELECT t.oid::text AS oid, n.nspname AS namespace,
238
+ t.typname AS physical_name, e.oid::text AS value_oid,
239
+ e.enumlabel AS value, e.enumsortorder::float8 AS ordinal_position
240
+ FROM pg_catalog.pg_type t
241
+ JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
242
+ JOIN pg_catalog.pg_enum e ON e.enumtypid = t.oid
243
+ WHERE n.nspname = $1 AND t.typtype = 'e'
244
+ ORDER BY t.oid, e.enumsortorder
245
+ `;
246
+ /** PostgreSQL domains and their exact base type/default metadata. */
247
+ const postgresDomainsQuery = `
248
+ SELECT t.oid::text AS oid, n.nspname AS namespace,
249
+ t.typname AS physical_name,
250
+ format_type(t.typbasetype, t.typtypmod) AS native_type,
251
+ NOT t.typnotnull AS nullable, t.typdefault AS default_expression
252
+ FROM pg_catalog.pg_type t
253
+ JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
254
+ WHERE n.nspname = $1 AND t.typtype = 'd'
255
+ ORDER BY t.oid
256
+ `;
257
+ /** Domain CHECK constraints, which use pg_constraint.contypid. */
258
+ const postgresDomainConstraintsQuery = `
259
+ SELECT con.oid::text AS oid, con.contypid::text AS domain_oid,
260
+ con.conname AS physical_name, pg_get_constraintdef(con.oid, true) AS definition,
261
+ con.condeferrable, con.condeferred, con.convalidated
262
+ FROM pg_catalog.pg_constraint con
263
+ JOIN pg_catalog.pg_type t ON t.oid = con.contypid
264
+ JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
265
+ WHERE n.nspname = $1 AND con.contype = 'c'
266
+ ORDER BY con.contypid, con.oid
267
+ `;
268
+ /** Collation provider, locale, determinism, and version facts. */
269
+ const postgresCollationsQuery = `
270
+ SELECT c.oid::text AS oid, n.nspname AS namespace,
271
+ c.collname AS physical_name, c.collprovider, c.collcollate,
272
+ c.collctype, to_jsonb(c)->>'colllocale' AS colliculocale,
273
+ c.collisdeterministic, c.collversion
274
+ FROM pg_catalog.pg_collation c
275
+ JOIN pg_catalog.pg_namespace n ON n.oid = c.collnamespace
276
+ WHERE n.nspname = $1
277
+ ORDER BY c.oid
278
+ `;
279
+ /** User-defined triggers with decompiled condition and definition text. */
280
+ const postgresTriggersQuery = `
281
+ SELECT t.oid::text AS oid, t.tgrelid::text AS table_oid,
282
+ n.nspname AS namespace, t.tgname AS physical_name,
283
+ t.tgtype::int AS trigger_type, t.tgenabled,
284
+ pg_get_expr(t.tgqual, t.tgrelid, true) AS condition,
285
+ pg_get_triggerdef(t.oid, true) AS definition
286
+ FROM pg_catalog.pg_trigger t
287
+ JOIN pg_catalog.pg_class c ON c.oid = t.tgrelid
288
+ JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
289
+ WHERE n.nspname = $1 AND NOT t.tgisinternal
290
+ ORDER BY t.tgrelid, t.oid
291
+ `;
292
+ /** PostgreSQL functions, procedures, aggregates, and window routines. */
293
+ const postgresRoutinesQuery = `
294
+ SELECT p.oid::text AS oid, n.nspname AS namespace,
295
+ p.proname AS physical_name, p.prokind,
296
+ format_type(p.prorettype, NULL) AS return_type,
297
+ l.lanname AS language, pg_get_functiondef(p.oid) AS definition,
298
+ pg_get_function_identity_arguments(p.oid) AS identity_arguments,
299
+ pg_get_expr(p.proargdefaults, 0, true) AS argument_defaults,
300
+ p.pronargdefaults, p.provolatile, p.proparallel, p.prosecdef
301
+ FROM pg_catalog.pg_proc p
302
+ JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
303
+ JOIN pg_catalog.pg_language l ON l.oid = p.prolang
304
+ WHERE n.nspname = $1 AND p.prokind IN ('f', 'p', 'a', 'w')
305
+ ORDER BY p.oid
306
+ `;
307
+ /** Routine parameter rows using PostgreSQL's complete argument type arrays. */
308
+ const postgresRoutineParametersQuery = `
309
+ SELECT p.oid::text AS routine_oid, x.position::int AS ordinal_position,
310
+ names.name AS parameter_name, modes.mode,
311
+ format_type(x.type_oid, -1) AS native_type
312
+ FROM pg_catalog.pg_proc p
313
+ JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
314
+ CROSS JOIN LATERAL unnest(
315
+ COALESCE(p.proallargtypes, p.proargtypes::oid[])
316
+ ) WITH ORDINALITY AS x(type_oid, position)
317
+ LEFT JOIN LATERAL unnest(p.proargnames) WITH ORDINALITY
318
+ AS names(name, position) ON names.position = x.position
319
+ LEFT JOIN LATERAL unnest(p.proargmodes) WITH ORDINALITY
320
+ AS modes(mode, position) ON modes.position = x.position
321
+ WHERE n.nspname = $1 AND p.prokind IN ('f', 'p', 'a', 'w')
322
+ ORDER BY p.oid, x.position
323
+ `;
324
+ /** Partition children, key attributes, strategy, and bound expression. */
325
+ const postgresPartitionsQuery = `
326
+ SELECT child.oid::text AS partition_oid, parent.oid::text AS parent_oid,
327
+ n.nspname AS namespace, child.relname AS physical_name,
328
+ part.partstrat, part.partattrs::text AS key_attributes,
329
+ pg_get_expr(child.relpartbound, child.oid, true) AS bound,
330
+ child.relispartition, child.relkind
331
+ FROM pg_catalog.pg_inherits inh
332
+ JOIN pg_catalog.pg_class child ON child.oid = inh.inhrelid
333
+ JOIN pg_catalog.pg_class parent ON parent.oid = inh.inhparent
334
+ JOIN pg_catalog.pg_namespace n ON n.oid = child.relnamespace
335
+ LEFT JOIN pg_catalog.pg_partitioned_table part ON part.partrelid = parent.oid
336
+ WHERE n.nspname = $1
337
+ ORDER BY parent.oid, child.oid
338
+ `;
339
+ /** Row-level security policies and their role/expression metadata. */
340
+ const postgresPoliciesQuery = `
341
+ SELECT p.oid::text AS oid, p.polrelid::text AS table_oid,
342
+ n.nspname AS namespace, p.polname AS physical_name,
343
+ p.polcmd, p.polpermissive,
344
+ ARRAY(SELECT r.rolname FROM pg_catalog.pg_roles r
345
+ WHERE r.oid = ANY(p.polroles)) AS roles,
346
+ pg_get_expr(p.polqual, p.polrelid, true) AS using_expression,
347
+ pg_get_expr(p.polwithcheck, p.polrelid, true) AS check_expression
348
+ FROM pg_catalog.pg_policy p
349
+ JOIN pg_catalog.pg_class c ON c.oid = p.polrelid
350
+ JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
351
+ WHERE n.nspname = $1
352
+ ORDER BY p.polrelid, p.oid
353
+ `;
354
+ /** Installed PostgreSQL extensions scoped to the selected schema. */
355
+ const postgresExtensionsQuery = `
356
+ SELECT e.oid::text AS oid, n.nspname AS namespace,
357
+ e.extname AS physical_name, e.extversion, e.extrelocatable,
358
+ e.extconfig::text AS config_relations,
359
+ e.extcondition::text AS config_conditions
360
+ FROM pg_catalog.pg_extension e
361
+ JOIN pg_catalog.pg_namespace n ON n.oid = e.extnamespace
362
+ WHERE n.nspname = $1
363
+ ORDER BY e.oid
364
+ `;
365
+ /** Comments and owners for PostgreSQL objects visible in one schema. */
366
+ const postgresMetadataQuery = `
367
+ WITH objects AS (
368
+ SELECT 'pg_class'::text AS catalog_relation, 'pg_class'::regclass AS catalog_oid,
369
+ c.oid::text AS object_oid, 0::int AS object_subid,
370
+ CASE c.relkind WHEN 'r' THEN 'table' WHEN 'p' THEN 'table'
371
+ WHEN 'v' THEN 'view' WHEN 'm' THEN 'materialized-view'
372
+ WHEN 'S' THEN 'sequence' WHEN 'i' THEN 'index'
373
+ WHEN 'I' THEN 'index' WHEN 'f' THEN 'deferred-object'
374
+ ELSE 'opaque-object' END AS object_kind,
375
+ c.relname AS object_name, n.nspname AS namespace,
376
+ c.relowner::oid AS owner_oid, NULL::text AS parent_oid
377
+ FROM pg_catalog.pg_class c
378
+ JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
379
+ WHERE n.nspname = $1
380
+ UNION ALL
381
+ SELECT 'pg_class', 'pg_class'::regclass, c.oid::text, a.attnum::int,
382
+ 'column', a.attname, n.nspname, c.relowner::oid, c.oid::text
383
+ FROM pg_catalog.pg_attribute a
384
+ JOIN pg_catalog.pg_class c ON c.oid = a.attrelid
385
+ JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
386
+ WHERE n.nspname = $1 AND c.relkind IN ('r', 'p', 'v', 'm')
387
+ AND a.attnum > 0 AND NOT a.attisdropped
388
+ UNION ALL
389
+ SELECT 'pg_proc', 'pg_proc'::regclass, p.oid::text, 0,
390
+ 'routine', p.proname, n.nspname, p.proowner::oid, NULL
391
+ FROM pg_catalog.pg_proc p
392
+ JOIN pg_catalog.pg_namespace n ON n.oid = p.pronamespace
393
+ WHERE n.nspname = $1 AND p.prokind IN ('f', 'p', 'a', 'w')
394
+ UNION ALL
395
+ SELECT 'pg_type', 'pg_type'::regclass, t.oid::text, 0,
396
+ CASE t.typtype WHEN 'e' THEN 'enum' ELSE 'domain' END,
397
+ t.typname, n.nspname, t.typowner::oid, NULL
398
+ FROM pg_catalog.pg_type t
399
+ JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
400
+ WHERE n.nspname = $1 AND t.typtype IN ('e', 'd')
401
+ UNION ALL
402
+ SELECT 'pg_collation', 'pg_collation'::regclass, c.oid::text, 0,
403
+ 'collation', c.collname, n.nspname, c.collowner::oid, NULL
404
+ FROM pg_catalog.pg_collation c
405
+ JOIN pg_catalog.pg_namespace n ON n.oid = c.collnamespace
406
+ WHERE n.nspname = $1
407
+ UNION ALL
408
+ SELECT 'pg_extension', 'pg_extension'::regclass, e.oid::text, 0,
409
+ 'extension', e.extname, n.nspname, e.extowner::oid, NULL
410
+ FROM pg_catalog.pg_extension e
411
+ JOIN pg_catalog.pg_namespace n ON n.oid = e.extnamespace
412
+ WHERE n.nspname = $1
413
+ UNION ALL
414
+ SELECT 'pg_constraint', 'pg_constraint'::regclass, con.oid::text, 0,
415
+ 'constraint', con.conname, n.nspname, c.relowner::oid,
416
+ con.conrelid::text
417
+ FROM pg_catalog.pg_constraint con
418
+ JOIN pg_catalog.pg_class c ON c.oid = con.conrelid
419
+ JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
420
+ WHERE n.nspname = $1
421
+ UNION ALL
422
+ SELECT 'pg_trigger', 'pg_trigger'::regclass, t.oid::text, 0,
423
+ 'trigger', t.tgname, n.nspname, c.relowner::oid,
424
+ t.tgrelid::text
425
+ FROM pg_catalog.pg_trigger t
426
+ JOIN pg_catalog.pg_class c ON c.oid = t.tgrelid
427
+ JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
428
+ WHERE n.nspname = $1 AND NOT t.tgisinternal
429
+ UNION ALL
430
+ SELECT 'pg_policy', 'pg_policy'::regclass, p.oid::text, 0,
431
+ 'policy', p.polname, n.nspname, c.relowner::oid,
432
+ p.polrelid::text
433
+ FROM pg_catalog.pg_policy p
434
+ JOIN pg_catalog.pg_class c ON c.oid = p.polrelid
435
+ JOIN pg_catalog.pg_namespace n ON n.oid = c.relnamespace
436
+ WHERE n.nspname = $1
437
+ )
438
+ SELECT o.catalog_relation, o.object_oid, o.object_subid,
439
+ o.object_kind, o.object_name, o.namespace, o.parent_oid,
440
+ d.description, pg_get_userbyid(o.owner_oid) AS owner
441
+ FROM objects o
442
+ LEFT JOIN pg_catalog.pg_description d
443
+ ON d.classoid = o.catalog_oid AND d.objoid::text = o.object_oid
444
+ AND d.objsubid = o.object_subid
445
+ ORDER BY o.catalog_relation, o.object_oid, o.object_subid
446
+ `;
447
+ async function query(connection, text, parameters, options, diagnostics, operation) {
448
+ try {
449
+ return await connection.query({
450
+ text,
451
+ parameters
452
+ }, { signal: options.signal });
453
+ } catch {
454
+ diagnostics.push(createIntrospectionDiagnostic({
455
+ severity: "error",
456
+ code: "query-failed",
457
+ message: `PostgreSQL catalog query failed while reading ${operation}`,
458
+ path: [operation],
459
+ remediation: "Check PostgreSQL permissions and the selected schema."
460
+ }));
461
+ return [];
462
+ }
463
+ }
464
+ function serverInfo(row, diagnostics) {
465
+ const rawVersion = text(row?.server_version) ?? "unknown";
466
+ const numericVersion = number(row?.server_version_num);
467
+ if (!row) diagnostics.push(createIntrospectionDiagnostic({
468
+ severity: "error",
469
+ code: "unsupported-server",
470
+ message: "PostgreSQL server version metadata was unavailable",
471
+ path: ["server"],
472
+ remediation: "Provide access to current_setting(server_version_num)."
473
+ }));
474
+ const major = numericVersion ? Math.floor(numericVersion / 1e4) : void 0;
475
+ const supported = major !== void 0 && major >= 12;
476
+ if (!supported) diagnostics.push(createIntrospectionDiagnostic({
477
+ severity: "error",
478
+ code: "unsupported-server",
479
+ message: "PostgreSQL introspection requires server version 12 or newer",
480
+ path: ["server", "version"],
481
+ remediation: "Use PostgreSQL 12+ or an adapter capability extension."
482
+ }));
483
+ return {
484
+ product: "postgresql",
485
+ rawVersion,
486
+ parsedVersion: major === void 0 ? void 0 : { major },
487
+ capabilities: {
488
+ generatedColumns: supported,
489
+ identityMetadata: numericVersion !== void 0 && numericVersion >= 1e5,
490
+ checkConstraints: true,
491
+ checkConstraintEnforcement: "enforced",
492
+ expressionDecompilation: true,
493
+ indexExpressions: true,
494
+ indexPredicates: true,
495
+ indexIncludedColumns: true,
496
+ namespaces: true,
497
+ visibility: "complete"
498
+ }
499
+ };
500
+ }
501
+ function emptyCatalog(namespace, diagnostics) {
502
+ return {
503
+ dialect: "postgresql",
504
+ server: {
505
+ product: "postgresql",
506
+ rawVersion: "unknown",
507
+ capabilities: {
508
+ generatedColumns: false,
509
+ identityMetadata: false,
510
+ checkConstraints: false,
511
+ checkConstraintEnforcement: "unknown",
512
+ expressionDecompilation: false,
513
+ indexExpressions: false,
514
+ indexPredicates: false,
515
+ indexIncludedColumns: false,
516
+ namespaces: false,
517
+ visibility: "unknown"
518
+ }
519
+ },
520
+ namespace: {
521
+ kind: "postgres-schema",
522
+ name: namespace
523
+ },
524
+ tables: [],
525
+ deferredObjects: [],
526
+ diagnostics: Object.freeze(diagnostics)
527
+ };
528
+ }
529
+ function viewObject(row, namespace, diagnostics) {
530
+ const physicalName = text(row.physical_name) ?? "unnamed_view";
531
+ const kind = row.relkind === "m" ? "materialized-view" : "view";
532
+ const physicalReference = reference(kind, physicalName, text(row.namespace) ?? namespace, "pg_class", "oid", row.oid);
533
+ const definition = text(row.definition);
534
+ if (definition === void 0) {
535
+ diagnostics.push(createIntrospectionDiagnostic({
536
+ severity: "warning",
537
+ code: "unmodeled-object",
538
+ message: `PostgreSQL ${kind} ${physicalName} has no recoverable definition`,
539
+ path: [
540
+ "views",
541
+ physicalName,
542
+ "definition"
543
+ ],
544
+ physicalReference,
545
+ remediation: "Grant access to pg_get_viewdef before treating this object as migration input."
546
+ }));
547
+ return deferredCatalogObject(kind === "view" ? "view" : "materialized-view", physicalName, physicalReference, [{
548
+ name: "definition",
549
+ value: expression("/* view definition unavailable */", "decompiler", physicalReference)
550
+ }]);
551
+ }
552
+ const options = stringArray(row.reloptions);
553
+ const checkOption = (() => {
554
+ const value = text(row.check_option)?.toLowerCase();
555
+ return value === "none" || value === "local" || value === "cascaded" ? value : void 0;
556
+ })();
557
+ return {
558
+ kind,
559
+ id: stableId(physicalName),
560
+ identitySource: "physical-name",
561
+ physicalName,
562
+ columns: [],
563
+ definition: expression(definition, "decompiler", physicalReference),
564
+ ...checkOption === "local" || checkOption === "cascaded" ? { checkOption } : checkOption === "none" ? { checkOption: "none" } : {},
565
+ ...booleanOption(options, "security_barrier") === void 0 ? {} : { securityBarrier: booleanOption(options, "security_barrier") },
566
+ ...booleanOption(options, "security_invoker") === void 0 ? {} : { securityInvoker: booleanOption(options, "security_invoker") },
567
+ reference: physicalReference
568
+ };
569
+ }
570
+ function columnKey(tableOid, ordinalPosition) {
571
+ return `${text(tableOid) ?? "unknown"}:${number(ordinalPosition) ?? 0}`;
572
+ }
573
+ function compareOrdinal(left, right) {
574
+ return (number(left.ordinal_position) ?? 0) - (number(right.ordinal_position) ?? 0);
575
+ }
576
+ function identityOptions(row) {
577
+ const options = {};
578
+ for (const [key, value] of [
579
+ ["start", row.seqstart],
580
+ ["increment", row.seqincrement],
581
+ ["minimum", row.seqmin],
582
+ ["maximum", row.seqmax],
583
+ ["cache", row.seqcache]
584
+ ]) {
585
+ const fact = literalFact(value);
586
+ if (fact !== void 0) options[key] = fact;
587
+ }
588
+ if (row.seqcycle !== void 0) options.cycle = {
589
+ kind: "literal",
590
+ value: boolean(row.seqcycle)
591
+ };
592
+ if (text(row.sequence_type) !== void 0) options.type = {
593
+ kind: "literal",
594
+ value: text(row.sequence_type)
595
+ };
596
+ return options;
597
+ }
598
+ function sequenceObject(row, namespace, tableByOid, diagnostics) {
599
+ const physicalName = text(row.physical_name) ?? `sequence_${text(row.oid) ?? "unknown"}`;
600
+ const physicalReference = reference("sequence", physicalName, text(row.namespace) ?? namespace, "pg_class", "oid", row.oid);
601
+ const ownedTable = tableByOid.get(text(row.owned_table_oid));
602
+ const ownedBy = ownedTable ? {
603
+ kind: "table",
604
+ id: ownedTable.id
605
+ } : void 0;
606
+ const ownedTableOid = text(row.owned_table_oid);
607
+ const ownedColumnPosition = number(row.owned_column_position);
608
+ if (ownedTableOid !== void 0 && ownedBy === void 0) diagnostics.push(createIntrospectionDiagnostic({
609
+ severity: "warning",
610
+ code: "unresolved-reference",
611
+ message: `PostgreSQL sequence ${physicalName} has an ownership target outside the selected schema`,
612
+ path: [
613
+ "sequences",
614
+ physicalName,
615
+ "ownedBy"
616
+ ],
617
+ physicalReference,
618
+ remediation: "Select the owning table schema or inspect the retained ownership catalog reference."
619
+ }));
620
+ const data = {};
621
+ if (ownedTableOid !== void 0) data.ownedTableOid = ownedTableOid;
622
+ if (ownedColumnPosition !== void 0) data.ownedColumnPosition = ownedColumnPosition;
623
+ return {
624
+ kind: "sequence",
625
+ id: stableId(physicalName),
626
+ identitySource: "physical-name",
627
+ physicalName,
628
+ storage: storage(row.native_type),
629
+ ...factIfPresent(row.seqstart) === void 0 ? {} : { start: factIfPresent(row.seqstart) },
630
+ ...factIfPresent(row.seqincrement) === void 0 ? {} : { increment: factIfPresent(row.seqincrement) },
631
+ ...factIfPresent(row.seqmin) === void 0 ? {} : { minimum: factIfPresent(row.seqmin) },
632
+ ...factIfPresent(row.seqmax) === void 0 ? {} : { maximum: factIfPresent(row.seqmax) },
633
+ ...factIfPresent(row.seqcache) === void 0 ? {} : { cache: factIfPresent(row.seqcache) },
634
+ ...row.seqcycle === void 0 || row.seqcycle === null ? {} : { cycle: boolean(row.seqcycle) },
635
+ ...ownedBy === void 0 ? {} : { ownedBy },
636
+ ...Object.keys(data).length === 0 ? {} : { dialect: {
637
+ dialect: "postgresql",
638
+ version: 1,
639
+ data
640
+ } },
641
+ reference: physicalReference
642
+ };
643
+ }
644
+ function mapEnums(rows, namespace) {
645
+ const groups = /* @__PURE__ */ new Map();
646
+ for (const row of rows) {
647
+ const key = text(row.oid) ?? text(row.physical_name) ?? "unknown";
648
+ const values = groups.get(key) ?? [];
649
+ values.push(row);
650
+ groups.set(key, values);
651
+ }
652
+ return [...groups.values()].map((enumRows) => {
653
+ const first = enumRows[0];
654
+ const physicalName = text(first.physical_name) ?? `enum_${text(first.oid) ?? "unknown"}`;
655
+ const physicalReference = reference("enum", physicalName, text(first.namespace) ?? namespace, "pg_type", "oid", first.oid);
656
+ const values = [...enumRows].sort((left, right) => (number(left.ordinal_position) ?? 0) - (number(right.ordinal_position) ?? 0)).map((row, index) => ({
657
+ value: text(row.value) ?? "",
658
+ ordinalPosition: index + 1,
659
+ provenance: {
660
+ kind: "catalog",
661
+ dialect: "postgresql",
662
+ reference: reference("enum", physicalName, text(row.namespace) ?? namespace, "pg_enum", "oid", row.value_oid)
663
+ }
664
+ }));
665
+ return {
666
+ kind: "enum",
667
+ id: stableId(physicalName),
668
+ identitySource: "physical-name",
669
+ physicalName,
670
+ values,
671
+ reference: physicalReference
672
+ };
673
+ });
674
+ }
675
+ function mapDomains(rows, constraintRows, namespace) {
676
+ const constraintsByDomain = groupBy(constraintRows, (row) => text(row.domain_oid) ?? "unknown");
677
+ return rows.map((row) => {
678
+ const physicalName = text(row.physical_name) ?? `domain_${text(row.oid) ?? "unknown"}`;
679
+ const physicalReference = reference("domain", physicalName, text(row.namespace) ?? namespace, "pg_type", "oid", row.oid);
680
+ const domainConstraints = (constraintsByDomain.get(text(row.oid)) ?? []).map((constraintRow) => {
681
+ const constraintName = text(constraintRow.physical_name) ?? `domain_constraint_${text(constraintRow.oid) ?? "unknown"}`;
682
+ const constraintReference = reference("constraint", constraintName, text(row.namespace) ?? namespace, "pg_constraint", "oid", constraintRow.oid);
683
+ return {
684
+ kind: "check",
685
+ id: stableId(constraintName),
686
+ identitySource: "physical-name",
687
+ physicalName: constraintName,
688
+ expression: expression(text(constraintRow.definition) ?? "CHECK (true)", "decompiler", constraintReference),
689
+ deferrable: constraintRow.condeferrable === void 0 ? void 0 : boolean(constraintRow.condeferrable),
690
+ initially: constraintRow.condeferred === void 0 ? void 0 : boolean(constraintRow.condeferred) ? "deferred" : "immediate",
691
+ validated: constraintRow.convalidated === void 0 ? void 0 : boolean(constraintRow.convalidated),
692
+ reference: constraintReference
693
+ };
694
+ });
695
+ return {
696
+ kind: "domain",
697
+ id: stableId(physicalName),
698
+ identitySource: "physical-name",
699
+ physicalName,
700
+ storage: storage(row.native_type),
701
+ ...row.nullable === void 0 || row.nullable === null ? {} : { nullable: boolean(row.nullable) },
702
+ ...factIfPresent(row.default_expression) === void 0 ? {} : { default: factIfPresent(row.default_expression) },
703
+ ...domainConstraints.length === 0 ? {} : { constraints: domainConstraints },
704
+ reference: physicalReference
705
+ };
706
+ });
707
+ }
708
+ function collationObject(row, namespace) {
709
+ const physicalName = text(row.physical_name) ?? `collation_${text(row.oid) ?? "unknown"}`;
710
+ return {
711
+ kind: "collation",
712
+ id: stableId(physicalName),
713
+ identitySource: "physical-name",
714
+ physicalName,
715
+ ...text(row.collprovider) === void 0 ? {} : { provider: text(row.collprovider) },
716
+ ...(text(row.colliculocale) ?? text(row.collcollate) ?? text(row.collctype)) === void 0 ? {} : { locale: text(row.colliculocale) ?? text(row.collcollate) ?? text(row.collctype) },
717
+ ...row.collisdeterministic === void 0 || row.collisdeterministic === null ? {} : { deterministic: boolean(row.collisdeterministic) },
718
+ ...text(row.collversion) === void 0 ? {} : { version: text(row.collversion) },
719
+ reference: reference("collation", physicalName, text(row.namespace) ?? namespace, "pg_collation", "oid", row.oid)
720
+ };
721
+ }
722
+ function triggerObject(row, namespace, relationReferences, diagnostics) {
723
+ const physicalName = text(row.physical_name) ?? `trigger_${text(row.oid) ?? "unknown"}`;
724
+ const physicalReference = reference("trigger", physicalName, text(row.namespace) ?? namespace, "pg_trigger", "oid", row.oid);
725
+ const table = relationReferences.get(text(row.table_oid));
726
+ const definition = text(row.definition);
727
+ if (table === void 0 || definition === void 0) {
728
+ diagnostics.push(createIntrospectionDiagnostic({
729
+ severity: "warning",
730
+ code: table === void 0 ? "unresolved-reference" : "unmodeled-object",
731
+ message: table === void 0 ? `PostgreSQL trigger ${physicalName} has no selected parent relation` : `PostgreSQL trigger ${physicalName} has no recoverable definition`,
732
+ path: ["triggers", physicalName],
733
+ physicalReference,
734
+ remediation: "Retain the deferred trigger until its parent relation and definition are visible."
735
+ }));
736
+ return deferredCatalogObject("trigger", physicalName, physicalReference, [...table === void 0 ? [{
737
+ name: "tableOid",
738
+ value: text(row.table_oid) ?? "unknown"
739
+ }] : [], ...definition === void 0 ? [] : [{
740
+ name: "definition",
741
+ value: expression(definition, "decompiler", physicalReference)
742
+ }]]);
743
+ }
744
+ const triggerType = number(row.trigger_type) ?? 0;
745
+ const timing = triggerType & 64 ? "instead-of" : triggerType & 2 ? "before" : "after";
746
+ const events = triggerEvents(triggerType);
747
+ const mode = triggerType & 1 ? "row" : "statement";
748
+ const enabled = triggerEnabled(row.tgenabled);
749
+ return {
750
+ kind: "trigger",
751
+ id: stableId(physicalName),
752
+ identitySource: "physical-name",
753
+ physicalName,
754
+ table,
755
+ timing,
756
+ events,
757
+ orientation: mode,
758
+ ...text(row.condition) === void 0 ? {} : { condition: expression(text(row.condition), "decompiler", physicalReference) },
759
+ body: expression(definition, "decompiler", physicalReference),
760
+ ...enabled === void 0 ? {} : { enabled },
761
+ reference: physicalReference
762
+ };
763
+ }
764
+ function mapRoutines(rows, parameterRows, namespace, diagnostics) {
765
+ const parametersByRoutine = groupBy(parameterRows, (row) => text(row.routine_oid) ?? "unknown");
766
+ const names = /* @__PURE__ */ new Map();
767
+ for (const row of rows) {
768
+ const name = text(row.physical_name) ?? `routine_${text(row.oid) ?? "unknown"}`;
769
+ names.set(name, (names.get(name) ?? 0) + 1);
770
+ }
771
+ return rows.map((row) => {
772
+ const physicalName = text(row.physical_name) ?? `routine_${text(row.oid) ?? "unknown"}`;
773
+ const physicalReference = reference("routine", physicalName, text(row.namespace) ?? namespace, "pg_proc", "oid", row.oid);
774
+ const identityArguments = text(row.identity_arguments);
775
+ const defaultArguments = text(row.argument_defaults);
776
+ if (defaultArguments !== void 0) diagnostics.push(createIntrospectionDiagnostic({
777
+ severity: "info",
778
+ code: "unmodeled-object",
779
+ message: `PostgreSQL routine ${physicalName} retains its argument defaults as opaque catalog text`,
780
+ path: [
781
+ "routines",
782
+ physicalName,
783
+ "argumentDefaults"
784
+ ],
785
+ physicalReference,
786
+ remediation: "Review routine argument defaults before using the complete snapshot for migration planning."
787
+ }));
788
+ if (text(row.definition) === void 0) diagnostics.push(createIntrospectionDiagnostic({
789
+ severity: "warning",
790
+ code: "unmodeled-object",
791
+ message: `PostgreSQL routine ${physicalName} has no recoverable definition`,
792
+ path: [
793
+ "routines",
794
+ physicalName,
795
+ "definition"
796
+ ],
797
+ physicalReference,
798
+ remediation: "Grant access to pg_get_functiondef before treating this routine as migration input."
799
+ }));
800
+ const routineUnknownFields = [...identityArguments === void 0 ? [] : [{
801
+ name: "identityArguments",
802
+ value: expression(identityArguments, "decompiler", physicalReference)
803
+ }], ...defaultArguments === void 0 ? [] : [{
804
+ name: "argumentDefaults",
805
+ value: expression(defaultArguments, "decompiler", physicalReference)
806
+ }]];
807
+ const parameters = (parametersByRoutine.get(text(row.oid)) ?? []).sort((left, right) => (number(left.ordinal_position) ?? 0) - (number(right.ordinal_position) ?? 0)).map((parameter) => ({
808
+ ...text(parameter.parameter_name) === void 0 ? {} : { name: text(parameter.parameter_name) },
809
+ ...routineParameterMode(parameter.mode) === void 0 ? {} : { mode: routineParameterMode(parameter.mode) },
810
+ storage: storage(parameter.native_type),
811
+ ordinalPosition: number(parameter.ordinal_position) ?? 0,
812
+ provenance: {
813
+ kind: "catalog",
814
+ dialect: "postgresql",
815
+ reference: physicalReference
816
+ }
817
+ }));
818
+ return {
819
+ kind: "routine",
820
+ id: stableId((names.get(physicalName) ?? 0) < 2 || identityArguments === void 0 ? physicalName : `${physicalName}_${identityArguments.replace(/[^a-zA-Z0-9_]+/g, "_")}`),
821
+ identitySource: "physical-name",
822
+ physicalName,
823
+ routineKind: routineKind(row.prokind),
824
+ parameters,
825
+ ...text(row.return_type) === void 0 ? {} : { returnType: storage(row.return_type) },
826
+ ...text(row.language) === void 0 ? {} : { language: text(row.language) },
827
+ ...text(row.definition) === void 0 ? {} : { body: expression(text(row.definition), "decompiler", physicalReference) },
828
+ ...routineVolatility(row.provolatile) === void 0 ? {} : { volatility: routineVolatility(row.provolatile) },
829
+ ...routineParallel(row.proparallel) === void 0 ? {} : { parallel: routineParallel(row.proparallel) },
830
+ ...row.prosecdef === void 0 || row.prosecdef === null ? {} : { security: boolean(row.prosecdef) ? "definer" : "invoker" },
831
+ ...routineUnknownFields.length === 0 ? {} : { unknownFields: routineUnknownFields },
832
+ reference: physicalReference
833
+ };
834
+ });
835
+ }
836
+ function partitionObject(row, namespace, tableByOid, diagnostics) {
837
+ const physicalName = text(row.physical_name) ?? `partition_${text(row.partition_oid) ?? "unknown"}`;
838
+ const physicalReference = reference("partition", physicalName, text(row.namespace) ?? namespace, "pg_class", "oid", row.partition_oid);
839
+ const parent = tableByOid.get(text(row.parent_oid));
840
+ if (parent === void 0) diagnostics.push(createIntrospectionDiagnostic({
841
+ severity: "error",
842
+ code: "unresolved-reference",
843
+ message: `PostgreSQL partition ${physicalName} has no parent table in the selected schema`,
844
+ path: [
845
+ "partitions",
846
+ physicalName,
847
+ "parent"
848
+ ],
849
+ physicalReference,
850
+ remediation: "Select the parent table schema before mapping partitions."
851
+ }));
852
+ const parentReference = parent ? {
853
+ kind: "table",
854
+ id: parent.id
855
+ } : {
856
+ kind: "table",
857
+ id: stableId(`missing_parent_${text(row.parent_oid) ?? "unknown"}`)
858
+ };
859
+ const keyColumns = partitionKeyColumns(row.key_attributes, parent?.columns ?? []);
860
+ const bound = text(row.bound);
861
+ return {
862
+ kind: "partition",
863
+ id: stableId(physicalName),
864
+ identitySource: "physical-name",
865
+ physicalName,
866
+ parent: parentReference,
867
+ strategy: partitionStrategy(row.partstrat),
868
+ ...keyColumns.length === 0 ? {} : { keyColumns },
869
+ ...bound === void 0 ? {} : { bound: expression(bound, "decompiler", physicalReference) },
870
+ ...bound !== void 0 && /^default$/i.test(bound.trim()) ? { default: true } : {},
871
+ reference: physicalReference
872
+ };
873
+ }
874
+ function policyObject(row, namespace, tableByOid, diagnostics) {
875
+ const physicalName = text(row.physical_name) ?? `policy_${text(row.oid) ?? "unknown"}`;
876
+ const physicalReference = reference("policy", physicalName, text(row.namespace) ?? namespace, "pg_policy", "oid", row.oid);
877
+ const table = tableByOid.get(text(row.table_oid));
878
+ if (table === void 0) diagnostics.push(createIntrospectionDiagnostic({
879
+ severity: "error",
880
+ code: "unresolved-reference",
881
+ message: `PostgreSQL policy ${physicalName} has no selected table`,
882
+ path: [
883
+ "policies",
884
+ physicalName,
885
+ "table"
886
+ ],
887
+ physicalReference,
888
+ remediation: "Select the policy table schema before mapping row-level security."
889
+ }));
890
+ return {
891
+ kind: "policy",
892
+ id: stableId(physicalName),
893
+ identitySource: "physical-name",
894
+ physicalName,
895
+ table: table ? {
896
+ kind: "table",
897
+ id: table.id
898
+ } : {
899
+ kind: "table",
900
+ id: stableId(`missing_table_${text(row.table_oid) ?? "unknown"}`)
901
+ },
902
+ command: policyCommand(row.polcmd),
903
+ ...stringArray(row.roles).length === 0 ? {} : { roles: stringArray(row.roles) },
904
+ ...row.polpermissive === void 0 || row.polpermissive === null ? {} : { permissive: boolean(row.polpermissive) },
905
+ ...text(row.using_expression) === void 0 ? {} : { using: expression(text(row.using_expression), "decompiler", physicalReference) },
906
+ ...text(row.check_expression) === void 0 ? {} : { check: expression(text(row.check_expression), "decompiler", physicalReference) },
907
+ reference: physicalReference
908
+ };
909
+ }
910
+ function extensionObject(row, namespace) {
911
+ const physicalName = text(row.physical_name) ?? `extension_${text(row.oid) ?? "unknown"}`;
912
+ const physicalReference = reference("extension", physicalName, text(row.namespace) ?? namespace, "pg_extension", "oid", row.oid);
913
+ const data = { relocatable: boolean(row.extrelocatable) };
914
+ const configuration = {};
915
+ if (text(row.config_relations) !== void 0) configuration.relations = text(row.config_relations);
916
+ if (text(row.config_conditions) !== void 0) configuration.conditions = text(row.config_conditions);
917
+ return {
918
+ kind: "extension",
919
+ id: stableId(physicalName),
920
+ identitySource: "physical-name",
921
+ physicalName,
922
+ extensionName: physicalName,
923
+ ...text(row.extversion) === void 0 ? {} : { extensionVersion: text(row.extversion) },
924
+ ...text(row.namespace) === void 0 ? {} : { schema: text(row.namespace) },
925
+ data,
926
+ ...Object.keys(configuration).length === 0 ? {} : { configuration },
927
+ dialect: {
928
+ dialect: "postgresql",
929
+ version: 1,
930
+ data: { relocatable: boolean(row.extrelocatable) }
931
+ },
932
+ reference: physicalReference
933
+ };
934
+ }
935
+ function deferredCatalogObject(objectKind, physicalName, physicalReference, unknownFields = []) {
936
+ return {
937
+ kind: "deferred-object",
938
+ objectKind,
939
+ id: stableId(`deferred_${objectKind}_${physicalName}`),
940
+ identitySource: "physical-name",
941
+ physicalName,
942
+ reference: physicalReference,
943
+ ...unknownFields.length === 0 ? {} : { unknownFields }
944
+ };
945
+ }
946
+ function triggerEvents(triggerType) {
947
+ const events = [];
948
+ if (triggerType & 4) events.push("insert");
949
+ if (triggerType & 8) events.push("delete");
950
+ if (triggerType & 16) events.push("update");
951
+ if (triggerType & 32) events.push("truncate");
952
+ return events.sort();
953
+ }
954
+ function triggerEnabled(value) {
955
+ const code = text(value)?.toUpperCase();
956
+ if (code === "D") return false;
957
+ if (code === "O" || code === "R" || code === "A") return true;
958
+ }
959
+ function routineKind(value) {
960
+ return {
961
+ f: "function",
962
+ p: "procedure",
963
+ a: "aggregate",
964
+ w: "window"
965
+ }[text(value)] ?? "unknown";
966
+ }
967
+ function routineParameterMode(value) {
968
+ return {
969
+ i: "in",
970
+ o: "out",
971
+ b: "inout",
972
+ v: "variadic",
973
+ t: "table"
974
+ }[text(value)];
975
+ }
976
+ function routineVolatility(value) {
977
+ return {
978
+ i: "immutable",
979
+ s: "stable",
980
+ v: "volatile"
981
+ }[text(value)];
982
+ }
983
+ function routineParallel(value) {
984
+ return {
985
+ s: "safe",
986
+ r: "restricted",
987
+ u: "unsafe"
988
+ }[text(value)];
989
+ }
990
+ function partitionStrategy(value) {
991
+ return {
992
+ r: "range",
993
+ l: "list",
994
+ h: "hash"
995
+ }[text(value)] ?? "unknown";
996
+ }
997
+ function partitionKeyColumns(value, columns) {
998
+ const byOrdinal = new Map(columns.map((column) => [column.ordinalPosition, column.physicalName]));
999
+ return integerArray(value).filter((position) => position > 0).map((position) => byOrdinal.get(position) ?? `attnum_${position}`);
1000
+ }
1001
+ function policyCommand(value) {
1002
+ return {
1003
+ "*": "all",
1004
+ r: "select",
1005
+ a: "insert",
1006
+ w: "update",
1007
+ d: "delete"
1008
+ }[text(value)] ?? "unknown";
1009
+ }
1010
+ function storage(value) {
1011
+ return { nativeType: text(value) ?? "unknown" };
1012
+ }
1013
+ function factIfPresent(value) {
1014
+ if (value === void 0 || value === null) return;
1015
+ return literalFact(value);
1016
+ }
1017
+ function literalFact(value) {
1018
+ if (value === void 0) return;
1019
+ if (value === null) return {
1020
+ kind: "literal",
1021
+ value: null
1022
+ };
1023
+ if (typeof value === "boolean") return {
1024
+ kind: "literal",
1025
+ value
1026
+ };
1027
+ if (typeof value === "bigint") return {
1028
+ kind: "literal",
1029
+ value
1030
+ };
1031
+ if (typeof value === "number") return Number.isFinite(value) ? {
1032
+ kind: "literal",
1033
+ value
1034
+ } : {
1035
+ kind: "literal",
1036
+ value: String(value)
1037
+ };
1038
+ const textValue = String(value);
1039
+ if (/^[+-]?\d+$/.test(textValue.trim())) try {
1040
+ const integerValue = BigInt(textValue);
1041
+ if (integerValue > BigInt(Number.MAX_SAFE_INTEGER) || integerValue < BigInt(Number.MIN_SAFE_INTEGER)) return {
1042
+ kind: "literal",
1043
+ value: integerValue
1044
+ };
1045
+ } catch {}
1046
+ const numericValue = Number(textValue);
1047
+ return textValue.trim() !== "" && Number.isFinite(numericValue) ? {
1048
+ kind: "literal",
1049
+ value: numericValue
1050
+ } : {
1051
+ kind: "literal",
1052
+ value: textValue
1053
+ };
1054
+ }
1055
+ function relationTable(row) {
1056
+ const physicalName = text(row.relname) ?? "unnamed_table";
1057
+ return {
1058
+ kind: "table",
1059
+ id: stableId(physicalName),
1060
+ identitySource: "physical-name",
1061
+ physicalName,
1062
+ reference: reference("table", physicalName, text(row.namespace), "pg_class", "oid", row.oid),
1063
+ columns: [],
1064
+ constraints: [],
1065
+ indexes: [],
1066
+ unknownFields: boolean(row.relispartition) ? [{
1067
+ name: "partitioned",
1068
+ value: true
1069
+ }] : void 0
1070
+ };
1071
+ }
1072
+ function deferredObject(row, objectKind = "other") {
1073
+ const physicalName = text(row.relname) ?? "unnamed_object";
1074
+ return {
1075
+ kind: "deferred-object",
1076
+ objectKind,
1077
+ id: stableId(`deferred:${objectKind}:${physicalName}`),
1078
+ identitySource: "physical-name",
1079
+ physicalName,
1080
+ reference: reference("deferred-object", physicalName, text(row.namespace), "pg_class", "oid", row.oid)
1081
+ };
1082
+ }
1083
+ function opaqueRelationObject(row, namespace, diagnostics) {
1084
+ const physicalName = text(row.relname) ?? "unnamed_object";
1085
+ const relkind = text(row.relkind) ?? "unknown";
1086
+ const physicalReference = reference("opaque-object", physicalName, text(row.namespace) ?? namespace, "pg_class", "oid", row.oid);
1087
+ diagnostics.push(createIntrospectionDiagnostic({
1088
+ severity: "warning",
1089
+ code: "unmodeled-object",
1090
+ message: `PostgreSQL relation ${physicalName} (${relkind}) was retained as an opaque object`,
1091
+ path: ["opaqueObjects", physicalName],
1092
+ physicalReference,
1093
+ remediation: "Inspect the opaque object before treating it as migration input."
1094
+ }));
1095
+ return {
1096
+ kind: "opaque-object",
1097
+ id: stableId(`relation:${relkind}:${physicalName}`),
1098
+ identitySource: "physical-name",
1099
+ physicalName,
1100
+ objectKind: `postgres-relation:${relkind}`,
1101
+ data: {
1102
+ relkind,
1103
+ relispartition: boolean(row.relispartition)
1104
+ },
1105
+ reference: physicalReference
1106
+ };
1107
+ }
1108
+ function column(row, table, namespace, identityOptionValues) {
1109
+ const physicalName = text(row.physical_name) ?? "unnamed_column";
1110
+ const defaultExpression = text(row.default_expression);
1111
+ const identityValue = text(row.attidentity);
1112
+ const generatedValue = text(row.attgenerated);
1113
+ const identity = identityValue === "a" || identityValue === "d" ? {
1114
+ kind: "identity",
1115
+ generation: identityValue === "a" ? "always" : "by-default",
1116
+ options: identityOptionValues ?? {}
1117
+ } : void 0;
1118
+ const generated = (generatedValue === "s" || generatedValue === "v") && defaultExpression ? {
1119
+ kind: "generated",
1120
+ mode: generatedValue === "s" ? "stored" : "virtual",
1121
+ expression: sql(defaultExpression, namespace, table, physicalName)
1122
+ } : void 0;
1123
+ const ordinaryDefault = defaultExpression && !identity && !generated ? {
1124
+ kind: "expression",
1125
+ expression: sql(defaultExpression, namespace, table, physicalName)
1126
+ } : void 0;
1127
+ return {
1128
+ kind: "column",
1129
+ id: stableId(physicalName),
1130
+ identitySource: "physical-name",
1131
+ physicalName,
1132
+ ordinalPosition: number(row.ordinal_position) ?? 0,
1133
+ nullable: boolean(row.nullable),
1134
+ storage: { nativeType: text(row.native_type) ?? "unknown" },
1135
+ ...ordinaryDefault ? { default: ordinaryDefault } : {},
1136
+ ...generated ? { generated } : {},
1137
+ identity,
1138
+ reference: reference("column", physicalName, namespace, "pg_attribute", "attrelid", row.table_oid)
1139
+ };
1140
+ }
1141
+ function constraint(row, table, columnsByNumber, tableByOid, namespace, diagnostics, indexReferences) {
1142
+ const kind = text(row.contype);
1143
+ const physicalName = text(row.physical_name) ?? `constraint_${text(row.oid) ?? "unknown"}`;
1144
+ const columns = integerArray(row.conkey).map((numberValue) => columnsByNumber.get(numberValue) ?? `attnum_${numberValue}`);
1145
+ const common = {
1146
+ id: stableId(physicalName),
1147
+ identitySource: "physical-name",
1148
+ physicalName,
1149
+ deferrable: boolean(row.condeferrable),
1150
+ initially: boolean(row.condeferred) ? "deferred" : "immediate",
1151
+ validated: boolean(row.convalidated),
1152
+ reference: reference("constraint", physicalName, namespace, "pg_constraint", "oid", row.oid),
1153
+ dialect: row.convalidated === false ? {
1154
+ dialect: "postgresql",
1155
+ version: 1,
1156
+ data: { notValid: true }
1157
+ } : void 0
1158
+ };
1159
+ const backingOid = text(row.backing_index_oid);
1160
+ const backing = backingOid ? indexReferences.get(`pg_class:${backingOid}`) : void 0;
1161
+ const backingIndex = backing ? {
1162
+ kind: "index",
1163
+ id: backing.id
1164
+ } : void 0;
1165
+ if (kind === "p") return {
1166
+ kind: "primary-key",
1167
+ ...common,
1168
+ columns,
1169
+ ...backingIndex === void 0 ? {} : { backingIndex }
1170
+ };
1171
+ if (kind === "u") return {
1172
+ kind: "unique",
1173
+ ...common,
1174
+ columns,
1175
+ nulls: boolean(row.indnullsnotdistinct) ? "not-distinct" : "distinct",
1176
+ ...backingIndex === void 0 ? {} : { backingIndex }
1177
+ };
1178
+ if (kind === "c") return {
1179
+ kind: "check",
1180
+ ...common,
1181
+ expression: sql(text(row.definition) ?? "CHECK (true)", namespace, table, physicalName)
1182
+ };
1183
+ if (kind !== "f") return;
1184
+ const targetTable = tableByOid.get(text(row.target_table_oid));
1185
+ if (!targetTable) {
1186
+ diagnostics.push(createIntrospectionDiagnostic({
1187
+ severity: "error",
1188
+ code: "unresolved-reference",
1189
+ message: `PostgreSQL foreign key target ${text(row.target_table_oid) ?? "unknown"} was not found`,
1190
+ path: [
1191
+ "tables",
1192
+ table.id,
1193
+ "constraints",
1194
+ physicalName
1195
+ ]
1196
+ }));
1197
+ return;
1198
+ }
1199
+ const targetColumns = integerArray(row.confkey).map((numberValue) => {
1200
+ return targetTable.columns.find((column) => column.ordinalPosition === numberValue)?.physicalName ?? `attnum_${numberValue}`;
1201
+ });
1202
+ return {
1203
+ kind: "foreign-key",
1204
+ ...common,
1205
+ columns,
1206
+ target: {
1207
+ table: targetTable.physicalName,
1208
+ columns: targetColumns
1209
+ },
1210
+ onUpdate: referentialAction(row.confupdtype),
1211
+ onDelete: referentialAction(row.confdeltype),
1212
+ match: matchType(row.confmatchtype)
1213
+ };
1214
+ }
1215
+ function mapIndexes(rows, table, columnsByNumber, namespace) {
1216
+ const grouped = /* @__PURE__ */ new Map();
1217
+ for (const row of rows) {
1218
+ const key = text(row.index_oid) ?? text(row.physical_name) ?? "unknown";
1219
+ const existing = grouped.get(key) ?? [];
1220
+ existing.push(row);
1221
+ grouped.set(key, existing);
1222
+ }
1223
+ return [...grouped.values()].map((indexRows) => {
1224
+ const orderedRows = [...indexRows].sort((left, right) => (number(left.position) ?? 0) - (number(right.position) ?? 0));
1225
+ const first = orderedRows[0];
1226
+ const physicalName = text(first.physical_name) ?? `index_${text(first.index_oid) ?? "unknown"}`;
1227
+ const keyCount = number(first.indnkeyatts) ?? indexRows.length;
1228
+ const terms = [];
1229
+ const includedColumns = [];
1230
+ for (const row of orderedRows) {
1231
+ const position = number(row.position) ?? 0;
1232
+ const attnum = number(row.attnum) ?? 0;
1233
+ const columnName = attnum > 0 ? columnsByNumber.get(attnum) : void 0;
1234
+ if (position > keyCount) {
1235
+ if (columnName) includedColumns.push(columnName);
1236
+ continue;
1237
+ }
1238
+ terms.push(columnName ? {
1239
+ kind: "column",
1240
+ column: columnName,
1241
+ position,
1242
+ ...indexTermOptions(row, text(first.method)),
1243
+ ...text(row.operator_class) === void 0 ? {} : { operatorClass: text(row.operator_class) }
1244
+ } : {
1245
+ kind: "expression",
1246
+ expression: sql(text(row.term_definition) ?? "/* expression unavailable */", namespace, table, physicalName),
1247
+ position,
1248
+ ...indexTermOptions(row, text(first.method)),
1249
+ ...text(row.operator_class) === void 0 ? {} : { operatorClass: text(row.operator_class) }
1250
+ });
1251
+ }
1252
+ return {
1253
+ kind: "index",
1254
+ id: stableId(physicalName),
1255
+ identitySource: "physical-name",
1256
+ physicalName,
1257
+ unique: boolean(first.indisunique),
1258
+ terms,
1259
+ predicate: text(first.predicate) ? sql(text(first.predicate), namespace, table, physicalName) : void 0,
1260
+ includedColumns: includedColumns.length > 0 ? includedColumns : void 0,
1261
+ method: text(first.method),
1262
+ dialect: text(first.method) && text(first.method) !== "btree" ? {
1263
+ dialect: "postgresql",
1264
+ version: 1,
1265
+ data: { method: text(first.method) }
1266
+ } : void 0,
1267
+ reference: reference("index", physicalName, namespace, "pg_class", "oid", first.index_oid)
1268
+ };
1269
+ });
1270
+ }
1271
+ function mapMetadataRows(rows, namespace, tables, views, sequences, enums, domains, collations, routines, triggers, policies, extensions, deferredObjects, opaqueObjects, indexReferences, relationReferences, diagnostics) {
1272
+ const targets = /* @__PURE__ */ new Map();
1273
+ const add = (relation, oid, object, physicalName, objectReference) => {
1274
+ const ref = objectReference ?? reference(object.kind, physicalName, namespace, relation, "oid", oid);
1275
+ targets.set(metadataKey(relation, oid, 0), {
1276
+ object,
1277
+ reference: ref,
1278
+ physicalName
1279
+ });
1280
+ };
1281
+ for (const table of tables) if (table.reference?.catalog !== void 0) add("pg_class", table.reference.catalog.value, {
1282
+ kind: "table",
1283
+ id: table.id
1284
+ }, table.physicalName, table.reference);
1285
+ for (const view of views) if (view.reference?.catalog !== void 0) add("pg_class", view.reference.catalog.value, {
1286
+ kind: view.kind,
1287
+ id: view.id
1288
+ }, view.physicalName, view.reference);
1289
+ for (const sequence of sequences) if (sequence.reference?.catalog !== void 0) add("pg_class", sequence.reference.catalog.value, {
1290
+ kind: "sequence",
1291
+ id: sequence.id
1292
+ }, sequence.physicalName, sequence.reference);
1293
+ for (const deferred of deferredObjects) if (deferred.reference?.catalog !== void 0 && deferred.id !== void 0) add("pg_class", deferred.reference.catalog.value, {
1294
+ kind: "deferred-object",
1295
+ id: deferred.id
1296
+ }, deferred.physicalName, deferred.reference);
1297
+ for (const opaque of opaqueObjects) if (opaque.reference?.catalog !== void 0) add("pg_class", opaque.reference.catalog.value, {
1298
+ kind: "opaque-object",
1299
+ id: opaque.id
1300
+ }, opaque.physicalName, opaque.reference);
1301
+ for (const index of indexReferences.values()) if (index.reference?.catalog !== void 0) add("pg_class", index.reference.catalog.value, {
1302
+ kind: "index",
1303
+ id: index.id
1304
+ }, index.physicalName, index.reference);
1305
+ for (const enumObject of enums) if (enumObject.reference?.catalog !== void 0) add("pg_type", enumObject.reference.catalog.value, {
1306
+ kind: "enum",
1307
+ id: enumObject.id
1308
+ }, enumObject.physicalName, enumObject.reference);
1309
+ for (const domain of domains) if (domain.reference?.catalog !== void 0) add("pg_type", domain.reference.catalog.value, {
1310
+ kind: "domain",
1311
+ id: domain.id
1312
+ }, domain.physicalName, domain.reference);
1313
+ for (const collation of collations) if (collation.reference?.catalog !== void 0) add("pg_collation", collation.reference.catalog.value, {
1314
+ kind: "collation",
1315
+ id: collation.id
1316
+ }, collation.physicalName, collation.reference);
1317
+ for (const routine of routines) if (routine.reference?.catalog !== void 0) add("pg_proc", routine.reference.catalog.value, {
1318
+ kind: "routine",
1319
+ id: routine.id
1320
+ }, routine.physicalName, routine.reference);
1321
+ for (const trigger of triggers) if (trigger.reference?.catalog !== void 0) add("pg_trigger", trigger.reference.catalog.value, {
1322
+ kind: "trigger",
1323
+ id: trigger.id
1324
+ }, trigger.physicalName, trigger.reference);
1325
+ for (const policy of policies) if (policy.reference?.catalog !== void 0) add("pg_policy", policy.reference.catalog.value, {
1326
+ kind: "policy",
1327
+ id: policy.id
1328
+ }, policy.physicalName, policy.reference);
1329
+ for (const extension of extensions) if (extension.reference?.catalog !== void 0) add("pg_extension", extension.reference.catalog.value, {
1330
+ kind: "extension",
1331
+ id: extension.id
1332
+ }, extension.physicalName, extension.reference);
1333
+ for (const table of tables) addNestedColumns(targets, "pg_class", table, namespace);
1334
+ for (const view of views) addNestedColumns(targets, "pg_class", view, namespace);
1335
+ for (const table of tables) for (const constraint of table.constraints) if (constraint.reference?.catalog !== void 0) targets.set(metadataKey("pg_constraint", constraint.reference.catalog.value, 0), {
1336
+ object: {
1337
+ kind: "constraint",
1338
+ id: constraint.id
1339
+ },
1340
+ reference: constraint.reference,
1341
+ physicalName: constraint.physicalName ?? constraint.id
1342
+ });
1343
+ for (const domain of domains) for (const constraint of domain.constraints ?? []) if (constraint.reference?.catalog !== void 0) targets.set(metadataKey("pg_constraint", constraint.reference.catalog.value, 0), {
1344
+ object: {
1345
+ kind: "constraint",
1346
+ id: constraint.id
1347
+ },
1348
+ reference: constraint.reference,
1349
+ physicalName: constraint.physicalName ?? constraint.id
1350
+ });
1351
+ const comments = [];
1352
+ const ownership = [];
1353
+ const opaque = [];
1354
+ for (const [index, row] of rows.entries()) {
1355
+ const relation = text(row.catalog_relation) ?? "unknown";
1356
+ const oid = text(row.object_oid);
1357
+ const subid = number(row.object_subid) ?? 0;
1358
+ const target = targets.get(metadataKey(relation, oid, subid));
1359
+ if (target === void 0) {
1360
+ const unknownReference = reference("opaque-object", text(row.object_name) ?? `metadata_${oid ?? "unknown"}`, text(row.namespace) ?? namespace, relation, "oid", oid);
1361
+ diagnostics.push(createIntrospectionDiagnostic({
1362
+ severity: "warning",
1363
+ code: "unmodeled-object",
1364
+ message: `PostgreSQL metadata row for ${text(row.object_name) ?? "unknown object"} could not be attached to a normalized object`,
1365
+ path: ["metadata", index],
1366
+ physicalReference: unknownReference,
1367
+ remediation: "Inspect the retained opaque metadata record before using it as migration input."
1368
+ }));
1369
+ opaque.push({
1370
+ kind: "opaque-object",
1371
+ id: stableId(`metadata_${relation}_${oid ?? "unknown"}_${subid}`),
1372
+ identitySource: "physical-name",
1373
+ physicalName: text(row.object_name) ?? `metadata_${oid ?? "unknown"}`,
1374
+ objectKind: `postgres-metadata:${text(row.object_kind) ?? "unknown"}`,
1375
+ data: {
1376
+ catalogRelation: relation,
1377
+ objectOid: oid ?? "unknown",
1378
+ objectSubid: subid,
1379
+ ...text(row.description) === void 0 ? {} : { description: text(row.description) },
1380
+ ...text(row.owner) === void 0 ? {} : { owner: text(row.owner) }
1381
+ },
1382
+ reference: unknownReference
1383
+ });
1384
+ continue;
1385
+ }
1386
+ const description = text(row.description);
1387
+ if (description !== void 0) comments.push({
1388
+ kind: "comment",
1389
+ id: stableId(`${target.object.kind}_${target.object.id}_comment`),
1390
+ object: target.object,
1391
+ text: description,
1392
+ reference: target.reference,
1393
+ provenance: {
1394
+ kind: "catalog",
1395
+ dialect: "postgresql",
1396
+ reference: target.reference
1397
+ }
1398
+ });
1399
+ const owner = text(row.owner);
1400
+ if (owner !== void 0) ownership.push({
1401
+ kind: "ownership",
1402
+ id: stableId(`${target.object.kind}_${target.object.id}_ownership`),
1403
+ object: target.object,
1404
+ owner,
1405
+ reference: target.reference,
1406
+ provenance: {
1407
+ kind: "catalog",
1408
+ dialect: "postgresql",
1409
+ reference: target.reference
1410
+ }
1411
+ });
1412
+ }
1413
+ return {
1414
+ comments,
1415
+ ownership,
1416
+ opaqueObjects: opaque
1417
+ };
1418
+ }
1419
+ function addNestedColumns(targets, relation, owner, namespace) {
1420
+ const tableOid = owner.reference?.catalog?.value;
1421
+ if (tableOid === void 0) return;
1422
+ for (const column of owner.columns) targets.set(metadataKey(relation, tableOid, column.ordinalPosition), {
1423
+ object: {
1424
+ kind: "column",
1425
+ id: column.id
1426
+ },
1427
+ reference: column.reference ?? reference("column", column.physicalName, namespace, "pg_attribute", "attrelid", tableOid),
1428
+ physicalName: column.physicalName
1429
+ });
1430
+ }
1431
+ function metadataKey(relation, oid, subid) {
1432
+ return `${relation}:${text(oid) ?? "unknown"}:${number(subid) ?? 0}`;
1433
+ }
1434
+ function indexTermOptions(row, method) {
1435
+ const option = number(row.indoption);
1436
+ if (method !== "btree" || option === void 0) return {};
1437
+ return {
1438
+ direction: option & 1 ? "DESC" : "ASC",
1439
+ nulls: option & 2 ? "FIRST" : "LAST"
1440
+ };
1441
+ }
1442
+ function sql(textValue, namespace, owner, name) {
1443
+ return expression(textValue, "decompiler", owner.reference ?? reference("table", name, namespace, "pg_class", "relname", owner.physicalName));
1444
+ }
1445
+ function expression(textValue, provenanceKind, physicalReference) {
1446
+ return {
1447
+ kind: "sql",
1448
+ dialect: "postgresql",
1449
+ text: textValue,
1450
+ provenance: {
1451
+ kind: provenanceKind,
1452
+ dialect: "postgresql",
1453
+ ...physicalReference === void 0 ? {} : { reference: physicalReference }
1454
+ }
1455
+ };
1456
+ }
1457
+ function reference(kind, name, namespace, relation, key, value = name) {
1458
+ return {
1459
+ kind,
1460
+ name,
1461
+ namespace,
1462
+ catalog: {
1463
+ relation,
1464
+ key,
1465
+ value: typeof value === "number" ? value : String(value)
1466
+ }
1467
+ };
1468
+ }
1469
+ function stableId(value) {
1470
+ if (value.length > 0 && !/[.\\\u0000-\u001f\u007f]/.test(value)) return value;
1471
+ let hash = 2166136261;
1472
+ for (let index = 0; index < value.length; index += 1) {
1473
+ hash ^= value.charCodeAt(index);
1474
+ hash = Math.imul(hash, 16777619);
1475
+ }
1476
+ return `introspected_${(hash >>> 0).toString(16)}`;
1477
+ }
1478
+ function groupBy(rows, key) {
1479
+ const result = /* @__PURE__ */ new Map();
1480
+ for (const row of rows) {
1481
+ const value = key(row);
1482
+ const group = result.get(value) ?? [];
1483
+ group.push(row);
1484
+ result.set(value, group);
1485
+ }
1486
+ return result;
1487
+ }
1488
+ function text(value) {
1489
+ return value === null || value === void 0 ? void 0 : String(value);
1490
+ }
1491
+ function number(value) {
1492
+ if (typeof value === "number" && Number.isFinite(value)) return value;
1493
+ if (typeof value === "string" && value.trim() !== "") {
1494
+ const parsed = Number(value);
1495
+ return Number.isFinite(parsed) ? parsed : void 0;
1496
+ }
1497
+ }
1498
+ function boolean(value) {
1499
+ return value === true || value === "t" || value === "true" || value === 1;
1500
+ }
1501
+ function stringArray(value) {
1502
+ if (Array.isArray(value)) return value.map((item) => text(item)).filter((item) => item !== void 0);
1503
+ const source = text(value)?.trim();
1504
+ if (source === void 0 || source === "") return [];
1505
+ if (source.startsWith("{") && source.endsWith("}")) {
1506
+ const values = [];
1507
+ let current = "";
1508
+ let quoted = false;
1509
+ let escaped = false;
1510
+ for (const character of source.slice(1, -1)) if (escaped) {
1511
+ current += character;
1512
+ escaped = false;
1513
+ } else if (character === "\\" && quoted) escaped = true;
1514
+ else if (character === "\"") quoted = !quoted;
1515
+ else if (character === "," && !quoted) {
1516
+ values.push(current);
1517
+ current = "";
1518
+ } else current += character;
1519
+ if (current !== "" || source !== "{}") values.push(current);
1520
+ return values.filter((value) => value !== "");
1521
+ }
1522
+ return source.split(",").map((item) => item.trim()).filter((item) => item !== "");
1523
+ }
1524
+ function booleanOption(options, name) {
1525
+ const value = options.find((option) => option.startsWith(`${name}=`));
1526
+ if (value === void 0) return;
1527
+ const setting = value.slice(name.length + 1).toLowerCase();
1528
+ if (setting === "true" || setting === "on" || setting === "yes") return true;
1529
+ if (setting === "false" || setting === "off" || setting === "no") return false;
1530
+ }
1531
+ function integerArray(value) {
1532
+ if (Array.isArray(value)) return value.map((item) => number(item) ?? 0);
1533
+ const parsed = text(value)?.replace(/[{}]/g, "").trim();
1534
+ if (!parsed) return [];
1535
+ return parsed.split(",").map((item) => number(item.trim()) ?? 0);
1536
+ }
1537
+ function referentialAction(value) {
1538
+ return {
1539
+ a: "no-action",
1540
+ r: "restrict",
1541
+ c: "cascade",
1542
+ n: "set-null",
1543
+ d: "set-default"
1544
+ }[text(value)];
1545
+ }
1546
+ function matchType(value) {
1547
+ return {
1548
+ s: "simple",
1549
+ f: "full",
1550
+ p: "partial"
1551
+ }[text(value)];
1552
+ }
1553
+ //#endregion
1554
+ export { postgresCollationsQuery, postgresColumnsQuery, postgresConstraintsQuery, postgresDomainConstraintsQuery, postgresDomainsQuery, postgresEnumsQuery, postgresExtensionsQuery, postgresIdentitiesQuery, postgresIndexesQuery, postgresMetadataQuery, postgresPartitionsQuery, postgresPoliciesQuery, postgresRelationsQuery, postgresRoutineParametersQuery, postgresRoutinesQuery, postgresSequencesQuery, postgresServerQuery, postgresTriggersQuery, postgresViewsQuery, readCatalog };