eslint-plugin-slonik 1.0.0

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 (35) hide show
  1. package/LICENSE +48 -0
  2. package/README.md +368 -0
  3. package/dist/config.cjs +61 -0
  4. package/dist/config.cjs.map +1 -0
  5. package/dist/config.d.cts +192 -0
  6. package/dist/config.d.mts +192 -0
  7. package/dist/config.d.ts +192 -0
  8. package/dist/config.mjs +59 -0
  9. package/dist/config.mjs.map +1 -0
  10. package/dist/index.cjs +27 -0
  11. package/dist/index.cjs.map +1 -0
  12. package/dist/index.d.cts +319 -0
  13. package/dist/index.d.mts +319 -0
  14. package/dist/index.d.ts +319 -0
  15. package/dist/index.mjs +20 -0
  16. package/dist/index.mjs.map +1 -0
  17. package/dist/shared/eslint-plugin-slonik.1m1xlVmw.d.cts +611 -0
  18. package/dist/shared/eslint-plugin-slonik.1m1xlVmw.d.mts +611 -0
  19. package/dist/shared/eslint-plugin-slonik.1m1xlVmw.d.ts +611 -0
  20. package/dist/shared/eslint-plugin-slonik.BxexVlk1.cjs +1539 -0
  21. package/dist/shared/eslint-plugin-slonik.BxexVlk1.cjs.map +1 -0
  22. package/dist/shared/eslint-plugin-slonik.C0xTyWZ2.mjs +2866 -0
  23. package/dist/shared/eslint-plugin-slonik.C0xTyWZ2.mjs.map +1 -0
  24. package/dist/shared/eslint-plugin-slonik.DbzoLz5_.mjs +1514 -0
  25. package/dist/shared/eslint-plugin-slonik.DbzoLz5_.mjs.map +1 -0
  26. package/dist/shared/eslint-plugin-slonik.rlOTrCdf.cjs +2929 -0
  27. package/dist/shared/eslint-plugin-slonik.rlOTrCdf.cjs.map +1 -0
  28. package/dist/workers/check-sql.worker.cjs +2436 -0
  29. package/dist/workers/check-sql.worker.cjs.map +1 -0
  30. package/dist/workers/check-sql.worker.d.cts +171 -0
  31. package/dist/workers/check-sql.worker.d.mts +171 -0
  32. package/dist/workers/check-sql.worker.d.ts +171 -0
  33. package/dist/workers/check-sql.worker.mjs +2412 -0
  34. package/dist/workers/check-sql.worker.mjs.map +1 -0
  35. package/package.json +103 -0
