@leonardovida-md/drizzle-neo-duckdb 1.2.0 → 1.2.2
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.
- package/README.md +2 -1
- package/dist/duckdb-introspect.mjs +562 -73
- package/dist/index.mjs +554 -65
- package/dist/sql/ast-transformer.d.ts +18 -0
- package/dist/sql/visitors/column-qualifier.d.ts +5 -0
- package/dist/sql/visitors/generate-series-alias.d.ts +13 -0
- package/dist/sql/visitors/union-with-hoister.d.ts +11 -0
- package/package.json +2 -2
- package/src/sql/ast-transformer.ts +120 -18
- package/src/sql/visitors/column-qualifier.ts +393 -85
- package/src/sql/visitors/generate-series-alias.ts +291 -0
- package/src/sql/visitors/union-with-hoister.ts +106 -0
|
@@ -1,5 +1,10 @@
|
|
|
1
1
|
/**
|
|
2
2
|
* AST visitor to qualify unqualified column references in JOIN ON clauses.
|
|
3
|
+
*
|
|
4
|
+
* Performance optimizations:
|
|
5
|
+
* - Early exit when no unqualified columns found in ON clause
|
|
6
|
+
* - Skip processing if all columns are already qualified
|
|
7
|
+
* - Minimal tree traversal when possible
|
|
3
8
|
*/
|
|
4
9
|
|
|
5
10
|
import type {
|
|
@@ -17,6 +22,12 @@ import type {
|
|
|
17
22
|
type TableSource = {
|
|
18
23
|
name: string;
|
|
19
24
|
alias: string | null;
|
|
25
|
+
schema: string | null;
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
type Qualifier = {
|
|
29
|
+
table: string;
|
|
30
|
+
schema: string | null;
|
|
20
31
|
};
|
|
21
32
|
|
|
22
33
|
function getTableSource(from: From): TableSource | null {
|
|
@@ -24,19 +35,24 @@ function getTableSource(from: From): TableSource | null {
|
|
|
24
35
|
return {
|
|
25
36
|
name: from.table,
|
|
26
37
|
alias: from.as ?? null,
|
|
38
|
+
schema: 'db' in from ? (from.db ?? null) : null,
|
|
27
39
|
};
|
|
28
40
|
}
|
|
29
41
|
if ('expr' in from && from.as) {
|
|
30
42
|
return {
|
|
31
43
|
name: from.as,
|
|
32
44
|
alias: from.as,
|
|
45
|
+
schema: null,
|
|
33
46
|
};
|
|
34
47
|
}
|
|
35
48
|
return null;
|
|
36
49
|
}
|
|
37
50
|
|
|
38
|
-
function getQualifier(source: TableSource):
|
|
39
|
-
return
|
|
51
|
+
function getQualifier(source: TableSource): Qualifier {
|
|
52
|
+
return {
|
|
53
|
+
table: source.alias ?? source.name,
|
|
54
|
+
schema: source.schema,
|
|
55
|
+
};
|
|
40
56
|
}
|
|
41
57
|
|
|
42
58
|
function isUnqualifiedColumnRef(expr: ExpressionValue): expr is ColumnRefItem {
|
|
@@ -45,7 +61,18 @@ function isUnqualifiedColumnRef(expr: ExpressionValue): expr is ColumnRefItem {
|
|
|
45
61
|
expr !== null &&
|
|
46
62
|
'type' in expr &&
|
|
47
63
|
expr.type === 'column_ref' &&
|
|
48
|
-
!('table' in expr
|
|
64
|
+
(!('table' in expr) || !expr.table)
|
|
65
|
+
);
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
function isQualifiedColumnRef(expr: ExpressionValue): expr is ColumnRefItem {
|
|
69
|
+
return (
|
|
70
|
+
typeof expr === 'object' &&
|
|
71
|
+
expr !== null &&
|
|
72
|
+
'type' in expr &&
|
|
73
|
+
expr.type === 'column_ref' &&
|
|
74
|
+
'table' in expr &&
|
|
75
|
+
!!expr.table
|
|
49
76
|
);
|
|
50
77
|
}
|
|
51
78
|
|
|
@@ -59,51 +86,140 @@ function getColumnName(col: ColumnRefItem): string | null {
|
|
|
59
86
|
return null;
|
|
60
87
|
}
|
|
61
88
|
|
|
89
|
+
function applyQualifier(col: ColumnRefItem, qualifier: Qualifier): void {
|
|
90
|
+
col.table = qualifier.table;
|
|
91
|
+
if (!('schema' in col) || !col.schema) {
|
|
92
|
+
(col as ColumnRefItem & { schema?: string | null }).schema =
|
|
93
|
+
qualifier.schema;
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
function unwrapColumnRef(
|
|
98
|
+
expr: ExpressionValue | undefined
|
|
99
|
+
): ColumnRefItem | null {
|
|
100
|
+
if (!expr || typeof expr !== 'object') return null;
|
|
101
|
+
if ('type' in expr && expr.type === 'column_ref') {
|
|
102
|
+
return expr as ColumnRefItem;
|
|
103
|
+
}
|
|
104
|
+
if ('expr' in expr && expr.expr) {
|
|
105
|
+
return unwrapColumnRef(expr.expr as ExpressionValue);
|
|
106
|
+
}
|
|
107
|
+
if ('ast' in expr && expr.ast && typeof expr.ast === 'object') {
|
|
108
|
+
return null;
|
|
109
|
+
}
|
|
110
|
+
if ('args' in expr && expr.args) {
|
|
111
|
+
const args = expr.args as {
|
|
112
|
+
value?: ExpressionValue[];
|
|
113
|
+
expr?: ExpressionValue;
|
|
114
|
+
};
|
|
115
|
+
if (args.expr) {
|
|
116
|
+
return unwrapColumnRef(args.expr as ExpressionValue);
|
|
117
|
+
}
|
|
118
|
+
if (args.value && args.value.length === 1) {
|
|
119
|
+
return unwrapColumnRef(args.value[0] as ExpressionValue);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return null;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
function isBinaryExpr(
|
|
126
|
+
expr: ExpressionValue | Binary | null | undefined
|
|
127
|
+
): expr is Binary {
|
|
128
|
+
return (
|
|
129
|
+
!!expr &&
|
|
130
|
+
typeof expr === 'object' &&
|
|
131
|
+
'type' in expr &&
|
|
132
|
+
(expr as { type?: string }).type === 'binary_expr'
|
|
133
|
+
);
|
|
134
|
+
}
|
|
135
|
+
|
|
62
136
|
function walkOnClause(
|
|
63
|
-
expr: Binary | null | undefined,
|
|
64
|
-
|
|
65
|
-
|
|
137
|
+
expr: Binary | ExpressionValue | null | undefined,
|
|
138
|
+
leftQualifier: Qualifier,
|
|
139
|
+
rightQualifier: Qualifier,
|
|
66
140
|
ambiguousColumns: Set<string>
|
|
67
141
|
): boolean {
|
|
68
142
|
if (!expr || typeof expr !== 'object') return false;
|
|
69
143
|
|
|
70
144
|
let transformed = false;
|
|
71
145
|
|
|
72
|
-
if (expr
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
146
|
+
if (isBinaryExpr(expr)) {
|
|
147
|
+
const left = expr.left as ExpressionValue;
|
|
148
|
+
const right = expr.right as ExpressionValue;
|
|
149
|
+
|
|
150
|
+
const leftCol = unwrapColumnRef(left);
|
|
151
|
+
const rightCol = unwrapColumnRef(right);
|
|
152
|
+
|
|
153
|
+
const leftUnqualified = leftCol ? isUnqualifiedColumnRef(leftCol) : false;
|
|
154
|
+
const rightUnqualified = rightCol
|
|
155
|
+
? isUnqualifiedColumnRef(rightCol)
|
|
156
|
+
: false;
|
|
157
|
+
const leftQualified = leftCol ? isQualifiedColumnRef(leftCol) : false;
|
|
158
|
+
const rightQualified = rightCol ? isQualifiedColumnRef(rightCol) : false;
|
|
159
|
+
const leftColName = leftCol ? getColumnName(leftCol) : null;
|
|
160
|
+
const rightColName = rightCol ? getColumnName(rightCol) : null;
|
|
161
|
+
|
|
162
|
+
if (
|
|
163
|
+
expr.operator === '=' &&
|
|
164
|
+
leftColName &&
|
|
165
|
+
rightColName &&
|
|
166
|
+
leftColName === rightColName
|
|
167
|
+
) {
|
|
168
|
+
if (leftUnqualified && rightUnqualified) {
|
|
169
|
+
applyQualifier(leftCol!, leftQualifier);
|
|
170
|
+
applyQualifier(rightCol!, rightQualifier);
|
|
171
|
+
ambiguousColumns.add(leftColName);
|
|
172
|
+
transformed = true;
|
|
173
|
+
} else if (leftQualified && rightUnqualified) {
|
|
174
|
+
applyQualifier(rightCol!, rightQualifier);
|
|
175
|
+
ambiguousColumns.add(rightColName);
|
|
176
|
+
transformed = true;
|
|
177
|
+
} else if (leftUnqualified && rightQualified) {
|
|
178
|
+
applyQualifier(leftCol!, leftQualifier);
|
|
179
|
+
ambiguousColumns.add(leftColName);
|
|
180
|
+
transformed = true;
|
|
88
181
|
}
|
|
89
182
|
}
|
|
90
183
|
|
|
91
|
-
if (
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
)
|
|
184
|
+
if (
|
|
185
|
+
expr.operator === '=' &&
|
|
186
|
+
leftCol &&
|
|
187
|
+
rightCol &&
|
|
188
|
+
leftColName &&
|
|
189
|
+
rightColName &&
|
|
190
|
+
leftColName !== rightColName
|
|
191
|
+
) {
|
|
192
|
+
if (leftQualified && rightUnqualified && !rightColName.includes('.')) {
|
|
193
|
+
applyQualifier(rightCol, rightQualifier);
|
|
194
|
+
transformed = true;
|
|
195
|
+
} else if (
|
|
196
|
+
leftUnqualified &&
|
|
197
|
+
rightQualified &&
|
|
198
|
+
!leftColName.includes('.')
|
|
199
|
+
) {
|
|
200
|
+
applyQualifier(leftCol, leftQualifier);
|
|
201
|
+
transformed = true;
|
|
202
|
+
}
|
|
106
203
|
}
|
|
204
|
+
|
|
205
|
+
transformed =
|
|
206
|
+
walkOnClause(
|
|
207
|
+
isBinaryExpr(expr.left as Binary)
|
|
208
|
+
? (expr.left as Binary)
|
|
209
|
+
: (expr.left as ExpressionValue),
|
|
210
|
+
leftQualifier,
|
|
211
|
+
rightQualifier,
|
|
212
|
+
ambiguousColumns
|
|
213
|
+
) || transformed;
|
|
214
|
+
transformed =
|
|
215
|
+
walkOnClause(
|
|
216
|
+
isBinaryExpr(expr.right as Binary)
|
|
217
|
+
? (expr.right as Binary)
|
|
218
|
+
: (expr.right as ExpressionValue),
|
|
219
|
+
leftQualifier,
|
|
220
|
+
rightQualifier,
|
|
221
|
+
ambiguousColumns
|
|
222
|
+
) || transformed;
|
|
107
223
|
}
|
|
108
224
|
|
|
109
225
|
return transformed;
|
|
@@ -111,7 +227,7 @@ function walkOnClause(
|
|
|
111
227
|
|
|
112
228
|
function qualifyAmbiguousInExpression(
|
|
113
229
|
expr: ExpressionValue | null | undefined,
|
|
114
|
-
defaultQualifier:
|
|
230
|
+
defaultQualifier: Qualifier,
|
|
115
231
|
ambiguousColumns: Set<string>
|
|
116
232
|
): boolean {
|
|
117
233
|
if (!expr || typeof expr !== 'object') return false;
|
|
@@ -121,13 +237,13 @@ function qualifyAmbiguousInExpression(
|
|
|
121
237
|
if (isUnqualifiedColumnRef(expr)) {
|
|
122
238
|
const colName = getColumnName(expr);
|
|
123
239
|
if (colName && ambiguousColumns.has(colName)) {
|
|
124
|
-
expr
|
|
240
|
+
applyQualifier(expr, defaultQualifier);
|
|
125
241
|
transformed = true;
|
|
126
242
|
}
|
|
127
243
|
return transformed;
|
|
128
244
|
}
|
|
129
245
|
|
|
130
|
-
if (
|
|
246
|
+
if (isBinaryExpr(expr)) {
|
|
131
247
|
const binary = expr as Binary;
|
|
132
248
|
transformed =
|
|
133
249
|
qualifyAmbiguousInExpression(
|
|
@@ -169,79 +285,186 @@ function qualifyAmbiguousInExpression(
|
|
|
169
285
|
}
|
|
170
286
|
}
|
|
171
287
|
|
|
288
|
+
if ('over' in expr && expr.over && typeof expr.over === 'object') {
|
|
289
|
+
const over = expr.over as {
|
|
290
|
+
partition?: ExpressionValue[];
|
|
291
|
+
orderby?: ExpressionValue[];
|
|
292
|
+
};
|
|
293
|
+
if (Array.isArray(over.partition)) {
|
|
294
|
+
for (const part of over.partition) {
|
|
295
|
+
transformed =
|
|
296
|
+
qualifyAmbiguousInExpression(
|
|
297
|
+
part,
|
|
298
|
+
defaultQualifier,
|
|
299
|
+
ambiguousColumns
|
|
300
|
+
) || transformed;
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
if (Array.isArray(over.orderby)) {
|
|
304
|
+
for (const order of over.orderby) {
|
|
305
|
+
transformed =
|
|
306
|
+
qualifyAmbiguousInExpression(
|
|
307
|
+
order,
|
|
308
|
+
defaultQualifier,
|
|
309
|
+
ambiguousColumns
|
|
310
|
+
) || transformed;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
172
315
|
return transformed;
|
|
173
316
|
}
|
|
174
317
|
|
|
318
|
+
/**
|
|
319
|
+
* Quick check if an ON clause has any unqualified column references.
|
|
320
|
+
* Used for early exit optimization.
|
|
321
|
+
*/
|
|
322
|
+
function hasUnqualifiedColumns(expr: Binary | null | undefined): boolean {
|
|
323
|
+
if (!expr || typeof expr !== 'object') return false;
|
|
324
|
+
|
|
325
|
+
if ('type' in expr && expr.type === 'binary_expr') {
|
|
326
|
+
const left = expr.left as ExpressionValue;
|
|
327
|
+
const right = expr.right as ExpressionValue;
|
|
328
|
+
const leftCol = unwrapColumnRef(left);
|
|
329
|
+
const rightCol = unwrapColumnRef(right);
|
|
330
|
+
if (
|
|
331
|
+
isUnqualifiedColumnRef(left) ||
|
|
332
|
+
isUnqualifiedColumnRef(right) ||
|
|
333
|
+
(leftCol && isUnqualifiedColumnRef(leftCol)) ||
|
|
334
|
+
(rightCol && isUnqualifiedColumnRef(rightCol))
|
|
335
|
+
) {
|
|
336
|
+
return true;
|
|
337
|
+
}
|
|
338
|
+
if (
|
|
339
|
+
isBinaryExpr(expr.left as Binary) &&
|
|
340
|
+
hasUnqualifiedColumns(expr.left as Binary)
|
|
341
|
+
)
|
|
342
|
+
return true;
|
|
343
|
+
if (
|
|
344
|
+
isBinaryExpr(expr.right as Binary) &&
|
|
345
|
+
hasUnqualifiedColumns(expr.right as Binary)
|
|
346
|
+
)
|
|
347
|
+
return true;
|
|
348
|
+
}
|
|
349
|
+
|
|
350
|
+
if ('args' in expr && expr.args) {
|
|
351
|
+
const args = expr.args as {
|
|
352
|
+
value?: ExpressionValue[];
|
|
353
|
+
expr?: ExpressionValue;
|
|
354
|
+
};
|
|
355
|
+
if (args.expr && isUnqualifiedColumnRef(args.expr as ExpressionValue))
|
|
356
|
+
return true;
|
|
357
|
+
if (args.value) {
|
|
358
|
+
for (const arg of args.value) {
|
|
359
|
+
if (isUnqualifiedColumnRef(arg)) return true;
|
|
360
|
+
}
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
return false;
|
|
365
|
+
}
|
|
366
|
+
|
|
175
367
|
function walkSelect(select: Select): boolean {
|
|
176
368
|
let transformed = false;
|
|
177
369
|
const ambiguousColumns = new Set<string>();
|
|
178
370
|
|
|
179
371
|
if (Array.isArray(select.from) && select.from.length >= 2) {
|
|
180
372
|
const firstSource = getTableSource(select.from[0]);
|
|
181
|
-
const defaultQualifier = firstSource ? getQualifier(firstSource) :
|
|
373
|
+
const defaultQualifier = firstSource ? getQualifier(firstSource) : null;
|
|
182
374
|
let prevSource = firstSource;
|
|
183
375
|
|
|
376
|
+
let hasAnyUnqualified = false;
|
|
184
377
|
for (const from of select.from) {
|
|
185
378
|
if ('join' in from) {
|
|
186
379
|
const join = from as Join;
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
const leftQualifier = getQualifier(prevSource);
|
|
191
|
-
const rightQualifier = getQualifier(currentSource);
|
|
192
|
-
|
|
193
|
-
transformed =
|
|
194
|
-
walkOnClause(
|
|
195
|
-
join.on,
|
|
196
|
-
leftQualifier,
|
|
197
|
-
rightQualifier,
|
|
198
|
-
ambiguousColumns
|
|
199
|
-
) || transformed;
|
|
380
|
+
if (join.on && hasUnqualifiedColumns(join.on)) {
|
|
381
|
+
hasAnyUnqualified = true;
|
|
382
|
+
break;
|
|
200
383
|
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
201
386
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
prevSource = source;
|
|
387
|
+
if (!hasAnyUnqualified) {
|
|
388
|
+
for (const from of select.from) {
|
|
389
|
+
if ('expr' in from && from.expr && 'ast' in from.expr) {
|
|
390
|
+
transformed = walkSelect(from.expr.ast) || transformed;
|
|
207
391
|
}
|
|
208
392
|
}
|
|
393
|
+
} else {
|
|
394
|
+
for (const from of select.from) {
|
|
395
|
+
if ('join' in from) {
|
|
396
|
+
const join = from as Join;
|
|
397
|
+
const currentSource = getTableSource(join);
|
|
209
398
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
}
|
|
399
|
+
if (join.on && prevSource && currentSource) {
|
|
400
|
+
const leftQualifier = getQualifier(prevSource);
|
|
401
|
+
const rightQualifier = getQualifier(currentSource);
|
|
214
402
|
|
|
215
|
-
if (ambiguousColumns.size > 0 && defaultQualifier) {
|
|
216
|
-
if (Array.isArray(select.columns)) {
|
|
217
|
-
for (const col of select.columns as Column[]) {
|
|
218
|
-
if ('expr' in col) {
|
|
219
403
|
transformed =
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
404
|
+
walkOnClause(
|
|
405
|
+
join.on,
|
|
406
|
+
leftQualifier,
|
|
407
|
+
rightQualifier,
|
|
223
408
|
ambiguousColumns
|
|
224
409
|
) || transformed;
|
|
225
410
|
}
|
|
411
|
+
|
|
412
|
+
if (join.using && prevSource && currentSource) {
|
|
413
|
+
for (const usingCol of join.using) {
|
|
414
|
+
if (typeof usingCol === 'string') {
|
|
415
|
+
ambiguousColumns.add(usingCol);
|
|
416
|
+
} else if ('value' in usingCol) {
|
|
417
|
+
ambiguousColumns.add(
|
|
418
|
+
String((usingCol as { value: unknown }).value)
|
|
419
|
+
);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
|
|
424
|
+
prevSource = currentSource;
|
|
425
|
+
} else {
|
|
426
|
+
const source = getTableSource(from);
|
|
427
|
+
if (source) {
|
|
428
|
+
prevSource = source;
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
|
|
432
|
+
if ('expr' in from && from.expr && 'ast' in from.expr) {
|
|
433
|
+
transformed = walkSelect(from.expr.ast) || transformed;
|
|
226
434
|
}
|
|
227
435
|
}
|
|
228
436
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
select.
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
437
|
+
if (ambiguousColumns.size > 0 && defaultQualifier) {
|
|
438
|
+
if (Array.isArray(select.columns)) {
|
|
439
|
+
for (const col of select.columns as Column[]) {
|
|
440
|
+
if ('expr' in col) {
|
|
441
|
+
transformed =
|
|
442
|
+
qualifyAmbiguousInExpression(
|
|
443
|
+
col.expr,
|
|
444
|
+
defaultQualifier,
|
|
445
|
+
ambiguousColumns
|
|
446
|
+
) || transformed;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
}
|
|
235
450
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
451
|
+
transformed =
|
|
452
|
+
qualifyAmbiguousInExpression(
|
|
453
|
+
select.where,
|
|
454
|
+
defaultQualifier,
|
|
455
|
+
ambiguousColumns
|
|
456
|
+
) || transformed;
|
|
457
|
+
|
|
458
|
+
if (Array.isArray(select.orderby)) {
|
|
459
|
+
for (const order of select.orderby as OrderBy[]) {
|
|
460
|
+
if (order.expr) {
|
|
461
|
+
transformed =
|
|
462
|
+
qualifyAmbiguousInExpression(
|
|
463
|
+
order.expr,
|
|
464
|
+
defaultQualifier,
|
|
465
|
+
ambiguousColumns
|
|
466
|
+
) || transformed;
|
|
467
|
+
}
|
|
245
468
|
}
|
|
246
469
|
}
|
|
247
470
|
}
|
|
@@ -271,6 +494,91 @@ export function qualifyJoinColumns(ast: AST | AST[]): boolean {
|
|
|
271
494
|
for (const stmt of statements) {
|
|
272
495
|
if (stmt.type === 'select') {
|
|
273
496
|
transformed = walkSelect(stmt as Select) || transformed;
|
|
497
|
+
} else if (stmt.type === 'insert') {
|
|
498
|
+
const insert = stmt as unknown as { values?: unknown };
|
|
499
|
+
if (
|
|
500
|
+
insert.values &&
|
|
501
|
+
typeof insert.values === 'object' &&
|
|
502
|
+
'type' in insert.values &&
|
|
503
|
+
(insert.values as { type: string }).type === 'select'
|
|
504
|
+
) {
|
|
505
|
+
transformed =
|
|
506
|
+
walkSelect(insert.values as unknown as Select) || transformed;
|
|
507
|
+
}
|
|
508
|
+
} else if (stmt.type === 'update') {
|
|
509
|
+
const update = stmt as unknown as {
|
|
510
|
+
table?: From[];
|
|
511
|
+
from?: From[];
|
|
512
|
+
where?: ExpressionValue;
|
|
513
|
+
returning?: ExpressionValue | ExpressionValue[];
|
|
514
|
+
};
|
|
515
|
+
const mainSource = update.table?.[0]
|
|
516
|
+
? getTableSource(update.table[0] as From)
|
|
517
|
+
: null;
|
|
518
|
+
const defaultQualifier = mainSource ? getQualifier(mainSource) : null;
|
|
519
|
+
const fromSources = update.from ?? [];
|
|
520
|
+
const firstFrom = fromSources[0] ? getTableSource(fromSources[0]) : null;
|
|
521
|
+
if (update.where && defaultQualifier && firstFrom) {
|
|
522
|
+
const ambiguous = new Set<string>();
|
|
523
|
+
transformed =
|
|
524
|
+
walkOnClause(
|
|
525
|
+
update.where as Binary,
|
|
526
|
+
defaultQualifier,
|
|
527
|
+
getQualifier(firstFrom),
|
|
528
|
+
ambiguous
|
|
529
|
+
) || transformed;
|
|
530
|
+
transformed =
|
|
531
|
+
qualifyAmbiguousInExpression(
|
|
532
|
+
update.where,
|
|
533
|
+
defaultQualifier,
|
|
534
|
+
ambiguous
|
|
535
|
+
) || transformed;
|
|
536
|
+
}
|
|
537
|
+
if (Array.isArray(update.returning) && defaultQualifier) {
|
|
538
|
+
for (const ret of update.returning) {
|
|
539
|
+
transformed =
|
|
540
|
+
qualifyAmbiguousInExpression(
|
|
541
|
+
ret,
|
|
542
|
+
defaultQualifier,
|
|
543
|
+
new Set<string>()
|
|
544
|
+
) || transformed;
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
} else if (stmt.type === 'delete') {
|
|
548
|
+
const del = stmt as unknown as {
|
|
549
|
+
table?: From[];
|
|
550
|
+
from?: From[];
|
|
551
|
+
where?: ExpressionValue;
|
|
552
|
+
};
|
|
553
|
+
const mainSource = del.table?.[0]
|
|
554
|
+
? getTableSource(del.table[0] as From)
|
|
555
|
+
: null;
|
|
556
|
+
const defaultQualifier = mainSource ? getQualifier(mainSource) : null;
|
|
557
|
+
const fromSources = del.from ?? [];
|
|
558
|
+
const firstFrom = fromSources[0] ? getTableSource(fromSources[0]) : null;
|
|
559
|
+
if (del.where && defaultQualifier && firstFrom) {
|
|
560
|
+
const ambiguous = new Set<string>();
|
|
561
|
+
transformed =
|
|
562
|
+
walkOnClause(
|
|
563
|
+
del.where as Binary,
|
|
564
|
+
defaultQualifier,
|
|
565
|
+
getQualifier(firstFrom),
|
|
566
|
+
ambiguous
|
|
567
|
+
) || transformed;
|
|
568
|
+
transformed =
|
|
569
|
+
qualifyAmbiguousInExpression(
|
|
570
|
+
del.where,
|
|
571
|
+
defaultQualifier,
|
|
572
|
+
ambiguous
|
|
573
|
+
) || transformed;
|
|
574
|
+
} else if (del.where && defaultQualifier) {
|
|
575
|
+
transformed =
|
|
576
|
+
qualifyAmbiguousInExpression(
|
|
577
|
+
del.where,
|
|
578
|
+
defaultQualifier,
|
|
579
|
+
new Set<string>()
|
|
580
|
+
) || transformed;
|
|
581
|
+
}
|
|
274
582
|
}
|
|
275
583
|
}
|
|
276
584
|
|