@@ -0,0 +1,2436 @@
1
+ 'use strict';
2
+
3
+ const checkSql_utils = require('../shared/eslint-plugin-slonik.rlOTrCdf.cjs');
4
+ const fpTs = require('fp-ts');
5
+ const parser = require('libpg-query');
6
+ const path = require('path');
7
+ const synckit = require('synckit');
8
+ const tsPattern = require('ts-pattern');
9
+ const postgres = require('postgres');
10
+ require('fp-ts/lib/Either.js');
11
+ const function_js = require('fp-ts/lib/function.js');
12
+ const O = require('fp-ts/lib/Option.js');
13
+ const TE = require('fp-ts/lib/TaskEither.js');
14
+ const J = require('fp-ts/lib/Json.js');
15
+ const chokidar = require('chokidar');
16
+ require('crypto');
17
+ require('fs');
18
+ require('@typescript-eslint/utils');
19
+ require('pg-connection-string');
20
+
21
+ function _interopDefaultCompat (e) { return e && typeof e === 'object' && 'default' in e ? e.default : e; }
22
+
23
+ function _interopNamespaceCompat(e) {
24
+ if (e && typeof e === 'object' && 'default' in e) return e;
25
+ const n = Object.create(null);
26
+ if (e) {
27
+ for (const k in e) {
28
+ n[k] = e[k];
29
+ }
30
+ }
31
+ n.default = e;
32
+ return n;
33
+ }
34
+
35
+ const parser__namespace = /*#__PURE__*/_interopNamespaceCompat(parser);
36
+ const path__default = /*#__PURE__*/_interopDefaultCompat(path);
37
+ const postgres__default = /*#__PURE__*/_interopDefaultCompat(postgres);
38
+ const O__namespace = /*#__PURE__*/_interopNamespaceCompat(O);
39
+ const TE__namespace = /*#__PURE__*/_interopNamespaceCompat(TE);
40
+ const J__namespace = /*#__PURE__*/_interopNamespaceCompat(J);
41
+ const chokidar__default = /*#__PURE__*/_interopDefaultCompat(chokidar);
42
+
43
+ var AExprKind = /* @__PURE__ */ ((AExprKind2) => {
44
+ AExprKind2["A_EXPR_KIND_UNDEFINED"] = "A_EXPR_KIND_UNDEFINED";
45
+ AExprKind2["AEXPR_OP"] = "AEXPR_OP";
46
+ AExprKind2["AEXPR_OP_ANY"] = "AEXPR_OP_ANY";
47
+ AExprKind2["AEXPR_OP_ALL"] = "AEXPR_OP_ALL";
48
+ AExprKind2["AEXPR_DISTINCT"] = "AEXPR_DISTINCT";
49
+ AExprKind2["AEXPR_NOT_DISTINCT"] = "AEXPR_NOT_DISTINCT";
50
+ AExprKind2["AEXPR_NULLIF"] = "AEXPR_NULLIF";
51
+ AExprKind2["AEXPR_IN"] = "AEXPR_IN";
52
+ AExprKind2["AEXPR_LIKE"] = "AEXPR_LIKE";
53
+ AExprKind2["AEXPR_ILIKE"] = "AEXPR_ILIKE";
54
+ AExprKind2["AEXPR_SIMILAR"] = "AEXPR_SIMILAR";
55
+ AExprKind2["AEXPR_BETWEEN"] = "AEXPR_BETWEEN";
56
+ AExprKind2["AEXPR_NOT_BETWEEN"] = "AEXPR_NOT_BETWEEN";
57
+ AExprKind2["AEXPR_BETWEEN_SYM"] = "AEXPR_BETWEEN_SYM";
58
+ AExprKind2["AEXPR_NOT_BETWEEN_SYM"] = "AEXPR_NOT_BETWEEN_SYM";
59
+ AExprKind2["UNRECOGNIZED"] = "UNRECOGNIZED";
60
+ return AExprKind2;
61
+ })(AExprKind || {});
62
+ var BoolExprType = /* @__PURE__ */ ((BoolExprType2) => {
63
+ BoolExprType2["BOOL_EXPR_TYPE_UNDEFINED"] = "BOOL_EXPR_TYPE_UNDEFINED";
64
+ BoolExprType2["AND_EXPR"] = "AND_EXPR";
65
+ BoolExprType2["OR_EXPR"] = "OR_EXPR";
66
+ BoolExprType2["NOT_EXPR"] = "NOT_EXPR";
67
+ BoolExprType2["UNRECOGNIZED"] = "UNRECOGNIZED";
68
+ return BoolExprType2;
69
+ })(BoolExprType || {});
70
+ var SubLinkType = /* @__PURE__ */ ((SubLinkType2) => {
71
+ SubLinkType2["SUB_LINK_TYPE_UNDEFINED"] = "SUB_LINK_TYPE_UNDEFINED";
72
+ SubLinkType2["EXISTS_SUBLINK"] = "EXISTS_SUBLINK";
73
+ SubLinkType2["ALL_SUBLINK"] = "ALL_SUBLINK";
74
+ SubLinkType2["ANY_SUBLINK"] = "ANY_SUBLINK";
75
+ SubLinkType2["ROWCOMPARE_SUBLINK"] = "ROWCOMPARE_SUBLINK";
76
+ SubLinkType2["EXPR_SUBLINK"] = "EXPR_SUBLINK";
77
+ SubLinkType2["MULTIEXPR_SUBLINK"] = "MULTIEXPR_SUBLINK";
78
+ SubLinkType2["ARRAY_SUBLINK"] = "ARRAY_SUBLINK";
79
+ SubLinkType2["CTE_SUBLINK"] = "CTE_SUBLINK";
80
+ SubLinkType2["UNRECOGNIZED"] = "UNRECOGNIZED";
81
+ return SubLinkType2;
82
+ })(SubLinkType || {});
83
+ var NullTestType = /* @__PURE__ */ ((NullTestType2) => {
84
+ NullTestType2["NULL_TEST_TYPE_UNDEFINED"] = "NULL_TEST_TYPE_UNDEFINED";
85
+ NullTestType2["IS_NULL"] = "IS_NULL";
86
+ NullTestType2["IS_NOT_NULL"] = "IS_NOT_NULL";
87
+ NullTestType2["UNRECOGNIZED"] = "UNRECOGNIZED";
88
+ return NullTestType2;
89
+ })(NullTestType || {});
90
+ var JoinType = /* @__PURE__ */ ((JoinType2) => {
91
+ JoinType2["JOIN_TYPE_UNDEFINED"] = "JOIN_TYPE_UNDEFINED";
92
+ JoinType2["JOIN_INNER"] = "JOIN_INNER";
93
+ JoinType2["JOIN_LEFT"] = "JOIN_LEFT";
94
+ JoinType2["JOIN_FULL"] = "JOIN_FULL";
95
+ JoinType2["JOIN_RIGHT"] = "JOIN_RIGHT";
96
+ JoinType2["JOIN_SEMI"] = "JOIN_SEMI";
97
+ JoinType2["JOIN_ANTI"] = "JOIN_ANTI";
98
+ JoinType2["JOIN_UNIQUE_OUTER"] = "JOIN_UNIQUE_OUTER";
99
+ JoinType2["JOIN_UNIQUE_INNER"] = "JOIN_UNIQUE_INNER";
100
+ JoinType2["UNRECOGNIZED"] = "UNRECOGNIZED";
101
+ return JoinType2;
102
+ })(JoinType || {});
103
+
104
+ function isColumnStarRef(fields) {
105
+ return isSingleCell(fields) && fields[0]?.A_Star !== void 0;
106
+ }
107
+ function isColumnTableStarRef(fields) {
108
+ return isTuple(fields) && fields[0].String !== void 0 && fields[1].A_Star !== void 0;
109
+ }
110
+ function isColumnUnknownRef(fields) {
111
+ return isSingleCell(fields) && fields[0].String !== void 0;
112
+ }
113
+ function isColumnTableColumnRef(fields) {
114
+ return isTuple(fields) && fields[0].String !== void 0 && fields[1].String !== void 0;
115
+ }
116
+ function isSingleCell(arr) {
117
+ return arr.length === 1;
118
+ }
119
+ function isTuple(arr) {
120
+ return arr.length === 2;
121
+ }
122
+
123
+ function getSources({
124
+ select,
125
+ prevSources,
126
+ nonNullableColumns,
127
+ pgColsBySchemaAndTableName,
128
+ relations
129
+ }) {
130
+ const relationsByAlias = /* @__PURE__ */ new Map();
131
+ const relationsByRelName = /* @__PURE__ */ new Map();
132
+ for (const rel of relations) {
133
+ const key = rel.alias ?? rel.joinRelName;
134
+ if (key) {
135
+ relationsByAlias.set(key, rel);
136
+ }
137
+ if (!relationsByRelName.has(rel.relName)) {
138
+ relationsByRelName.set(rel.relName, []);
139
+ }
140
+ relationsByRelName.get(rel.relName).push(rel);
141
+ }
142
+ const tableToSchema = /* @__PURE__ */ new Map();
143
+ const publicCols = pgColsBySchemaAndTableName.get("public");
144
+ if (publicCols) {
145
+ for (const tableName of publicCols.keys()) {
146
+ tableToSchema.set(tableName, "public");
147
+ }
148
+ }
149
+ for (const [schemaName, cols] of pgColsBySchemaAndTableName) {
150
+ if (schemaName === "public") break;
151
+ for (const tableName of cols.keys()) {
152
+ if (!tableToSchema.has(tableName)) {
153
+ tableToSchema.set(tableName, schemaName);
154
+ }
155
+ }
156
+ }
157
+ function getColumnCTEs(ctes2) {
158
+ const map = /* @__PURE__ */ new Map();
159
+ for (const cte of ctes2) {
160
+ if (cte.CommonTableExpr?.ctequery?.SelectStmt === void 0) continue;
161
+ if (cte.CommonTableExpr?.ctename === void 0) continue;
162
+ const resolver = getSources({
163
+ pgColsBySchemaAndTableName,
164
+ prevSources,
165
+ nonNullableColumns,
166
+ relations,
167
+ select: cte.CommonTableExpr.ctequery.SelectStmt
168
+ });
169
+ map.set(cte.CommonTableExpr.ctename, resolver);
170
+ }
171
+ return map;
172
+ }
173
+ const ctes = getColumnCTEs(select.withClause?.ctes ?? []);
174
+ function resolveRangeVarSchema(node) {
175
+ switch (true) {
176
+ case node.schemaname !== void 0:
177
+ return node.schemaname;
178
+ case pgColsBySchemaAndTableName.get("public")?.has(node.relname):
179
+ return "public";
180
+ default:
181
+ for (const [schemaName, cols] of pgColsBySchemaAndTableName) {
182
+ if (cols.has(node.relname)) {
183
+ return schemaName;
184
+ }
185
+ }
186
+ return "public";
187
+ }
188
+ }
189
+ function getNodeColumnAndSources(node) {
190
+ if (node.RangeVar !== void 0) {
191
+ const cteResolver = ctes.get(node.RangeVar.relname);
192
+ if (cteResolver !== void 0) {
193
+ return [{ kind: "cte", name: node.RangeVar.relname, sources: cteResolver }];
194
+ }
195
+ const schemaName = resolveRangeVarSchema(node.RangeVar);
196
+ const realTableName = node.RangeVar.relname;
197
+ const tableName = node.RangeVar.alias?.aliasname ?? realTableName;
198
+ const tableColsArray = pgColsBySchemaAndTableName.get(schemaName)?.get(realTableName) ?? [];
199
+ const tableSource = {
200
+ kind: "table",
201
+ schemaName,
202
+ original: realTableName,
203
+ name: tableName,
204
+ alias: node.RangeVar.alias?.aliasname,
205
+ columns: /* @__PURE__ */ new Map()
206
+ };
207
+ for (const col of tableColsArray) {
208
+ tableSource.columns.set(col.colName, resolveColumn(col, tableSource));
209
+ }
210
+ return [tableSource];
211
+ }
212
+ const sourcesArr = [];
213
+ if (node.JoinExpr?.larg !== void 0) {
214
+ sourcesArr.push(...getNodeColumnAndSources(node.JoinExpr.larg));
215
+ }
216
+ if (node.JoinExpr?.rarg !== void 0) {
217
+ sourcesArr.push(...getNodeColumnAndSources(node.JoinExpr.rarg));
218
+ }
219
+ if (node.RangeSubselect?.subquery?.SelectStmt?.fromClause !== void 0) {
220
+ const combinedPrevSources = new Map([
221
+ ...prevSources?.entries() ?? [],
222
+ ...sourcesArr.map((x) => [x.name, x])
223
+ ]);
224
+ sourcesArr.push({
225
+ kind: "subselect",
226
+ name: node.RangeSubselect.alias?.aliasname ?? "subselect",
227
+ sources: getSources({
228
+ nonNullableColumns,
229
+ pgColsBySchemaAndTableName,
230
+ relations,
231
+ prevSources: combinedPrevSources,
232
+ select: node.RangeSubselect.subquery.SelectStmt
233
+ })
234
+ });
235
+ }
236
+ return sourcesArr;
237
+ }
238
+ function getColumnSources(stmt) {
239
+ const fromClauseSources = [];
240
+ for (const node of stmt.fromClause ?? []) {
241
+ const nodes = getNodeColumnAndSources(node);
242
+ for (const nodeSource of nodes) {
243
+ fromClauseSources.push([nodeSource.name, nodeSource]);
244
+ }
245
+ }
246
+ return new Map(fromClauseSources);
247
+ }
248
+ const sources = new Map([
249
+ ...prevSources?.entries() ?? [],
250
+ ...getColumnSources(select).entries()
251
+ ]);
252
+ const cachedColumnsMap = /* @__PURE__ */ new WeakMap();
253
+ function getSourceColumns(source) {
254
+ if (cachedColumnsMap.has(source)) {
255
+ return cachedColumnsMap.get(source);
256
+ }
257
+ let result = [];
258
+ switch (source.kind) {
259
+ case "table":
260
+ result = Array.from(source.columns.values()).map((col) => ({
261
+ column: col,
262
+ source
263
+ }));
264
+ break;
265
+ case "cte":
266
+ case "subselect":
267
+ result = [];
268
+ break;
269
+ }
270
+ cachedColumnsMap.set(source, result);
271
+ return result;
272
+ }
273
+ function getAllResolvedColumns() {
274
+ const all = [];
275
+ for (const source of sources.values()) {
276
+ all.push(...getSourceColumns(source));
277
+ }
278
+ return all;
279
+ }
280
+ const allResolved = getAllResolvedColumns();
281
+ const columnIndex = /* @__PURE__ */ new Map();
282
+ const unknownColumnIndex = /* @__PURE__ */ new Map();
283
+ for (const entry of allResolved) {
284
+ const key = `${entry.source.name}.${entry.column.column.colName}`;
285
+ columnIndex.set(key, entry);
286
+ const unknownKey = entry.column.column.colName;
287
+ if (!unknownColumnIndex.has(unknownKey)) {
288
+ unknownColumnIndex.set(unknownKey, []);
289
+ }
290
+ unknownColumnIndex.get(unknownKey).push(entry);
291
+ }
292
+ function getColumnByTableAndColumnName(p) {
293
+ const source = sources.get(p.table);
294
+ if (!source) return null;
295
+ switch (source.kind) {
296
+ case "table":
297
+ return source.columns.get(p.column) || null;
298
+ default:
299
+ return null;
300
+ }
301
+ }
302
+ function getResolvedColumnsInTable(sourceName) {
303
+ const source = sources.get(sourceName);
304
+ if (!source) return [];
305
+ return getSourceColumns(source).map((x) => x.column);
306
+ }
307
+ function getNestedResolvedTargetField(field) {
308
+ switch (field.kind) {
309
+ case "column": {
310
+ const key = `${field.table}.${field.column}`;
311
+ if (columnIndex.has(key)) {
312
+ return columnIndex.get(key)?.column ?? null;
313
+ }
314
+ break;
315
+ }
316
+ case "unknown": {
317
+ if (unknownColumnIndex.has(field.field)) {
318
+ const candidates = unknownColumnIndex.get(field.field);
319
+ if (candidates.length > 0) return candidates[0]?.column ?? null;
320
+ }
321
+ break;
322
+ }
323
+ }
324
+ for (const source of sources.values()) {
325
+ switch (source.kind) {
326
+ case "cte":
327
+ case "subselect": {
328
+ const nested = source.sources.getNestedResolvedTargetField(field);
329
+ if (nested) {
330
+ return {
331
+ ...nested,
332
+ isNotNull: nested.isNotNull && !checkIsNullableDueToRelation(source.name)
333
+ };
334
+ }
335
+ break;
336
+ }
337
+ case "table": {
338
+ const key = field.kind === "column" ? field.column : field.field;
339
+ const column = source.columns.get(key);
340
+ if (column) return column;
341
+ break;
342
+ }
343
+ }
344
+ }
345
+ return null;
346
+ }
347
+ function getColumnsByTargetField(field) {
348
+ switch (field.kind) {
349
+ case "column": {
350
+ const result = getColumnByTableAndColumnName(field);
351
+ if (result !== null) {
352
+ return [result];
353
+ }
354
+ for (const source of sources.values()) {
355
+ switch (source.kind) {
356
+ case "subselect": {
357
+ const column = source.sources.getNestedResolvedTargetField(field);
358
+ if (column) {
359
+ const isNullableDueToRelation = checkIsNullableDueToRelation(source.name);
360
+ if (isNullableDueToRelation && column.isNotNull) {
361
+ return [{ ...column, isNotNull: false }];
362
+ }
363
+ return [column];
364
+ }
365
+ break;
366
+ }
367
+ }
368
+ }
369
+ return null;
370
+ }
371
+ case "unknown": {
372
+ const source = sources.get(field.field);
373
+ if (source !== void 0) {
374
+ return getSourceColumns(source).map((x) => x.column);
375
+ }
376
+ const foundColumn = getNestedResolvedTargetField(field);
377
+ if (foundColumn) {
378
+ return [foundColumn];
379
+ }
380
+ for (const source2 of sources.values()) {
381
+ switch (source2.kind) {
382
+ case "subselect": {
383
+ const columns = source2.sources.getColumnsByTargetField(field);
384
+ if (columns) {
385
+ const isNullableDueToRelation = checkIsNullableDueToRelation(source2.name);
386
+ if (isNullableDueToRelation) {
387
+ return columns.map((col) => col.isNotNull ? { ...col, isNotNull: false } : col);
388
+ }
389
+ return columns;
390
+ }
391
+ break;
392
+ }
393
+ }
394
+ }
395
+ return null;
396
+ }
397
+ }
398
+ }
399
+ function checkIsNullableDueToRelation(key) {
400
+ const rel = relationsByAlias.get(key);
401
+ if (rel !== void 0) {
402
+ switch (rel.joinType) {
403
+ case JoinType.JOIN_LEFT:
404
+ case JoinType.JOIN_FULL:
405
+ return true;
406
+ case JoinType.JOIN_TYPE_UNDEFINED:
407
+ case JoinType.JOIN_INNER:
408
+ case JoinType.JOIN_RIGHT:
409
+ case JoinType.JOIN_SEMI:
410
+ case JoinType.JOIN_ANTI:
411
+ case JoinType.JOIN_UNIQUE_OUTER:
412
+ case JoinType.JOIN_UNIQUE_INNER:
413
+ case JoinType.UNRECOGNIZED:
414
+ return false;
415
+ default:
416
+ return checkSql_utils.assertNever(rel.joinType);
417
+ }
418
+ }
419
+ for (const relation of relationsByRelName.get(key) ?? []) {
420
+ switch (relation.joinType) {
421
+ case JoinType.JOIN_RIGHT:
422
+ case JoinType.JOIN_FULL:
423
+ return true;
424
+ case JoinType.JOIN_TYPE_UNDEFINED:
425
+ case JoinType.JOIN_INNER:
426
+ case JoinType.JOIN_LEFT:
427
+ case JoinType.JOIN_SEMI:
428
+ case JoinType.JOIN_ANTI:
429
+ case JoinType.JOIN_UNIQUE_OUTER:
430
+ case JoinType.JOIN_UNIQUE_INNER:
431
+ case JoinType.UNRECOGNIZED:
432
+ return false;
433
+ default:
434
+ return checkSql_utils.assertNever(relation.joinType);
435
+ }
436
+ }
437
+ return false;
438
+ }
439
+ function resolveColumn(col, source) {
440
+ const keyForNullability = source.alias ? source.alias : source.original;
441
+ const isNullableDueToRelation = checkIsNullableDueToRelation(keyForNullability);
442
+ const isNotNullBasedOnAST = nonNullableColumns.has(col.colName) || nonNullableColumns.has(`${source.name}.${col.colName}`);
443
+ const isNotNullInTable = col.colNotNull;
444
+ const isNonNullable = isNotNullBasedOnAST || isNotNullInTable && !isNullableDueToRelation;
445
+ return { column: col, isNotNull: isNonNullable };
446
+ }
447
+ return {
448
+ getNodeColumnAndSources,
449
+ getResolvedColumnsInTable,
450
+ getAllResolvedColumns,
451
+ getColumnsByTargetField,
452
+ getNestedResolvedTargetField,
453
+ sources
454
+ };
455
+ }
456
+
457
+ const nonNullFunctions = /* @__PURE__ */ new Set([
458
+ "count",
459
+ "now",
460
+ "abs",
461
+ "ceil",
462
+ "floor",
463
+ "round",
464
+ "sqrt",
465
+ "cbrt",
466
+ "exp",
467
+ "log",
468
+ "log10",
469
+ "sin",
470
+ "cos",
471
+ "tan",
472
+ "asin",
473
+ "acos",
474
+ "atan",
475
+ "radians",
476
+ "degrees",
477
+ "length",
478
+ "trim",
479
+ "lower",
480
+ "upper",
481
+ "ascii",
482
+ "concat",
483
+ "concat_ws",
484
+ "lpad",
485
+ "rpad",
486
+ "initcap",
487
+ "left",
488
+ "right",
489
+ "cdat",
490
+ "chr",
491
+ "strpos",
492
+ "substr",
493
+ "translate",
494
+ "current_date",
495
+ "current_time",
496
+ "current_timestamp",
497
+ "localtime",
498
+ "localtimestamp",
499
+ "uuid_generate_v1",
500
+ "uuid_generate_v4",
501
+ "pi",
502
+ "random",
503
+ "exists",
504
+ "row_number",
505
+ "current_schema",
506
+ "current_schemas",
507
+ "inet_server_addr",
508
+ "inet_server_port",
509
+ "isfinite",
510
+ "isnan",
511
+ "pg_backend_pid",
512
+ "pg_blocking_pids",
513
+ "pg_cancel_backend",
514
+ "pg_is_in_recovery",
515
+ "pg_postmaster_start_time",
516
+ "pg_relation_size",
517
+ "pg_total_relation_size",
518
+ "timeofday",
519
+ "similar_to_escape"
520
+ ]);
521
+ function concatStringNodes$1(nodes) {
522
+ return nodes?.map((x) => x.String?.sval).filter(Boolean).join(".") ?? "";
523
+ }
524
+ function isColumnNonNullable(val, root) {
525
+ if (val === void 0) {
526
+ return false;
527
+ }
528
+ if (val.NullTest) {
529
+ return true;
530
+ }
531
+ if (val.BoolExpr?.boolop === BoolExprType.NOT_EXPR) {
532
+ return true;
533
+ }
534
+ if (val.A_Const) {
535
+ return val.A_Const.isnull !== true;
536
+ }
537
+ if (val.FuncCall) {
538
+ const functionName = concatStringNodes$1(val.FuncCall.funcname);
539
+ return nonNullFunctions.has(functionName.toLowerCase());
540
+ }
541
+ if (val.TypeCast?.arg) {
542
+ return isColumnNonNullable(val.TypeCast.arg, root);
543
+ }
544
+ if (val.SubLink) {
545
+ switch (val.SubLink.subLinkType) {
546
+ case SubLinkType.EXISTS_SUBLINK:
547
+ return true;
548
+ case SubLinkType.ARRAY_SUBLINK:
549
+ return true;
550
+ // while the array itself can be non-nullable, the elements can be nullable
551
+ case SubLinkType.ALL_SUBLINK:
552
+ case SubLinkType.ANY_SUBLINK:
553
+ case SubLinkType.ROWCOMPARE_SUBLINK:
554
+ case SubLinkType.EXPR_SUBLINK:
555
+ case SubLinkType.MULTIEXPR_SUBLINK:
556
+ case SubLinkType.CTE_SUBLINK:
557
+ return isColumnNonNullable(val.SubLink.subselect, root);
558
+ case SubLinkType.SUB_LINK_TYPE_UNDEFINED:
559
+ case SubLinkType.UNRECOGNIZED:
560
+ return false;
561
+ default:
562
+ checkSql_utils.assertNever(val.SubLink.subLinkType);
563
+ }
564
+ }
565
+ if (val.A_Expr?.kind === AExprKind.AEXPR_SIMILAR) {
566
+ return true;
567
+ }
568
+ if (val.A_Expr?.kind === AExprKind.AEXPR_LIKE) {
569
+ return true;
570
+ }
571
+ if (val.A_Expr?.kind === AExprKind.AEXPR_OP) {
572
+ return isColumnNonNullable(val.A_Expr.lexpr, root) && isColumnNonNullable(val.A_Expr.rexpr, root);
573
+ }
574
+ if (val.CaseExpr) {
575
+ for (const when of val.CaseExpr.args) {
576
+ if (!isColumnNonNullable(when.CaseWhen?.result, root)) {
577
+ return false;
578
+ }
579
+ }
580
+ if (val.CaseExpr.defresult && !isColumnNonNullable(val.CaseExpr.defresult, root)) {
581
+ return false;
582
+ }
583
+ return true;
584
+ }
585
+ if (val.ColumnRef) {
586
+ const refColumnName = concatStringNodes$1(val.ColumnRef.fields);
587
+ for (const stmt of root.stmts) {
588
+ if (stmt?.stmt?.SelectStmt?.whereClause) {
589
+ const whereClause = stmt.stmt.SelectStmt.whereClause;
590
+ const whereClauseColumnName = concatStringNodes$1(
591
+ whereClause.NullTest?.arg?.ColumnRef?.fields
592
+ );
593
+ if (whereClause.NullTest?.nulltesttype === NullTestType.IS_NOT_NULL && whereClauseColumnName === refColumnName) {
594
+ return true;
595
+ }
596
+ }
597
+ }
598
+ }
599
+ if (val.CoalesceExpr) {
600
+ for (const arg of val.CoalesceExpr.args) {
601
+ if (isColumnNonNullable(arg, root)) {
602
+ return true;
603
+ }
604
+ }
605
+ }
606
+ if (val.A_ArrayExpr) {
607
+ return true;
608
+ }
609
+ if (val.SelectStmt) {
610
+ const nonNullableColumnsInSubStmt = getNonNullableColumnsInSelectStmt(val.SelectStmt, root);
611
+ return Array.from(nonNullableColumnsInSubStmt.values()).some(Boolean);
612
+ }
613
+ return false;
614
+ }
615
+ function getNodeName(node) {
616
+ if (node?.ColumnRef !== void 0) {
617
+ return concatStringNodes$1(node.ColumnRef.fields);
618
+ }
619
+ if (node?.NullTest) {
620
+ return getNodeName(node.NullTest.arg);
621
+ }
622
+ if (node?.A_Const?.boolval !== void 0) {
623
+ return "bool";
624
+ }
625
+ if (node?.TypeCast !== void 0) {
626
+ const typeName = concatStringNodes$1(node.TypeCast.typeName?.names);
627
+ if (typeName === "pg_catalog.interval") {
628
+ return "interval";
629
+ }
630
+ if (node.TypeCast.arg) {
631
+ return getNodeName(node.TypeCast.arg);
632
+ }
633
+ return typeName.replace(/^pg_catalog\./, "");
634
+ }
635
+ if (node?.FuncCall?.funcname !== void 0) {
636
+ return concatStringNodes$1(node.FuncCall.funcname);
637
+ }
638
+ if (node?.SubLink?.subLinkType === SubLinkType.EXISTS_SUBLINK) {
639
+ return "exists";
640
+ }
641
+ if (node?.SubLink?.subLinkType === SubLinkType.ARRAY_SUBLINK) {
642
+ return "array";
643
+ }
644
+ if (node?.SubLink?.subselect?.SelectStmt?.targetList !== void 0) {
645
+ const subSelectTargetList = node.SubLink.subselect.SelectStmt.targetList;
646
+ if (subSelectTargetList?.[0].ResTarget !== void 0) {
647
+ return getTargetName(subSelectTargetList[0].ResTarget);
648
+ }
649
+ }
650
+ if (node?.A_ArrayExpr !== void 0) {
651
+ return "array";
652
+ }
653
+ if (node?.CaseExpr !== void 0) {
654
+ return "case";
655
+ }
656
+ if (node?.CoalesceExpr !== void 0) {
657
+ return "coalesce";
658
+ }
659
+ return "?column?";
660
+ }
661
+ function getTargetName(target) {
662
+ return target.name ?? getNodeName(target.val);
663
+ }
664
+ function getNonNullableColumnsInSelectStmt(stmt, root) {
665
+ const nonNullableColumns = /* @__PURE__ */ new Set();
666
+ const targetList = [
667
+ ...stmt.targetList ?? [],
668
+ ...stmt.larg?.targetList ?? [],
669
+ ...stmt.rarg?.targetList ?? []
670
+ ];
671
+ const targetNames = /* @__PURE__ */ new Set();
672
+ for (const target of targetList) {
673
+ if (target.ResTarget) {
674
+ targetNames.add(getTargetName(target.ResTarget));
675
+ }
676
+ if (target.ResTarget && isColumnNonNullable(target.ResTarget.val, root)) {
677
+ nonNullableColumns.add(getTargetName(target.ResTarget));
678
+ }
679
+ }
680
+ if (stmt.whereClause) {
681
+ if (stmt.whereClause.NullTest?.nulltesttype === NullTestType.IS_NOT_NULL) {
682
+ const colRef = stmt.whereClause.NullTest.arg?.ColumnRef;
683
+ const whereClauseName = concatStringNodes$1(colRef?.fields);
684
+ switch (true) {
685
+ case targetNames.has(whereClauseName):
686
+ nonNullableColumns.add(whereClauseName);
687
+ break;
688
+ case targetNames.has(colRef?.fields?.at(-1)?.String?.sval ?? ""):
689
+ nonNullableColumns.add(colRef?.fields?.at(-1)?.String?.sval ?? "");
690
+ break;
691
+ default:
692
+ nonNullableColumns.add(whereClauseName);
693
+ break;
694
+ }
695
+ }
696
+ if (stmt.whereClause.BoolExpr?.boolop === BoolExprType.AND_EXPR) {
697
+ for (const arg of stmt.whereClause.BoolExpr.args) {
698
+ if (arg.NullTest?.nulltesttype === NullTestType.IS_NOT_NULL && arg.NullTest.arg?.ColumnRef?.fields) {
699
+ nonNullableColumns.add(concatStringNodes$1(arg.NullTest.arg.ColumnRef.fields));
700
+ }
701
+ }
702
+ }
703
+ }
704
+ return nonNullableColumns;
705
+ }
706
+ function getNonNullableColumns(root) {
707
+ for (const stmt of root.stmts) {
708
+ if (stmt.stmt?.SelectStmt) {
709
+ return getNonNullableColumnsInSelectStmt(stmt.stmt.SelectStmt, root);
710
+ }
711
+ }
712
+ return /* @__PURE__ */ new Set();
713
+ }
714
+
715
+ function getRelationsWithJoins(parsed) {
716
+ const results = /* @__PURE__ */ new Map();
717
+ const stmt = parsed.stmts[0];
718
+ if (stmt === void 0 || stmt?.stmt?.SelectStmt?.fromClause === void 0) {
719
+ return results;
720
+ }
721
+ for (const fromClause of stmt.stmt.SelectStmt.fromClause) {
722
+ if (fromClause.JoinExpr !== void 0) {
723
+ const { relName, joins } = recursiveTraverseJoins([], fromClause.JoinExpr);
724
+ results.set(relName, joins);
725
+ }
726
+ }
727
+ return results;
728
+ }
729
+ function recursiveGetJoinName(joinExpr) {
730
+ if (joinExpr.rarg?.JoinExpr !== void 0) {
731
+ return recursiveGetJoinName(joinExpr.rarg.JoinExpr);
732
+ }
733
+ return joinExpr.rarg?.RangeVar?.relname ?? joinExpr.rarg?.RangeSubselect?.alias?.aliasname;
734
+ }
735
+ function recursiveTraverseJoins(joins, joinExpr) {
736
+ const joinName = recursiveGetJoinName(joinExpr);
737
+ const aliasName = joinExpr.rarg?.RangeVar?.alias?.aliasname;
738
+ if (joinName === void 0) {
739
+ throw new Error("joinName is undefined");
740
+ }
741
+ const join = { type: joinExpr.jointype, name: joinName, alias: aliasName };
742
+ if (joinExpr.larg?.JoinExpr !== void 0) {
743
+ return recursiveTraverseJoins([join, ...joins], joinExpr.larg?.JoinExpr);
744
+ }
745
+ if (joinExpr.rarg?.JoinExpr !== void 0) {
746
+ return recursiveTraverseJoins([join, ...joins], joinExpr.rarg?.JoinExpr);
747
+ }
748
+ const relName = joinExpr.larg?.RangeVar?.relname ?? joinExpr.larg?.RangeFunction?.alias?.aliasname ?? joinExpr.rarg?.RangeVar?.relname ?? joinExpr.rarg?.RangeFunction?.alias?.aliasname;
749
+ if (relName === void 0) {
750
+ throw new Error("relName is undefined");
751
+ }
752
+ return { relName, joins: [join, ...joins] };
753
+ }
754
+ function flattenRelationsWithJoinsMap(relationsWithJoinsMap) {
755
+ const result = [];
756
+ relationsWithJoinsMap.forEach((joins, relName) => {
757
+ joins.forEach((join) => {
758
+ result.push({ relName, joinType: join.type, joinRelName: join.name, alias: join.alias });
759
+ });
760
+ });
761
+ return result;
762
+ }
763
+
764
+ function getASTDescription(params) {
765
+ const select = params.parsed.stmts[0]?.stmt?.SelectStmt;
766
+ if (select === void 0) {
767
+ return {
768
+ map: /* @__PURE__ */ new Map(),
769
+ meta: {
770
+ relations: [],
771
+ nonNullableColumns: /* @__PURE__ */ new Set()
772
+ }
773
+ };
774
+ }
775
+ const nonNullableColumns = getNonNullableColumns(params.parsed);
776
+ const relations = flattenRelationsWithJoinsMap(getRelationsWithJoins(params.parsed));
777
+ function getTypeByOid(oid) {
778
+ const name = params.pgTypes.get(oid)?.name;
779
+ if (name === void 0) {
780
+ return { isArray: false, override: false, value: "unknown" };
781
+ }
782
+ const { isArray, typeName } = name.startsWith("_") ? { isArray: true, typeName: name.slice(1) } : { isArray: false, typeName: name };
783
+ const resolvedTypeName = params.typesMap.get(typeName) ?? { override: false, value: "unknown" };
784
+ return {
785
+ isArray,
786
+ override: resolvedTypeName.override,
787
+ value: resolvedTypeName.value
788
+ };
789
+ }
790
+ const context = {
791
+ ...params,
792
+ nonNullableColumns,
793
+ relations,
794
+ resolver: getSources({
795
+ relations,
796
+ select,
797
+ nonNullableColumns,
798
+ pgColsBySchemaAndTableName: params.pgColsBySchemaAndTableName
799
+ }),
800
+ select,
801
+ resolved: /* @__PURE__ */ new WeakMap(),
802
+ toTypeScriptType: (p) => {
803
+ if ("name" in p) {
804
+ return {
805
+ kind: "type",
806
+ value: params.typesMap.get(p.name)?.value ?? "unknown",
807
+ type: p.name
808
+ };
809
+ }
810
+ const pgType = params.pgTypes.get(p.oid);
811
+ const typeByOid = getTypeByOid(p.oid);
812
+ if (typeByOid.override) {
813
+ const baseType = {
814
+ kind: "type",
815
+ value: typeByOid.value,
816
+ type: pgType?.name ?? "unknown"
817
+ };
818
+ return typeByOid.isArray ? { kind: "array", value: baseType } : baseType;
819
+ }
820
+ const typeByBaseOid = checkSql_utils.fmap(p.baseOid, getTypeByOid);
821
+ if (typeByBaseOid?.override === true) {
822
+ const baseType = {
823
+ kind: "type",
824
+ value: typeByBaseOid.value,
825
+ type: params.pgTypes.get(p.baseOid)?.name ?? "unknown"
826
+ };
827
+ return typeByBaseOid.isArray ? { kind: "array", value: baseType } : baseType;
828
+ }
829
+ const getEnumByOid = (oid) => {
830
+ const pgEnum = params.pgEnums.get(oid);
831
+ if (pgEnum === void 0) {
832
+ return void 0;
833
+ }
834
+ return {
835
+ kind: "union",
836
+ value: pgEnum.values.map((value2) => ({
837
+ kind: "type",
838
+ value: `'${value2}'`,
839
+ type: pgEnum.name
840
+ }))
841
+ };
842
+ };
843
+ const valueAsEnum = (() => {
844
+ const enumType = getEnumByOid(p.oid);
845
+ if (enumType !== void 0) {
846
+ return enumType;
847
+ }
848
+ if (pgType?.typelem !== void 0 && pgType.typelem !== 0) {
849
+ const arrayEnumValue = getEnumByOid(pgType.typelem);
850
+ if (arrayEnumValue !== void 0) {
851
+ return {
852
+ kind: "array",
853
+ value: arrayEnumValue
854
+ };
855
+ }
856
+ }
857
+ return void 0;
858
+ })();
859
+ if (valueAsEnum !== void 0) {
860
+ return valueAsEnum;
861
+ }
862
+ const { isArray, value } = typeByBaseOid ?? typeByOid;
863
+ const type = {
864
+ kind: "type",
865
+ value,
866
+ type: pgType?.name ?? "unknown"
867
+ };
868
+ if (p.baseOid !== null) {
869
+ type.base = params.pgTypes.get(p.baseOid)?.name;
870
+ }
871
+ return isArray ? { kind: "array", value: type } : type;
872
+ }
873
+ };
874
+ const targetLists = [select.targetList, select.larg?.targetList, select.rarg?.targetList].filter(
875
+ (x) => x !== void 0
876
+ );
877
+ const resolvedColumnsList = [];
878
+ for (const [targetListIdx, targetList] of targetLists.entries()) {
879
+ resolvedColumnsList[targetListIdx] = targetList.map((target) => {
880
+ const described = getDescribedNode({
881
+ alias: void 0,
882
+ node: target,
883
+ context
884
+ });
885
+ if (described.length === 0) {
886
+ return [void 0];
887
+ }
888
+ return described;
889
+ }).flat();
890
+ }
891
+ const columnsLength = resolvedColumnsList.reduce((acc, x) => Math.max(acc, x.length), 0);
892
+ const final = /* @__PURE__ */ new Map();
893
+ for (let i = 0; i < columnsLength; i++) {
894
+ const result = mergeColumns(resolvedColumnsList.map((x) => x[i]));
895
+ final.set(i, result);
896
+ }
897
+ return {
898
+ map: final,
899
+ meta: {
900
+ relations,
901
+ nonNullableColumns
902
+ }
903
+ };
904
+ }
905
+ function mergeColumns(columns) {
906
+ const definedColumns = columns.filter((x) => x !== void 0);
907
+ if (definedColumns.length === 0) {
908
+ return void 0;
909
+ }
910
+ const name = definedColumns[0].name;
911
+ const type = mergeDescribedColumnTypes(definedColumns.map((x) => x.type));
912
+ return { name, type };
913
+ }
914
+ function getDescribedNode(params) {
915
+ const { alias, node, context } = params;
916
+ if (node.ResTarget !== void 0) {
917
+ return getDescribedResTarget({ node: node.ResTarget, context });
918
+ }
919
+ if (node.A_Const !== void 0) {
920
+ return getDescribedAConst({ alias, node: node.A_Const, context });
921
+ }
922
+ if (node.ColumnRef !== void 0) {
923
+ return getDescribedColumnRef({ alias, node: node.ColumnRef, context });
924
+ }
925
+ if (node.FuncCall !== void 0) {
926
+ return getDescribedFuncCall({ alias, node: node.FuncCall, context });
927
+ }
928
+ if (node.TypeCast !== void 0) {
929
+ return getDescribedTypeCast({ alias, node: node.TypeCast, context });
930
+ }
931
+ if (node.A_ArrayExpr !== void 0) {
932
+ return getDescribedArrayExpr({ alias, node: node.A_ArrayExpr, context });
933
+ }
934
+ if (node.CoalesceExpr !== void 0) {
935
+ return getDescribedCoalesceExpr({ alias, node: node.CoalesceExpr, context });
936
+ }
937
+ if (node.SubLink !== void 0) {
938
+ return getDescribedSubLink({ alias, node: node.SubLink, context });
939
+ }
940
+ if (node.BoolExpr !== void 0) {
941
+ return getDescribedBoolExpr({ alias, node: node.BoolExpr, context });
942
+ }
943
+ if (node.CaseExpr !== void 0) {
944
+ return getDescribedCaseExpr({ alias, node: node.CaseExpr, context });
945
+ }
946
+ if (node.NullTest !== void 0) {
947
+ return getDescribedNullTest({ alias, node: node.NullTest, context });
948
+ }
949
+ if (node.A_Expr !== void 0) {
950
+ return getDescribedAExpr({ alias, node: node.A_Expr, context });
951
+ }
952
+ if (node.SelectStmt !== void 0) {
953
+ return getDescribedSelectStmt({ alias, node: node.SelectStmt, context });
954
+ }
955
+ return [];
956
+ }
957
+ function getDescribedAExpr({
958
+ alias,
959
+ node,
960
+ context
961
+ }) {
962
+ const name = alias ?? "?column?";
963
+ if (node.lexpr === void 0 && node.rexpr !== void 0) {
964
+ const described = getDescribedNode({ alias, node: node.rexpr, context }).at(0);
965
+ const type2 = checkSql_utils.fmap(described, (x) => getBaseType(x.type));
966
+ if (type2 === null) return [];
967
+ return [{ name, type: type2 }];
968
+ }
969
+ if (node.lexpr === void 0 || node.rexpr === void 0) {
970
+ return [];
971
+ }
972
+ const getResolvedNullableValueOrNull = (node2) => {
973
+ const column = getDescribedNode({ alias: void 0, node: node2, context }).at(0);
974
+ if (column === void 0) return null;
975
+ const getFromType = (type2) => {
976
+ switch (true) {
977
+ case type2.kind === "type":
978
+ return { value: type2.base ?? type2.type, array: false, nullable: false };
979
+ case (type2.kind === "literal" && type2.base.kind === "type"):
980
+ return { value: type2.base.type, array: false, nullable: false };
981
+ case (type2.kind === "union" && type2.value.every((x) => x.kind === "literal")): {
982
+ const resolved = getFromType(type2.value[0].base);
983
+ if (resolved === null) return null;
984
+ return { value: resolved.value, nullable: false, array: false };
985
+ }
986
+ case (type2.kind === "union" && isTuple(type2.value)): {
987
+ let nullable = false;
988
+ let value = void 0;
989
+ for (const valueType of type2.value) {
990
+ if (valueType.kind !== "type") return null;
991
+ if (valueType.value === "null") nullable = true;
992
+ if (valueType.value !== "null") value = valueType.type;
993
+ }
994
+ if (value === void 0) return null;
995
+ return { value, nullable, array: false };
996
+ }
997
+ case type2.kind === "object":
998
+ return { value: "jsonb", array: false, nullable: false };
999
+ default:
1000
+ return null;
1001
+ }
1002
+ };
1003
+ if (column.type.kind === "array") {
1004
+ const resolved = getFromType(column.type.value);
1005
+ if (!resolved) return null;
1006
+ return { value: resolved.value, nullable: resolved.nullable, array: true };
1007
+ }
1008
+ return getFromType(column.type);
1009
+ };
1010
+ const lnode = getResolvedNullableValueOrNull(node.lexpr);
1011
+ const rnode = getResolvedNullableValueOrNull(node.rexpr);
1012
+ const operator = concatStringNodes(node.name);
1013
+ if (lnode === null || rnode === null) {
1014
+ return [];
1015
+ }
1016
+ const downcast = () => {
1017
+ const left = lnode.array ? `_${lnode.value}` : lnode.value;
1018
+ const right = rnode.array ? `_${rnode.value}` : rnode.value;
1019
+ const overrides = {
1020
+ "int4 ^ int4": ["float8", "^", "float8"]
1021
+ };
1022
+ if (overrides[`${left} ${operator} ${right}`]) {
1023
+ return overrides[`${left} ${operator} ${right}`];
1024
+ }
1025
+ const adjust = (value) => value === "varchar" ? "text" : value;
1026
+ return [adjust(left), operator, adjust(right)];
1027
+ };
1028
+ const getNullable = () => {
1029
+ if (context.nonNullableColumns.has(name)) {
1030
+ return false;
1031
+ }
1032
+ if (lnode.nullable || rnode.nullable) {
1033
+ return true;
1034
+ }
1035
+ const operatorForcesNullable = ["->>", "#>>"].includes(operator) && hasColumnReference(node.lexpr);
1036
+ return operatorForcesNullable;
1037
+ };
1038
+ const getType = () => {
1039
+ const nullable = getNullable();
1040
+ const [dleft, doperator, dright] = downcast();
1041
+ const type2 = context.typeExprMap.get(dleft)?.get(doperator)?.get(dright) ?? context.typeExprMap.get("anycompatiblearray")?.get(operator)?.get("anycompatiblearray") ?? context.typeExprMap.get("anyarray")?.get(operator)?.get("anyarray") ?? context.typeExprMap.get(lnode.value)?.get(operator)?.values().next().value;
1042
+ if (type2 === void 0) {
1043
+ return;
1044
+ }
1045
+ if (type2 === "anycompatiblearray") {
1046
+ return {
1047
+ kind: "array",
1048
+ value: resolveType({
1049
+ context,
1050
+ nullable,
1051
+ type: context.toTypeScriptType({ name: lnode.value })
1052
+ })
1053
+ };
1054
+ }
1055
+ return resolveType({
1056
+ context,
1057
+ nullable,
1058
+ type: context.toTypeScriptType({ name: type2 })
1059
+ });
1060
+ };
1061
+ const type = getType();
1062
+ if (type === void 0) {
1063
+ return [];
1064
+ }
1065
+ return [{ name, type }];
1066
+ }
1067
+ function getDescribedNullTest({
1068
+ alias,
1069
+ context
1070
+ }) {
1071
+ return [
1072
+ {
1073
+ name: alias ?? "?column?",
1074
+ type: resolveType({
1075
+ context,
1076
+ nullable: false,
1077
+ type: context.toTypeScriptType({ name: "bool" })
1078
+ })
1079
+ }
1080
+ ];
1081
+ }
1082
+ function getDescribedCaseExpr({
1083
+ alias,
1084
+ node,
1085
+ context
1086
+ }) {
1087
+ const results = [];
1088
+ for (const arg of node.args) {
1089
+ if (arg.CaseWhen?.result !== void 0) {
1090
+ results.push(getDescribedNode({ alias: void 0, node: arg.CaseWhen.result, context }));
1091
+ }
1092
+ }
1093
+ results.push(
1094
+ node.defresult !== void 0 ? getDescribedNode({ alias: void 0, node: node.defresult, context }) : [{ name: "?column?", type: context.toTypeScriptType({ name: "null" }) }]
1095
+ );
1096
+ const types = results.flat().map((x) => x.type);
1097
+ const literalsOnly = types.some((x) => x.kind !== "literal" && x.value !== "null");
1098
+ const value = mergeDescribedColumnTypes(literalsOnly ? types.map(getBaseType) : types);
1099
+ return [
1100
+ {
1101
+ name: alias ?? "case",
1102
+ type: value
1103
+ }
1104
+ ];
1105
+ }
1106
+ function getBaseType(type) {
1107
+ switch (type.kind) {
1108
+ case "object":
1109
+ case "union":
1110
+ case "array":
1111
+ case "type":
1112
+ return type;
1113
+ case "literal":
1114
+ return type.base;
1115
+ }
1116
+ }
1117
+ function getDescribedBoolExpr({
1118
+ alias,
1119
+ context
1120
+ }) {
1121
+ return [
1122
+ {
1123
+ name: alias ?? "?column?",
1124
+ type: resolveType({
1125
+ context,
1126
+ nullable: false,
1127
+ type: context.toTypeScriptType({ name: "bool" })
1128
+ })
1129
+ }
1130
+ ];
1131
+ }
1132
+ function getDescribedSubLink({
1133
+ alias,
1134
+ context,
1135
+ node
1136
+ }) {
1137
+ const getSubLinkType = () => {
1138
+ if (node.subLinkType === SubLinkType.EXISTS_SUBLINK) {
1139
+ return context.toTypeScriptType({ name: "bool" });
1140
+ }
1141
+ if (node.subLinkType === SubLinkType.EXPR_SUBLINK) {
1142
+ const described = node.subselect?.SelectStmt ? getDescribedNode({
1143
+ alias: void 0,
1144
+ node: { SelectStmt: node.subselect.SelectStmt },
1145
+ context
1146
+ }) : [];
1147
+ return described.length > 0 ? described[0].type : context.toTypeScriptType({ name: "unknown" });
1148
+ }
1149
+ return context.toTypeScriptType({ name: "unknown" });
1150
+ };
1151
+ return [
1152
+ {
1153
+ name: alias ?? "exists",
1154
+ type: resolveType({
1155
+ context,
1156
+ nullable: false,
1157
+ type: getSubLinkType()
1158
+ })
1159
+ }
1160
+ ];
1161
+ }
1162
+ function getDescribedSelectStmt({
1163
+ alias,
1164
+ context,
1165
+ node
1166
+ }) {
1167
+ const subParsed = {
1168
+ version: 0,
1169
+ stmts: [{ stmt: { SelectStmt: node }, stmtLocation: 0, stmtLen: 0 }]
1170
+ };
1171
+ const subDescription = getASTDescription({
1172
+ parsed: subParsed,
1173
+ typesMap: context.typesMap,
1174
+ typeExprMap: context.typeExprMap,
1175
+ overridenColumnTypesMap: context.overridenColumnTypesMap,
1176
+ pgColsBySchemaAndTableName: context.pgColsBySchemaAndTableName,
1177
+ pgTypes: context.pgTypes,
1178
+ pgEnums: context.pgEnums,
1179
+ pgFns: context.pgFns,
1180
+ fieldTransform: context.fieldTransform
1181
+ });
1182
+ const firstColumn = subDescription.map.get(0);
1183
+ if (firstColumn) {
1184
+ return [
1185
+ {
1186
+ name: alias ?? firstColumn.name,
1187
+ type: firstColumn.type
1188
+ }
1189
+ ];
1190
+ }
1191
+ return [];
1192
+ }
1193
+ function getDescribedCoalesceExpr({
1194
+ alias,
1195
+ context,
1196
+ node
1197
+ }) {
1198
+ const firstArg = node.args.at(0);
1199
+ const unknownCoalesce = {
1200
+ name: alias ?? "coalesce",
1201
+ type: context.toTypeScriptType({ name: "unknown" })
1202
+ };
1203
+ if (firstArg === void 0) {
1204
+ return [unknownCoalesce];
1205
+ }
1206
+ const type = getDescribedNode({ alias: void 0, node: firstArg, context }).map((x) => asNonNullableType(x.type)).at(0);
1207
+ if (type === void 0) {
1208
+ return [];
1209
+ }
1210
+ return [
1211
+ {
1212
+ name: alias ?? "coalesce",
1213
+ type
1214
+ }
1215
+ ];
1216
+ }
1217
+ function getDescribedArrayExpr({
1218
+ alias,
1219
+ context,
1220
+ node
1221
+ }) {
1222
+ const types = mergeDescribedColumnTypes(
1223
+ node.elements.flatMap((node2) => getDescribedNode({ alias: void 0, node: node2, context })).map((x) => x.type)
1224
+ );
1225
+ return [
1226
+ {
1227
+ name: alias ?? "?column?",
1228
+ type: {
1229
+ kind: "array",
1230
+ value: types
1231
+ }
1232
+ }
1233
+ ];
1234
+ }
1235
+ function mergeDescribedColumnTypes(types) {
1236
+ const result = [];
1237
+ const seenSymbols = /* @__PURE__ */ new Set();
1238
+ function processType(type) {
1239
+ switch (type.kind) {
1240
+ case "union":
1241
+ type.value.forEach((subtype) => processType(subtype));
1242
+ break;
1243
+ case "type":
1244
+ case "literal":
1245
+ if (!seenSymbols.has(type.value)) {
1246
+ seenSymbols.add(type.value);
1247
+ result.push(type);
1248
+ }
1249
+ break;
1250
+ case "object":
1251
+ case "array":
1252
+ result.push(type);
1253
+ break;
1254
+ }
1255
+ }
1256
+ for (const t of types) {
1257
+ processType(t);
1258
+ }
1259
+ if (!seenSymbols.has("boolean") && seenSymbols.has("true") && seenSymbols.has("false")) {
1260
+ seenSymbols.add("boolean");
1261
+ result.push({ kind: "type", value: "boolean", type: "bool" });
1262
+ }
1263
+ if (seenSymbols.has("boolean") && (seenSymbols.has("true") || seenSymbols.has("false"))) {
1264
+ const filtered = result.filter(
1265
+ (t) => !(t.kind === "literal" && (t.value === "true" || t.value === "false"))
1266
+ );
1267
+ return isSingleCell(filtered) ? filtered[0] : { kind: "union", value: filtered };
1268
+ }
1269
+ return isSingleCell(result) ? result[0] : { kind: "union", value: result };
1270
+ }
1271
+ function getDescribedTypeCast({
1272
+ alias,
1273
+ context,
1274
+ node
1275
+ }) {
1276
+ let typeName = node.typeName?.names.at(-1)?.String?.sval;
1277
+ if (typeName === "int") {
1278
+ typeName = "int4";
1279
+ }
1280
+ if (typeName === void 0 || node.arg === void 0) {
1281
+ return [];
1282
+ }
1283
+ const type = context.toTypeScriptType({ name: typeName });
1284
+ const innerDescribed = getDescribedNode({ alias, node: node.arg, context }).at(0);
1285
+ const nullable = checkSql_utils.fmap(innerDescribed, (x) => isDescribedColumnNullable(x.type)) ?? true;
1286
+ switch (true) {
1287
+ case node.arg.FuncCall !== void 0: {
1288
+ return [
1289
+ {
1290
+ name: alias ?? node.arg.FuncCall?.funcname.at(-1)?.String?.sval ?? "?column?",
1291
+ type: resolveType({ context, nullable, type })
1292
+ }
1293
+ ];
1294
+ }
1295
+ case node.arg.ColumnRef !== void 0: {
1296
+ return [
1297
+ {
1298
+ name: alias ?? concatStringNodes(node.arg.ColumnRef.fields),
1299
+ type: resolveType({ context, nullable, type })
1300
+ }
1301
+ ];
1302
+ }
1303
+ default: {
1304
+ return [
1305
+ {
1306
+ name: alias ?? typeName ?? "?column?",
1307
+ type: resolveType({ context, nullable, type })
1308
+ }
1309
+ ];
1310
+ }
1311
+ }
1312
+ }
1313
+ function getDescribedResTarget(params) {
1314
+ const { node, context } = params;
1315
+ if (node.val === void 0) {
1316
+ return [];
1317
+ }
1318
+ return getDescribedNode({
1319
+ alias: node.name,
1320
+ context,
1321
+ node: node.val
1322
+ });
1323
+ }
1324
+ function getDescribedFuncCall(params) {
1325
+ const functionName = params.node.funcname.at(-1)?.String?.sval;
1326
+ if (functionName === void 0) {
1327
+ return [];
1328
+ }
1329
+ switch (true) {
1330
+ case functionName === "json_build_object":
1331
+ case functionName === "jsonb_build_object":
1332
+ return getDescribedJsonBuildObjectFunCall(params);
1333
+ case functionName === "json_agg":
1334
+ case functionName === "jsonb_agg":
1335
+ return getDescribedJsonAggFunCall(params);
1336
+ case functionName === "array_agg":
1337
+ return getDescribedArrayAggFunCall(params);
1338
+ case functionName === "unnest":
1339
+ return getDescribedUnnestFunCall(params);
1340
+ default:
1341
+ return getDescribedFuncCallByPgFn(params);
1342
+ }
1343
+ }
1344
+ function getDescribedUnnestFunCall({
1345
+ alias,
1346
+ context,
1347
+ node
1348
+ }) {
1349
+ const functionName = node.funcname.at(-1)?.String?.sval ?? "";
1350
+ const name = alias ?? functionName;
1351
+ const firstArg = node.args?.at(0);
1352
+ if (firstArg === void 0) {
1353
+ return [{ name, type: context.toTypeScriptType({ name: "unknown" }) }];
1354
+ }
1355
+ const described = getDescribedNode({ alias: void 0, node: firstArg, context }).at(0);
1356
+ if (described === void 0) {
1357
+ return [{ name, type: context.toTypeScriptType({ name: "unknown" }) }];
1358
+ }
1359
+ function unwrap(type) {
1360
+ if (type.kind === "array") {
1361
+ return unwrap(type.value);
1362
+ }
1363
+ if (type.kind === "union") {
1364
+ const hasArray = type.value.some((t) => t.kind === "array");
1365
+ const unwrapped = type.value.filter((t) => !hasArray || !(t.kind === "type" && t.value === "null")).map(unwrap);
1366
+ return mergeDescribedColumnTypes(unwrapped);
1367
+ }
1368
+ if (type.kind === "type" && type.type.startsWith("_")) {
1369
+ return { ...type, type: type.type.slice(1) };
1370
+ }
1371
+ return type;
1372
+ }
1373
+ return [{ name, type: unwrap(described.type) }];
1374
+ }
1375
+ function getDescribedFuncCallByPgFn({
1376
+ alias,
1377
+ context,
1378
+ node
1379
+ }) {
1380
+ const functionName = node.funcname.at(-1)?.String?.sval;
1381
+ const name = alias ?? functionName ?? "?column?";
1382
+ const args = (node.args ?? []).flatMap((node2) => {
1383
+ const described = getDescribedNode({ alias: void 0, node: node2, context }).at(0);
1384
+ if (described?.type.kind === "type") {
1385
+ return [described.type.value];
1386
+ }
1387
+ return [];
1388
+ });
1389
+ if (functionName === void 0) {
1390
+ return [{ name, type: context.toTypeScriptType({ name: "unknown" }) }];
1391
+ }
1392
+ const pgFnValue = args.length === 0 ? context.pgFns.get(functionName) ?? context.pgFns.get(`${functionName}(string)`) : context.pgFns.get(`${functionName}(${args.join(", ")})`) ?? context.pgFns.get(`${functionName}(any)`) ?? context.pgFns.get(`${functionName}(unknown)`);
1393
+ const type = resolveType({
1394
+ context,
1395
+ nullable: !context.nonNullableColumns.has(name),
1396
+ type: { kind: "type", value: pgFnValue?.ts ?? "unknown", type: pgFnValue?.pg ?? "unknown" }
1397
+ });
1398
+ return [{ name, type }];
1399
+ }
1400
+ function getDescribedArrayAggFunCall({
1401
+ alias,
1402
+ context,
1403
+ node
1404
+ }) {
1405
+ const name = alias ?? concatStringNodes(node.funcname);
1406
+ const firstArg = checkSql_utils.fmap(node.args?.at(0), (node2) => {
1407
+ return {
1408
+ node: node2,
1409
+ described: getDescribedNode({ alias: void 0, node: node2, context })
1410
+ };
1411
+ });
1412
+ if (firstArg === null) {
1413
+ return [
1414
+ {
1415
+ name,
1416
+ type: context.toTypeScriptType({ name: "unknown" })
1417
+ }
1418
+ ];
1419
+ }
1420
+ const isSourceRef = context.resolver.sources.get(concatStringNodes(firstArg.node.ColumnRef?.fields)) !== void 0;
1421
+ const type = resolveType({
1422
+ context,
1423
+ nullable: !context.nonNullableColumns.has(name),
1424
+ type: {
1425
+ kind: "array",
1426
+ value: isSourceRef || firstArg.described.length > 1 ? {
1427
+ kind: "object",
1428
+ value: firstArg.described.map((x) => [x.name, x.type])
1429
+ } : firstArg.described[0].type
1430
+ }
1431
+ });
1432
+ return [{ name, type }];
1433
+ }
1434
+ function getDescribedJsonAggFunCall({
1435
+ alias,
1436
+ context,
1437
+ node
1438
+ }) {
1439
+ const name = alias ?? concatStringNodes(node.funcname);
1440
+ if (node.args === void 0 || !isSingleCell(node.args)) {
1441
+ return [];
1442
+ }
1443
+ const argNode = node.args[0];
1444
+ const cellType = getDescribedNode({ alias: void 0, node: argNode, context });
1445
+ if (cellType.length === 0) {
1446
+ return [];
1447
+ }
1448
+ const isSourceRef = context.resolver.sources.get(concatStringNodes(argNode.ColumnRef?.fields)) !== void 0;
1449
+ const type = resolveType({
1450
+ context,
1451
+ nullable: !context.nonNullableColumns.has(name),
1452
+ type: {
1453
+ kind: "array",
1454
+ value: isSourceRef || cellType.length > 1 ? {
1455
+ kind: "object",
1456
+ value: cellType.map((x) => [x.name, x.type])
1457
+ } : cellType[0].type
1458
+ }
1459
+ });
1460
+ return [{ name, type }];
1461
+ }
1462
+ function getDescribedJsonBuildObjectFunCall({
1463
+ alias,
1464
+ context,
1465
+ node
1466
+ }) {
1467
+ const functionName = node.funcname.at(-1)?.String?.sval ?? "";
1468
+ const name = alias ?? functionName;
1469
+ const unknownDescribedColumn = {
1470
+ name,
1471
+ type: context.toTypeScriptType({ name: "unknown" })
1472
+ };
1473
+ if (node.args === void 0) {
1474
+ return [unknownDescribedColumn];
1475
+ }
1476
+ const describedColumn = { kind: "object", value: [] };
1477
+ for (const [idx, arg] of node.args.entries()) {
1478
+ if (idx % 2 === 1) {
1479
+ continue;
1480
+ }
1481
+ const valueNode = node.args.at(idx + 1);
1482
+ if (valueNode === void 0) {
1483
+ throw new Error(checkSql_utils.normalizeIndent`
1484
+ argument list must have even number of elements
1485
+ Hint: The arguments of ${functionName}() must consist of alternating keys and values.
1486
+ `);
1487
+ }
1488
+ const alias2 = arg.A_Const?.sval?.sval;
1489
+ const type = checkSql_utils.fmap(node.args[idx + 1], (node2) => {
1490
+ return getDescribedNode({ alias: alias2, node: node2, context }).at(0)?.type ?? null;
1491
+ });
1492
+ if (alias2 === void 0 || type === null) {
1493
+ return [unknownDescribedColumn];
1494
+ }
1495
+ const transformedKey = checkSql_utils.toCase(alias2, context.fieldTransform);
1496
+ describedColumn.value.push([transformedKey, resolveType({ context, nullable: false, type })]);
1497
+ }
1498
+ return [
1499
+ {
1500
+ name,
1501
+ type: describedColumn
1502
+ }
1503
+ ];
1504
+ }
1505
+ function getColumnRefOrigins({
1506
+ context,
1507
+ node
1508
+ }) {
1509
+ if (isColumnTableStarRef(node.fields)) {
1510
+ const source = node.fields[0].String.sval;
1511
+ return (
1512
+ // lookup in cte
1513
+ context.select.withClause?.ctes.find((cte) => cte.CommonTableExpr?.ctename === source)?.CommonTableExpr?.ctequery?.SelectStmt?.targetList ?? // lookup in subselect
1514
+ context.select.fromClause?.map((from) => from.RangeSubselect).find((subselect) => subselect?.alias?.aliasname === source)?.subquery?.SelectStmt?.targetList
1515
+ );
1516
+ }
1517
+ if (isColumnTableColumnRef(node.fields)) {
1518
+ const source = node.fields[0].String.sval;
1519
+ const column = node.fields[1].String.sval;
1520
+ const origin = (
1521
+ // lookup in cte
1522
+ context.select.withClause?.ctes.find((cte) => cte.CommonTableExpr?.ctename === source)?.CommonTableExpr?.ctequery?.SelectStmt?.targetList?.find(
1523
+ (x) => x.ResTarget?.name === column
1524
+ ) ?? // lookup in subselect
1525
+ context.select.fromClause?.map((from) => from.RangeSubselect).find((subselect) => subselect?.alias?.aliasname === source)?.subquery?.SelectStmt?.targetList?.find((x) => x.ResTarget?.name === column)
1526
+ );
1527
+ if (!origin) return void 0;
1528
+ return [origin];
1529
+ }
1530
+ }
1531
+ function getContextForColumnRef(context, node) {
1532
+ if (isColumnTableColumnRef(node.fields) || isColumnTableStarRef(node.fields)) {
1533
+ const sourceName = node.fields[0].String.sval;
1534
+ const source = context.resolver.sources.get(sourceName);
1535
+ if (source?.kind === "cte") {
1536
+ return { ...context, resolver: source.sources };
1537
+ }
1538
+ }
1539
+ return context;
1540
+ }
1541
+ function getDescribedColumnRef({
1542
+ alias,
1543
+ context,
1544
+ node
1545
+ }) {
1546
+ const definitionNodes = getColumnRefOrigins({ context, node });
1547
+ if (definitionNodes) {
1548
+ const defContext = getContextForColumnRef(context, node);
1549
+ return definitionNodes.flatMap(
1550
+ (node2) => getDescribedNode({ alias, node: node2, context: defContext })
1551
+ );
1552
+ }
1553
+ return getDescribedColumnRefFromSchema({ alias, context, node });
1554
+ }
1555
+ function getDescribedColumnRefFromSchema({
1556
+ alias,
1557
+ context,
1558
+ node
1559
+ }) {
1560
+ if (isColumnStarRef(node.fields)) {
1561
+ return getDescribedColumnByResolvedColumns({
1562
+ alias,
1563
+ context,
1564
+ resolved: context.resolver.getAllResolvedColumns().map((x) => x.column)
1565
+ });
1566
+ }
1567
+ if (isColumnTableStarRef(node.fields)) {
1568
+ return getDescribedColumnByResolvedColumns({
1569
+ alias,
1570
+ context,
1571
+ resolved: context.resolver.getResolvedColumnsInTable(node.fields[0].String.sval)
1572
+ });
1573
+ }
1574
+ if (isColumnUnknownRef(node.fields)) {
1575
+ const resolved = context.resolver.getColumnsByTargetField({
1576
+ kind: "unknown",
1577
+ field: node.fields[0].String.sval
1578
+ });
1579
+ return getDescribedColumnByResolvedColumns({
1580
+ alias,
1581
+ context,
1582
+ resolved: resolved ?? []
1583
+ });
1584
+ }
1585
+ if (isColumnTableColumnRef(node.fields)) {
1586
+ const resolved = context.resolver.getNestedResolvedTargetField({
1587
+ kind: "column",
1588
+ table: node.fields[0].String.sval,
1589
+ column: node.fields[1].String.sval
1590
+ });
1591
+ return getDescribedColumnByResolvedColumns({
1592
+ alias,
1593
+ context,
1594
+ resolved: checkSql_utils.fmap(resolved, (x) => [x]) ?? []
1595
+ });
1596
+ }
1597
+ return [];
1598
+ }
1599
+ function getDescribedColumnByResolvedColumns(params) {
1600
+ return params.resolved.map(({ column, isNotNull }) => {
1601
+ const getType = () => {
1602
+ const overridenType = params.context.overridenColumnTypesMap.get(column.tableName)?.get(column.colName);
1603
+ if (overridenType !== void 0) {
1604
+ return {
1605
+ kind: "type",
1606
+ value: overridenType,
1607
+ type: params.context.pgTypes.get(column.colTypeOid)?.name ?? "unknown"
1608
+ };
1609
+ }
1610
+ return params.context.toTypeScriptType({
1611
+ oid: column.colTypeOid,
1612
+ baseOid: column.colBaseTypeOid
1613
+ });
1614
+ };
1615
+ return {
1616
+ name: params.alias ?? column.colName,
1617
+ type: resolveType({
1618
+ context: params.context,
1619
+ nullable: !isNotNull,
1620
+ type: getType()
1621
+ })
1622
+ };
1623
+ });
1624
+ }
1625
+ function getDescribedAConst({
1626
+ alias,
1627
+ context,
1628
+ node
1629
+ }) {
1630
+ const type = (() => {
1631
+ switch (true) {
1632
+ case node.boolval !== void 0:
1633
+ return {
1634
+ kind: "literal",
1635
+ value: node.boolval.boolval ? "true" : "false",
1636
+ base: context.toTypeScriptType({ name: "bool" })
1637
+ };
1638
+ case node.bsval !== void 0:
1639
+ return context.toTypeScriptType({ name: "bytea" });
1640
+ case node.fval !== void 0:
1641
+ return {
1642
+ kind: "literal",
1643
+ value: node.fval.toString(),
1644
+ base: context.toTypeScriptType({ name: "float8" })
1645
+ };
1646
+ case node.isnull !== void 0:
1647
+ return context.toTypeScriptType({ name: "null" });
1648
+ case node.ival !== void 0:
1649
+ return {
1650
+ kind: "literal",
1651
+ value: (node.ival.ival ?? 0).toString(),
1652
+ base: context.toTypeScriptType({ name: "int4" })
1653
+ };
1654
+ case node.sval !== void 0:
1655
+ return {
1656
+ kind: "literal",
1657
+ value: `'${node.sval.sval}'`,
1658
+ base: context.toTypeScriptType({ name: "text" })
1659
+ };
1660
+ default:
1661
+ return context.toTypeScriptType({ name: "unknown" });
1662
+ }
1663
+ })();
1664
+ return [
1665
+ {
1666
+ name: alias ?? "?column?",
1667
+ type: resolveType({ context, nullable: node.isnull === true, type })
1668
+ }
1669
+ ];
1670
+ }
1671
+ function asNonNullableType(type) {
1672
+ switch (type.kind) {
1673
+ case "object":
1674
+ case "array":
1675
+ case "literal":
1676
+ return type;
1677
+ case "union": {
1678
+ const filtered = type.value.filter(
1679
+ (described) => described.kind !== "type" || described.value !== "null"
1680
+ );
1681
+ if (filtered.length === 0) {
1682
+ return { kind: "type", value: "unknown", type: "unknown" };
1683
+ }
1684
+ if (filtered.length === 1) {
1685
+ return filtered[0];
1686
+ }
1687
+ return { kind: "union", value: filtered };
1688
+ }
1689
+ case "type":
1690
+ return type.value === "null" ? { kind: "type", value: "unknown", type: "unknown" } : type;
1691
+ }
1692
+ }
1693
+ function isDescribedColumnNullable(type) {
1694
+ return type.kind === "union" && type.value.some((x) => x.kind === "type" && x.value === "null");
1695
+ }
1696
+ function resolveType(params) {
1697
+ if (params.nullable && params.type.value !== "null") {
1698
+ return {
1699
+ kind: "union",
1700
+ value: [params.type, params.context.toTypeScriptType({ name: "null" })]
1701
+ };
1702
+ }
1703
+ return params.type;
1704
+ }
1705
+ function concatStringNodes(nodes) {
1706
+ return nodes?.map((x) => x.String?.sval).filter(Boolean).join(".") ?? "";
1707
+ }
1708
+ function hasColumnReference(node) {
1709
+ if (node === void 0) {
1710
+ return false;
1711
+ }
1712
+ if (node.ColumnRef !== void 0) {
1713
+ return true;
1714
+ }
1715
+ if (node.A_Const !== void 0) {
1716
+ return false;
1717
+ }
1718
+ if (node.TypeCast !== void 0) {
1719
+ return hasColumnReference(node.TypeCast.arg);
1720
+ }
1721
+ if (node.A_Expr !== void 0) {
1722
+ return hasColumnReference(node.A_Expr.lexpr) || hasColumnReference(node.A_Expr.rexpr);
1723
+ }
1724
+ if (node.BoolExpr !== void 0) {
1725
+ return (node.BoolExpr.args ?? []).some(hasColumnReference);
1726
+ }
1727
+ if (node.FuncCall !== void 0) {
1728
+ return (node.FuncCall.args ?? []).some(hasColumnReference);
1729
+ }
1730
+ if (node.CoalesceExpr !== void 0) {
1731
+ return node.CoalesceExpr.args.some(hasColumnReference);
1732
+ }
1733
+ if (node.CaseExpr !== void 0) {
1734
+ if (node.CaseExpr.arg && hasColumnReference(node.CaseExpr.arg)) {
1735
+ return true;
1736
+ }
1737
+ if (node.CaseExpr.defresult && hasColumnReference(node.CaseExpr.defresult)) {
1738
+ return true;
1739
+ }
1740
+ return node.CaseExpr.args.some((caseWhen) => {
1741
+ if (caseWhen.CaseWhen === void 0) {
1742
+ return false;
1743
+ }
1744
+ return hasColumnReference(caseWhen.CaseWhen.expr) || hasColumnReference(caseWhen.CaseWhen.result);
1745
+ });
1746
+ }
1747
+ if (node.A_ArrayExpr !== void 0) {
1748
+ return (node.A_ArrayExpr.elements ?? []).some(hasColumnReference);
1749
+ }
1750
+ if (node.SubLink !== void 0) {
1751
+ return true;
1752
+ }
1753
+ return false;
1754
+ }
1755
+
1756
+ function isParsedInsertResult(parsed) {
1757
+ return parsed.stmts[0]?.stmt?.InsertStmt !== void 0;
1758
+ }
1759
+ function validateInsertResult(parsed, pgColsBySchemaAndTableName, query) {
1760
+ const insertStmt = parsed.stmts[0].stmt.InsertStmt;
1761
+ if (insertStmt.relation === void 0) {
1762
+ return;
1763
+ }
1764
+ const schemaName = insertStmt.relation.schemaname ?? "public";
1765
+ const tableName = insertStmt.relation.relname;
1766
+ const tableCols = pgColsBySchemaAndTableName.get(schemaName)?.get(tableName);
1767
+ if (tableCols === void 0) {
1768
+ return;
1769
+ }
1770
+ const insertCols = getInsertColumns(insertStmt, tableCols);
1771
+ const missing = tableCols.filter(
1772
+ (c) => c.colNotNull && !c.colHasDef && c.colIdentity === "" && !insertCols.includes(c.colName)
1773
+ );
1774
+ if (missing.length === 0) {
1775
+ return;
1776
+ }
1777
+ const position = (parsed.stmts[0]?.stmtLocation ?? 0) + 1;
1778
+ const columnsStr = missing.map((c) => `"${c.colName}"`).join(", ");
1779
+ const message = missing.length === 1 ? [
1780
+ `null value in column ${columnsStr} violates not-null constraint`,
1781
+ `Hint: Column ${columnsStr} is not nullable and has no default value.`
1782
+ ].join("\n") : [
1783
+ `null value in columns ${columnsStr} violates not-null constraint`,
1784
+ `Hint: Columns ${columnsStr} are not nullable and have no default value.`
1785
+ ].join("\n");
1786
+ throw checkSql_utils.PostgresError.of({
1787
+ queryText: query.text,
1788
+ message,
1789
+ line: "1",
1790
+ position,
1791
+ sourcemaps: query.sourcemaps
1792
+ });
1793
+ }
1794
+ function getInsertColumns(stmt, tableCols) {
1795
+ if (stmt.cols) {
1796
+ return stmt.cols.map((col) => col.ResTarget?.name).filter((name) => Boolean(name));
1797
+ }
1798
+ if (stmt.selectStmt === void 0) {
1799
+ return [];
1800
+ }
1801
+ const valuesFromSelect = stmt.selectStmt.SelectStmt?.valuesLists?.at(0)?.List?.items;
1802
+ if (valuesFromSelect !== void 0) {
1803
+ return tableCols.slice(0, valuesFromSelect.length).map((c) => c.colName);
1804
+ }
1805
+ return tableCols.map((c) => c.colName);
1806
+ }
1807
+
1808
+ function createEmptyCache() {
1809
+ return {
1810
+ base: /* @__PURE__ */ new Map(),
1811
+ overrides: {
1812
+ types: /* @__PURE__ */ new Map(),
1813
+ columns: /* @__PURE__ */ new Map()
1814
+ },
1815
+ functions: /* @__PURE__ */ new Map()
1816
+ };
1817
+ }
1818
+ function createGenerator() {
1819
+ const cache = createEmptyCache();
1820
+ return {
1821
+ generate: (params) => generate(params, cache),
1822
+ dropCacheKey: (cacheKey) => cache.base.delete(cacheKey),
1823
+ clearCache: () => {
1824
+ cache.base.clear();
1825
+ cache.overrides.types.clear();
1826
+ cache.overrides.columns.clear();
1827
+ cache.functions.clear();
1828
+ }
1829
+ };
1830
+ }
1831
+ async function generate(params, cache) {
1832
+ const { sql, query, cacheKey, cacheMetadata = true } = params;
1833
+ const {
1834
+ pgColsByTableOidCache,
1835
+ pgColsBySchemaAndTableName,
1836
+ pgTypes,
1837
+ pgEnums,
1838
+ pgFnsByName,
1839
+ pgTypeExprMap
1840
+ } = await checkSql_utils.getOrSetFromMapWithEnabled({
1841
+ shouldCache: cacheMetadata,
1842
+ map: cache.base,
1843
+ key: cacheKey,
1844
+ value: () => getDatabaseMetadata(sql)
1845
+ });
1846
+ const typesMap = await checkSql_utils.getOrSetFromMapWithEnabled({
1847
+ shouldCache: cacheMetadata,
1848
+ map: cache.overrides.types,
1849
+ key: JSON.stringify(params.overrides?.types),
1850
+ value: () => {
1851
+ const map = /* @__PURE__ */ new Map([["array", { override: false, value: "array" }]]);
1852
+ for (const [key, value] of checkSql_utils.defaultTypesMap.entries()) {
1853
+ map.set(key, { override: false, value });
1854
+ }
1855
+ for (const [k, v] of Object.entries(params.overrides?.types ?? {})) {
1856
+ map.set(k, { override: true, value: typeof v === "string" ? v : v.return });
1857
+ }
1858
+ return map;
1859
+ }
1860
+ });
1861
+ const overridenColumnTypesMap = await checkSql_utils.getOrSetFromMapWithEnabled({
1862
+ shouldCache: cacheMetadata,
1863
+ map: cache.overrides.columns,
1864
+ key: JSON.stringify(params.overrides?.columns),
1865
+ value: () => {
1866
+ const map = /* @__PURE__ */ new Map();
1867
+ for (const [colPath, type] of Object.entries(params.overrides?.columns ?? {})) {
1868
+ const [table, column] = colPath.split(".");
1869
+ if (table === void 0 || column === void 0) {
1870
+ throw new Error(`Invalid override column key: ${colPath}. Expected format: table.column`);
1871
+ }
1872
+ map.has(table) ? map.get(table)?.set(column, type) : map.set(table, /* @__PURE__ */ new Map([[column, type]]));
1873
+ }
1874
+ return map;
1875
+ }
1876
+ });
1877
+ function byReturnType(a, b) {
1878
+ const priority = ["numeric", "int8"];
1879
+ return priority.indexOf(a.returnType) - priority.indexOf(b.returnType);
1880
+ }
1881
+ const functionsMap = await checkSql_utils.getOrSetFromMapWithEnabled({
1882
+ shouldCache: cacheMetadata,
1883
+ map: cache.functions,
1884
+ key: JSON.stringify(params.overrides?.types),
1885
+ value: () => {
1886
+ const map = /* @__PURE__ */ new Map();
1887
+ for (const [functionName, signatures] of pgFnsByName.entries()) {
1888
+ for (const signature of signatures.sort(byReturnType)) {
1889
+ const tsArgs = signature.arguments.map((arg) => {
1890
+ return typesMap.get(arg)?.value ?? "unknown";
1891
+ });
1892
+ const tsReturnType = typesMap.get(signature.returnType)?.value ?? signature.returnType;
1893
+ const key = tsArgs.length === 0 ? functionName : `${functionName}(${tsArgs.join(", ")})`;
1894
+ map.set(key, { ts: tsReturnType, pg: signature.returnType });
1895
+ }
1896
+ }
1897
+ return map;
1898
+ }
1899
+ });
1900
+ try {
1901
+ const result = await sql.unsafe(query.text, [], { prepare: true }).describe();
1902
+ const parsed = await parser__namespace.parse(query.text);
1903
+ if (isParsedInsertResult(parsed)) {
1904
+ validateInsertResult(parsed, pgColsBySchemaAndTableName, query);
1905
+ }
1906
+ if (result.columns === void 0 || result.columns === null || result.columns.length === 0) {
1907
+ return fpTs.either.right({ output: null, unknownColumns: [], stmt: result, query });
1908
+ }
1909
+ const duplicateCols = result.columns.filter(
1910
+ (col, index) => result.columns.find((c, i) => c.name === col.name && i != index)
1911
+ );
1912
+ if (duplicateCols.length > 0) {
1913
+ const dupes = duplicateCols.map((col) => {
1914
+ const tableCols = pgColsByTableOidCache.get(col.table);
1915
+ const tableCol = col.number !== 0 ? tableCols?.at(col.number - 1) : tableCols?.find((c) => c.colName === col.name);
1916
+ return {
1917
+ table: tableCol?.tableName,
1918
+ column: col.name,
1919
+ originalColumn: tableCol?.colName
1920
+ };
1921
+ });
1922
+ const dupePosition = (() => {
1923
+ const match = query.text.search(new RegExp(`\\b${duplicateCols[0].name}\\b`));
1924
+ return (match > -1 ? match : query.text.search(/SELECT/i)) + 1;
1925
+ })();
1926
+ return fpTs.either.left(
1927
+ checkSql_utils.DuplicateColumnsError.of({
1928
+ queryText: query.text,
1929
+ sourcemaps: query.sourcemaps,
1930
+ position: dupePosition,
1931
+ columns: dupes.map((x) => {
1932
+ return x.column !== x.originalColumn ? `${x.table}.${x.originalColumn} (alias: ${x.column})` : `${x.table}.${x.column}`;
1933
+ })
1934
+ })
1935
+ );
1936
+ }
1937
+ const astQueryDescription = getASTDescription({
1938
+ parsed,
1939
+ typesMap,
1940
+ overridenColumnTypesMap,
1941
+ pgColsBySchemaAndTableName,
1942
+ pgTypes,
1943
+ pgEnums,
1944
+ pgFns: functionsMap,
1945
+ typeExprMap: pgTypeExprMap,
1946
+ fieldTransform: params.fieldTransform
1947
+ });
1948
+ const columns = result.columns.map((col, position) => {
1949
+ const introspected = pgColsByTableOidCache.get(col.table)?.find((x) => x.colNum === col.number);
1950
+ const astDescribed = astQueryDescription.map.get(position);
1951
+ return {
1952
+ described: col,
1953
+ astDescribed,
1954
+ introspected,
1955
+ isNonNullableBasedOnAST: astQueryDescription.meta.nonNullableColumns.has(col.name)
1956
+ };
1957
+ });
1958
+ const context = {
1959
+ columns,
1960
+ pgTypes,
1961
+ pgEnums,
1962
+ relationsWithJoins: astQueryDescription.meta.relations,
1963
+ overrides: {
1964
+ types: typesMap,
1965
+ columns: overridenColumnTypesMap
1966
+ },
1967
+ pgColsBySchemaAndTableName,
1968
+ fieldTransform: params.fieldTransform
1969
+ };
1970
+ return fpTs.either.right({
1971
+ output: getTypedColumnEntries({ context }),
1972
+ unknownColumns: columns.filter((x) => x.astDescribed === void 0).map((x) => x.described.name),
1973
+ stmt: result,
1974
+ query
1975
+ });
1976
+ } catch (e) {
1977
+ if (checkSql_utils.isPostgresError(e)) {
1978
+ return fpTs.either.left(
1979
+ checkSql_utils.PostgresError.of({
1980
+ queryText: query.text,
1981
+ sourcemaps: query.sourcemaps,
1982
+ message: e.message,
1983
+ line: e.line,
1984
+ position: e.position
1985
+ })
1986
+ );
1987
+ }
1988
+ throw e;
1989
+ }
1990
+ }
1991
+ async function getDatabaseMetadata(sql) {
1992
+ const pgTypes = await getPgTypes(sql);
1993
+ const pgCols = await getPgCols(sql);
1994
+ const pgEnums = await getPgEnums(sql);
1995
+ const pgFns = await getPgFunctions(sql);
1996
+ const pgColsByTableOidCache = checkSql_utils.groupBy(pgCols, "tableOid");
1997
+ const pgColsBySchemaAndTableName = checkSql_utils.groupBy(pgCols, "schemaName", "tableName");
1998
+ const pgFnsByName = checkSql_utils.groupBy(pgFns, "name");
1999
+ const pgTypeExprMap = await getPgTypeExprMap(sql);
2000
+ return {
2001
+ pgTypes,
2002
+ pgCols,
2003
+ pgEnums,
2004
+ pgColsByTableOidCache,
2005
+ pgColsBySchemaAndTableName,
2006
+ pgFnsByName,
2007
+ pgTypeExprMap
2008
+ };
2009
+ }
2010
+ function getTypedColumnEntries(params) {
2011
+ const value = params.context.columns.map(
2012
+ (col) => getResolvedTargetEntry({ col, context: params.context })
2013
+ );
2014
+ return { kind: "object", value };
2015
+ }
2016
+ function isNullableResolvedTarget(target) {
2017
+ switch (target.kind) {
2018
+ case "type":
2019
+ return ["any", "null"].includes(target.value) === false;
2020
+ case "union":
2021
+ return target.value.some(isNullableResolvedTarget);
2022
+ case "array":
2023
+ return isNullableResolvedTarget(target.value);
2024
+ case "object":
2025
+ return target.value.some(([, value]) => isNullableResolvedTarget(value));
2026
+ case "literal":
2027
+ return false;
2028
+ }
2029
+ }
2030
+ function buildInterfacePropertyValue(params) {
2031
+ const isNullable = params.isNullable && isNullableResolvedTarget(params.value);
2032
+ return [
2033
+ params.key,
2034
+ isNullable ? { kind: "union", value: [params.value, { kind: "type", value: "null", type: "null" }] } : params.value
2035
+ ];
2036
+ }
2037
+ function checkIsNullableDueToRelation(params) {
2038
+ const { col, relationsWithJoins } = params;
2039
+ const findByJoin = relationsWithJoins.find((x) => x.joinRelName === col.tableName);
2040
+ if (findByJoin !== void 0) {
2041
+ switch (findByJoin.joinType) {
2042
+ case JoinType.JOIN_LEFT:
2043
+ case JoinType.JOIN_FULL:
2044
+ return true;
2045
+ case JoinType.JOIN_TYPE_UNDEFINED:
2046
+ case JoinType.JOIN_INNER:
2047
+ case JoinType.JOIN_RIGHT:
2048
+ case JoinType.JOIN_SEMI:
2049
+ case JoinType.JOIN_ANTI:
2050
+ case JoinType.JOIN_UNIQUE_OUTER:
2051
+ case JoinType.JOIN_UNIQUE_INNER:
2052
+ case JoinType.UNRECOGNIZED:
2053
+ return false;
2054
+ default:
2055
+ checkSql_utils.assertNever(findByJoin.joinType);
2056
+ }
2057
+ }
2058
+ const findByRel = relationsWithJoins.filter((x) => x.relName === col.tableName);
2059
+ for (const rel of findByRel) {
2060
+ switch (rel.joinType) {
2061
+ case JoinType.JOIN_RIGHT:
2062
+ case JoinType.JOIN_FULL:
2063
+ return true;
2064
+ case JoinType.JOIN_TYPE_UNDEFINED:
2065
+ case JoinType.JOIN_INNER:
2066
+ case JoinType.JOIN_LEFT:
2067
+ case JoinType.JOIN_SEMI:
2068
+ case JoinType.JOIN_ANTI:
2069
+ case JoinType.JOIN_UNIQUE_OUTER:
2070
+ case JoinType.JOIN_UNIQUE_INNER:
2071
+ case JoinType.UNRECOGNIZED:
2072
+ return false;
2073
+ default:
2074
+ checkSql_utils.assertNever(rel.joinType);
2075
+ }
2076
+ }
2077
+ return false;
2078
+ }
2079
+ function getResolvedTargetEntry(params) {
2080
+ if (params.col.astDescribed !== void 0) {
2081
+ return [
2082
+ checkSql_utils.toCase(params.col.described.name, params.context.fieldTransform),
2083
+ params.col.astDescribed.type
2084
+ ];
2085
+ }
2086
+ const pgTypeOid = params.col.introspected?.colBaseTypeOid ?? params.col.described.type;
2087
+ const pgType = params.context.pgTypes.get(pgTypeOid);
2088
+ const getEnumByOid = (oid) => {
2089
+ const pgEnum = params.context.pgEnums.get(oid);
2090
+ if (pgEnum === void 0) {
2091
+ return void 0;
2092
+ }
2093
+ return {
2094
+ kind: "union",
2095
+ value: pgEnum.values.map(
2096
+ (value2) => ({
2097
+ kind: "type",
2098
+ value: `'${value2}'`,
2099
+ type: pgEnum.name
2100
+ })
2101
+ )
2102
+ };
2103
+ };
2104
+ const valueAsEnum = (() => {
2105
+ const enumTarget = getEnumByOid(pgTypeOid);
2106
+ if (enumTarget !== void 0) {
2107
+ return enumTarget;
2108
+ }
2109
+ if (pgType?.typelem !== void 0 && pgType.typelem !== 0) {
2110
+ const elemEnumTarget = getEnumByOid(pgType.typelem);
2111
+ if (elemEnumTarget !== void 0) {
2112
+ return { kind: "array", value: elemEnumTarget };
2113
+ }
2114
+ }
2115
+ return void 0;
2116
+ })();
2117
+ const valueAsType = getTsTypeFromPgTypeOid({
2118
+ pgTypeOid,
2119
+ pgTypes: params.context.pgTypes
2120
+ });
2121
+ const valueAsOverride = (() => {
2122
+ const pgType2 = params.context.pgTypes.get(
2123
+ params.col.introspected?.colTypeOid ?? params.col.described.type
2124
+ );
2125
+ if (!pgType2) return void 0;
2126
+ const columnOverride = params?.context?.overrides?.columns.get(params.col.introspected?.tableName ?? "")?.get(params.col.introspected?.colName ?? params.col.described.name);
2127
+ if (columnOverride !== void 0) {
2128
+ return { kind: "type", value: columnOverride, type: pgType2.name };
2129
+ }
2130
+ const typeOverride = params?.context?.overrides?.types.get(pgType2.name);
2131
+ if (typeOverride !== void 0) {
2132
+ return {
2133
+ kind: "type",
2134
+ value: typeOverride.value,
2135
+ type: pgType2.name
2136
+ };
2137
+ }
2138
+ return void 0;
2139
+ })();
2140
+ const value = valueAsOverride ?? valueAsEnum ?? valueAsType;
2141
+ const key = params.col.described.name ?? params.col.introspected?.colName;
2142
+ let isNonNullable = params.col.isNonNullableBasedOnAST;
2143
+ if (!isNonNullable && params.col.introspected !== void 0) {
2144
+ isNonNullable = params.col.introspected.colNotNull;
2145
+ if (checkIsNullableDueToRelation({
2146
+ col: params.col.introspected,
2147
+ relationsWithJoins: params.context.relationsWithJoins
2148
+ })) {
2149
+ isNonNullable = false;
2150
+ }
2151
+ }
2152
+ return buildInterfacePropertyValue({
2153
+ key: checkSql_utils.toCase(key, params.context.fieldTransform),
2154
+ value,
2155
+ isNullable: !isNonNullable
2156
+ });
2157
+ }
2158
+ function getTsTypeFromPgTypeOid(params) {
2159
+ const pgType = params.pgTypes.get(params.pgTypeOid);
2160
+ if (pgType === void 0) {
2161
+ return { kind: "type", value: "unknown", type: "unknown" };
2162
+ }
2163
+ return getTsTypeFromPgType({ pgTypeName: pgType.name });
2164
+ }
2165
+ function getTsTypeFromPgType(params) {
2166
+ const { isArray, pgType } = parsePgType(params.pgTypeName);
2167
+ const tsType = checkSql_utils.defaultTypesMap.get(pgType) ?? "any";
2168
+ const property = { kind: "type", value: tsType, type: pgType };
2169
+ return isArray ? { kind: "array", value: property } : property;
2170
+ }
2171
+ function isPgTypeArray(pgType) {
2172
+ return pgType.startsWith("_");
2173
+ }
2174
+ function parsePgType(pgType) {
2175
+ const isArray = isPgTypeArray(pgType);
2176
+ return {
2177
+ isArray,
2178
+ pgType: isArray ? pgType.slice(1) : pgType
2179
+ };
2180
+ }
2181
+ async function getPgEnums(sql) {
2182
+ const rows = await sql`
2183
+ SELECT pg_type.oid, pg_type.typname, pg_enum.enumlabel
2184
+ FROM pg_type
2185
+ JOIN pg_enum ON pg_enum.enumtypid = pg_type.oid
2186
+ WHERE pg_type.typtype = 'e'
2187
+ ORDER BY pg_type.typname, pg_enum.enumsortorder
2188
+ `;
2189
+ const map = /* @__PURE__ */ new Map();
2190
+ for (const row of rows) {
2191
+ const existing = map.get(row.oid);
2192
+ if (existing === void 0) {
2193
+ map.set(row.oid, {
2194
+ name: row.typname,
2195
+ values: [row.enumlabel]
2196
+ });
2197
+ continue;
2198
+ }
2199
+ existing.values.push(row.enumlabel);
2200
+ }
2201
+ return map;
2202
+ }
2203
+ async function getPgTypes(sql) {
2204
+ const rows = await sql`
2205
+ SELECT oid, typname as name, typelem FROM pg_type
2206
+ `;
2207
+ const map = /* @__PURE__ */ new Map();
2208
+ for (const row of rows) {
2209
+ map.set(row.oid, row);
2210
+ }
2211
+ return map;
2212
+ }
2213
+ async function getPgCols(sql) {
2214
+ const rows = await sql`
2215
+ SELECT
2216
+ pg_class.oid AS "tableOid",
2217
+ pg_namespace.nspname AS "schemaName",
2218
+ pg_class.relname AS "tableName",
2219
+ pg_attribute.attname AS "colName",
2220
+ pg_type.oid AS "colTypeOid",
2221
+ CASE
2222
+ WHEN pg_type.typtype = 'd' THEN
2223
+ (SELECT pt.oid FROM pg_type pt WHERE pt.oid = pg_type.typbasetype)
2224
+ ELSE
2225
+ NULL
2226
+ END AS "colBaseTypeOid",
2227
+ pg_attribute.attnum AS "colNum",
2228
+ pg_attribute.atthasdef "colHasDef",
2229
+ pg_attribute.attnotnull "colNotNull",
2230
+ pg_attribute.attidentity "colIdentity"
2231
+ FROM
2232
+ pg_attribute,
2233
+ pg_class,
2234
+ pg_type,
2235
+ pg_namespace
2236
+ WHERE TRUE
2237
+ AND pg_attribute.attrelid = pg_class.oid
2238
+ AND pg_attribute.atttypid = pg_type.oid
2239
+ AND pg_class.relnamespace = pg_namespace.oid
2240
+ AND pg_attribute.attnum >= 1
2241
+ ORDER BY
2242
+ pg_class.relname,
2243
+ pg_attribute.attnum
2244
+ `;
2245
+ return rows;
2246
+ }
2247
+ async function getPgFunctions(sql) {
2248
+ const rows = await sql`
2249
+ SELECT
2250
+ pg_proc.proname AS "name",
2251
+ pg_catalog.pg_get_function_arguments(pg_proc.oid) AS "argumentsString",
2252
+ pg_type.typname AS "returnType"
2253
+ FROM
2254
+ pg_catalog.pg_proc
2255
+ JOIN
2256
+ pg_catalog.pg_type ON pg_proc.prorettype = pg_type.oid
2257
+ WHERE
2258
+ pg_proc.pronamespace::regnamespace = 'pg_catalog'::regnamespace
2259
+ `;
2260
+ return rows.map((row) => ({
2261
+ name: row.name,
2262
+ arguments: row.argumentsString.replace(/"/, "").split(", ").filter((x) => x !== ""),
2263
+ returnType: row.returnType
2264
+ }));
2265
+ }
2266
+ async function getPgTypeExprMap(sql) {
2267
+ const rows = await sql`
2268
+ SELECT
2269
+ l.typname as left,
2270
+ o.oprname as operator,
2271
+ r.typname as right,
2272
+ ret.typname AS result
2273
+ FROM pg_operator o
2274
+ JOIN pg_type l ON l.oid = o.oprleft
2275
+ JOIN pg_type r ON r.oid = o.oprright
2276
+ JOIN pg_type ret ON ret.oid = o.oprresult
2277
+ WHERE o.oprleft <> 0 AND o.oprright <> 0
2278
+ `;
2279
+ const map = /* @__PURE__ */ new Map();
2280
+ for (const row of rows) {
2281
+ const leftMap = map.get(row.left) ?? /* @__PURE__ */ new Map();
2282
+ const rightMap = leftMap.get(row.operator) ?? /* @__PURE__ */ new Map();
2283
+ rightMap.set(row.right, row.result);
2284
+ leftMap.set(row.operator, rightMap);
2285
+ map.set(row.left, leftMap);
2286
+ }
2287
+ return map;
2288
+ }
2289
+
2290
+ function createConnectionManager() {
2291
+ const connectionMap = /* @__PURE__ */ new Map();
2292
+ return {
2293
+ getOrCreate: (databaseUrl, options) => getOrCreateConnection(databaseUrl, connectionMap, options),
2294
+ close: (params) => closeConnection(params, connectionMap)
2295
+ };
2296
+ }
2297
+ function getOrCreateConnection(databaseUrl, connectionMap, options) {
2298
+ return function_js.pipe(
2299
+ O__namespace.fromNullable(connectionMap.get(databaseUrl)),
2300
+ O__namespace.foldW(
2301
+ () => {
2302
+ const sql = postgres__default(databaseUrl, options);
2303
+ connectionMap.set(databaseUrl, sql);
2304
+ return { sql, databaseUrl, isFirst: true };
2305
+ },
2306
+ (sql) => ({ sql, databaseUrl, isFirst: false })
2307
+ )
2308
+ );
2309
+ }
2310
+ function closeConnection(params, connectionMap) {
2311
+ const { connection, projectDir } = params;
2312
+ const strategy = checkSql_utils.getConnectionStrategyByRuleOptionConnection({ connection, projectDir });
2313
+ tsPattern.match(strategy).with({ type: "databaseUrl" }, ({ databaseUrl }) => {
2314
+ const sql = connectionMap.get(databaseUrl);
2315
+ if (sql) {
2316
+ sql.end();
2317
+ connectionMap.delete(databaseUrl);
2318
+ }
2319
+ }).with({ type: "migrations" }, ({ connectionUrl, databaseName }) => {
2320
+ const connectionOptions = { ...checkSql_utils.parseConnection(connectionUrl), database: databaseName };
2321
+ const databaseUrl = checkSql_utils.mapConnectionOptionsToString(connectionOptions);
2322
+ const sql = connectionMap.get(databaseUrl);
2323
+ const migrationSql = connectionMap.get(connectionUrl);
2324
+ if (sql) {
2325
+ sql.end();
2326
+ connectionMap.delete(databaseUrl);
2327
+ }
2328
+ if (migrationSql) {
2329
+ migrationSql.end();
2330
+ connectionMap.delete(connectionUrl);
2331
+ }
2332
+ }).exhaustive();
2333
+ }
2334
+
2335
+ function createWatchManager() {
2336
+ const migrationPaths = /* @__PURE__ */ new Map();
2337
+ const watcher = chokidar__default.watch([], { ignoreInitial: true }).on("all", (_, filePath) => {
2338
+ for (const [path2, { onChange }] of migrationPaths.entries()) {
2339
+ if (filePath.startsWith(path2)) {
2340
+ return onChange();
2341
+ }
2342
+ }
2343
+ });
2344
+ const watchMigrationsDir = (params) => {
2345
+ const migrationPath = path__default.join(params.projectDir, params.connection.migrationsDir);
2346
+ if (migrationPaths.has(migrationPath)) {
2347
+ return;
2348
+ }
2349
+ migrationPaths.set(migrationPath, {
2350
+ onChange: () => {
2351
+ const { databaseUrl } = checkSql_utils.getMigrationDatabaseMetadata({
2352
+ connectionUrl: params.connection.connectionUrl ?? checkSql_utils.DEFAULT_CONNECTION_URL,
2353
+ databaseName: checkSql_utils.getDatabaseName({
2354
+ databaseName: params.connection.databaseName,
2355
+ migrationsDir: params.connection.migrationsDir,
2356
+ projectDir: params.projectDir
2357
+ })
2358
+ });
2359
+ params.dropCacheKeyFn(databaseUrl);
2360
+ params.closeConnectionFn({ connection: params.connection, projectDir: params.projectDir });
2361
+ }
2362
+ });
2363
+ watcher.add(migrationPath);
2364
+ };
2365
+ return {
2366
+ watchMigrationsDir
2367
+ };
2368
+ }
2369
+
2370
+ const generator = createGenerator();
2371
+ const connections = createConnectionManager();
2372
+ const watchers = createWatchManager();
2373
+ async function handler(params) {
2374
+ if (checkSql_utils.isWatchMigrationsDirEnabled(params.connection)) {
2375
+ watchers.watchMigrationsDir({
2376
+ connection: params.connection,
2377
+ projectDir: params.projectDir,
2378
+ dropCacheKeyFn: generator.dropCacheKey,
2379
+ closeConnectionFn: connections.close
2380
+ });
2381
+ }
2382
+ const result = await function_js.pipe(
2383
+ TE__namespace.Do,
2384
+ TE__namespace.chain(() => workerHandler(params))
2385
+ )();
2386
+ if (params.connection.keepAlive === false) {
2387
+ connections.close({ connection: params.connection, projectDir: params.projectDir });
2388
+ }
2389
+ return J__namespace.stringify(result);
2390
+ }
2391
+ synckit.runAsWorker(handler);
2392
+ function workerHandler(params) {
2393
+ const strategy = checkSql_utils.getConnectionStrategyByRuleOptionConnection(params);
2394
+ const connectionPayload = tsPattern.match(strategy).with(
2395
+ { type: "databaseUrl" },
2396
+ ({ databaseUrl }) => TE__namespace.right(connections.getOrCreate(databaseUrl))
2397
+ ).with({ type: "migrations" }, ({ migrationsDir, databaseName, connectionUrl }) => {
2398
+ const { connectionOptions, databaseUrl } = checkSql_utils.getMigrationDatabaseMetadata({
2399
+ connectionUrl,
2400
+ databaseName
2401
+ });
2402
+ const { sql, isFirst } = connections.getOrCreate(databaseUrl);
2403
+ const { sql: migrationSql } = connections.getOrCreate(connectionUrl, {
2404
+ onnotice: () => {
2405
+ }
2406
+ });
2407
+ const connectionPayload2 = { sql, isFirst, databaseUrl };
2408
+ if (isFirst) {
2409
+ const migrationsPath = path__default.join(params.projectDir, migrationsDir);
2410
+ return function_js.pipe(
2411
+ TE__namespace.Do,
2412
+ TE__namespace.chainW(() => checkSql_utils.initDatabase(migrationSql, connectionOptions.database)),
2413
+ TE__namespace.chainW(() => checkSql_utils.runMigrations({ migrationsPath, sql })),
2414
+ TE__namespace.map(() => connectionPayload2)
2415
+ );
2416
+ }
2417
+ return TE__namespace.right(connectionPayload2);
2418
+ }).exhaustive();
2419
+ const generateTask = (params2) => {
2420
+ return TE__namespace.tryCatch(() => generator.generate(params2), checkSql_utils.InternalError.to);
2421
+ };
2422
+ return function_js.pipe(
2423
+ connectionPayload,
2424
+ TE__namespace.chainW(({ sql, databaseUrl }) => {
2425
+ return generateTask({
2426
+ sql,
2427
+ query: params.query,
2428
+ cacheKey: databaseUrl,
2429
+ overrides: params.connection.overrides,
2430
+ fieldTransform: params.target.fieldTransform
2431
+ });
2432
+ }),
2433
+ TE__namespace.chainW(TE__namespace.fromEither)
2434
+ );
2435
+ }
2436
+ //# sourceMappingURL=check-sql.worker.cjs.map