@leonardovida-md/drizzle-neo-duckdb 1.2.0 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/duckdb-introspect.mjs +262 -73
- package/dist/index.mjs +254 -65
- package/dist/sql/ast-transformer.d.ts +16 -0
- package/dist/sql/visitors/column-qualifier.d.ts +5 -0
- package/package.json +2 -2
- package/src/sql/ast-transformer.ts +93 -17
- package/src/sql/visitors/column-qualifier.ts +373 -86
|
@@ -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,119 @@ 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
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
expr.left as Binary
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
transformed
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
184
|
+
transformed =
|
|
185
|
+
walkOnClause(
|
|
186
|
+
isBinaryExpr(expr.left as Binary)
|
|
187
|
+
? (expr.left as Binary)
|
|
188
|
+
: (expr.left as ExpressionValue),
|
|
189
|
+
leftQualifier,
|
|
190
|
+
rightQualifier,
|
|
191
|
+
ambiguousColumns
|
|
192
|
+
) || transformed;
|
|
193
|
+
transformed =
|
|
194
|
+
walkOnClause(
|
|
195
|
+
isBinaryExpr(expr.right as Binary)
|
|
196
|
+
? (expr.right as Binary)
|
|
197
|
+
: (expr.right as ExpressionValue),
|
|
198
|
+
leftQualifier,
|
|
199
|
+
rightQualifier,
|
|
200
|
+
ambiguousColumns
|
|
201
|
+
) || transformed;
|
|
107
202
|
}
|
|
108
203
|
|
|
109
204
|
return transformed;
|
|
@@ -111,7 +206,7 @@ function walkOnClause(
|
|
|
111
206
|
|
|
112
207
|
function qualifyAmbiguousInExpression(
|
|
113
208
|
expr: ExpressionValue | null | undefined,
|
|
114
|
-
defaultQualifier:
|
|
209
|
+
defaultQualifier: Qualifier,
|
|
115
210
|
ambiguousColumns: Set<string>
|
|
116
211
|
): boolean {
|
|
117
212
|
if (!expr || typeof expr !== 'object') return false;
|
|
@@ -121,13 +216,13 @@ function qualifyAmbiguousInExpression(
|
|
|
121
216
|
if (isUnqualifiedColumnRef(expr)) {
|
|
122
217
|
const colName = getColumnName(expr);
|
|
123
218
|
if (colName && ambiguousColumns.has(colName)) {
|
|
124
|
-
expr
|
|
219
|
+
applyQualifier(expr, defaultQualifier);
|
|
125
220
|
transformed = true;
|
|
126
221
|
}
|
|
127
222
|
return transformed;
|
|
128
223
|
}
|
|
129
224
|
|
|
130
|
-
if (
|
|
225
|
+
if (isBinaryExpr(expr)) {
|
|
131
226
|
const binary = expr as Binary;
|
|
132
227
|
transformed =
|
|
133
228
|
qualifyAmbiguousInExpression(
|
|
@@ -169,79 +264,186 @@ function qualifyAmbiguousInExpression(
|
|
|
169
264
|
}
|
|
170
265
|
}
|
|
171
266
|
|
|
267
|
+
if ('over' in expr && expr.over && typeof expr.over === 'object') {
|
|
268
|
+
const over = expr.over as {
|
|
269
|
+
partition?: ExpressionValue[];
|
|
270
|
+
orderby?: ExpressionValue[];
|
|
271
|
+
};
|
|
272
|
+
if (Array.isArray(over.partition)) {
|
|
273
|
+
for (const part of over.partition) {
|
|
274
|
+
transformed =
|
|
275
|
+
qualifyAmbiguousInExpression(
|
|
276
|
+
part,
|
|
277
|
+
defaultQualifier,
|
|
278
|
+
ambiguousColumns
|
|
279
|
+
) || transformed;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
if (Array.isArray(over.orderby)) {
|
|
283
|
+
for (const order of over.orderby) {
|
|
284
|
+
transformed =
|
|
285
|
+
qualifyAmbiguousInExpression(
|
|
286
|
+
order,
|
|
287
|
+
defaultQualifier,
|
|
288
|
+
ambiguousColumns
|
|
289
|
+
) || transformed;
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
|
|
172
294
|
return transformed;
|
|
173
295
|
}
|
|
174
296
|
|
|
297
|
+
/**
|
|
298
|
+
* Quick check if an ON clause has any unqualified column references.
|
|
299
|
+
* Used for early exit optimization.
|
|
300
|
+
*/
|
|
301
|
+
function hasUnqualifiedColumns(expr: Binary | null | undefined): boolean {
|
|
302
|
+
if (!expr || typeof expr !== 'object') return false;
|
|
303
|
+
|
|
304
|
+
if ('type' in expr && expr.type === 'binary_expr') {
|
|
305
|
+
const left = expr.left as ExpressionValue;
|
|
306
|
+
const right = expr.right as ExpressionValue;
|
|
307
|
+
const leftCol = unwrapColumnRef(left);
|
|
308
|
+
const rightCol = unwrapColumnRef(right);
|
|
309
|
+
if (
|
|
310
|
+
isUnqualifiedColumnRef(left) ||
|
|
311
|
+
isUnqualifiedColumnRef(right) ||
|
|
312
|
+
(leftCol && isUnqualifiedColumnRef(leftCol)) ||
|
|
313
|
+
(rightCol && isUnqualifiedColumnRef(rightCol))
|
|
314
|
+
) {
|
|
315
|
+
return true;
|
|
316
|
+
}
|
|
317
|
+
if (
|
|
318
|
+
isBinaryExpr(expr.left as Binary) &&
|
|
319
|
+
hasUnqualifiedColumns(expr.left as Binary)
|
|
320
|
+
)
|
|
321
|
+
return true;
|
|
322
|
+
if (
|
|
323
|
+
isBinaryExpr(expr.right as Binary) &&
|
|
324
|
+
hasUnqualifiedColumns(expr.right as Binary)
|
|
325
|
+
)
|
|
326
|
+
return true;
|
|
327
|
+
}
|
|
328
|
+
|
|
329
|
+
if ('args' in expr && expr.args) {
|
|
330
|
+
const args = expr.args as {
|
|
331
|
+
value?: ExpressionValue[];
|
|
332
|
+
expr?: ExpressionValue;
|
|
333
|
+
};
|
|
334
|
+
if (args.expr && isUnqualifiedColumnRef(args.expr as ExpressionValue))
|
|
335
|
+
return true;
|
|
336
|
+
if (args.value) {
|
|
337
|
+
for (const arg of args.value) {
|
|
338
|
+
if (isUnqualifiedColumnRef(arg)) return true;
|
|
339
|
+
}
|
|
340
|
+
}
|
|
341
|
+
}
|
|
342
|
+
|
|
343
|
+
return false;
|
|
344
|
+
}
|
|
345
|
+
|
|
175
346
|
function walkSelect(select: Select): boolean {
|
|
176
347
|
let transformed = false;
|
|
177
348
|
const ambiguousColumns = new Set<string>();
|
|
178
349
|
|
|
179
350
|
if (Array.isArray(select.from) && select.from.length >= 2) {
|
|
180
351
|
const firstSource = getTableSource(select.from[0]);
|
|
181
|
-
const defaultQualifier = firstSource ? getQualifier(firstSource) :
|
|
352
|
+
const defaultQualifier = firstSource ? getQualifier(firstSource) : null;
|
|
182
353
|
let prevSource = firstSource;
|
|
183
354
|
|
|
355
|
+
let hasAnyUnqualified = false;
|
|
184
356
|
for (const from of select.from) {
|
|
185
357
|
if ('join' in from) {
|
|
186
358
|
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;
|
|
359
|
+
if (join.on && hasUnqualifiedColumns(join.on)) {
|
|
360
|
+
hasAnyUnqualified = true;
|
|
361
|
+
break;
|
|
200
362
|
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
201
365
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
prevSource = source;
|
|
366
|
+
if (!hasAnyUnqualified) {
|
|
367
|
+
for (const from of select.from) {
|
|
368
|
+
if ('expr' in from && from.expr && 'ast' in from.expr) {
|
|
369
|
+
transformed = walkSelect(from.expr.ast) || transformed;
|
|
207
370
|
}
|
|
208
371
|
}
|
|
372
|
+
} else {
|
|
373
|
+
for (const from of select.from) {
|
|
374
|
+
if ('join' in from) {
|
|
375
|
+
const join = from as Join;
|
|
376
|
+
const currentSource = getTableSource(join);
|
|
209
377
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
}
|
|
378
|
+
if (join.on && prevSource && currentSource) {
|
|
379
|
+
const leftQualifier = getQualifier(prevSource);
|
|
380
|
+
const rightQualifier = getQualifier(currentSource);
|
|
214
381
|
|
|
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
382
|
transformed =
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
383
|
+
walkOnClause(
|
|
384
|
+
join.on,
|
|
385
|
+
leftQualifier,
|
|
386
|
+
rightQualifier,
|
|
223
387
|
ambiguousColumns
|
|
224
388
|
) || transformed;
|
|
225
389
|
}
|
|
390
|
+
|
|
391
|
+
if (join.using && prevSource && currentSource) {
|
|
392
|
+
for (const usingCol of join.using) {
|
|
393
|
+
if (typeof usingCol === 'string') {
|
|
394
|
+
ambiguousColumns.add(usingCol);
|
|
395
|
+
} else if ('value' in usingCol) {
|
|
396
|
+
ambiguousColumns.add(
|
|
397
|
+
String((usingCol as { value: unknown }).value)
|
|
398
|
+
);
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
|
|
403
|
+
prevSource = currentSource;
|
|
404
|
+
} else {
|
|
405
|
+
const source = getTableSource(from);
|
|
406
|
+
if (source) {
|
|
407
|
+
prevSource = source;
|
|
408
|
+
}
|
|
409
|
+
}
|
|
410
|
+
|
|
411
|
+
if ('expr' in from && from.expr && 'ast' in from.expr) {
|
|
412
|
+
transformed = walkSelect(from.expr.ast) || transformed;
|
|
226
413
|
}
|
|
227
414
|
}
|
|
228
415
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
select.
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
416
|
+
if (ambiguousColumns.size > 0 && defaultQualifier) {
|
|
417
|
+
if (Array.isArray(select.columns)) {
|
|
418
|
+
for (const col of select.columns as Column[]) {
|
|
419
|
+
if ('expr' in col) {
|
|
420
|
+
transformed =
|
|
421
|
+
qualifyAmbiguousInExpression(
|
|
422
|
+
col.expr,
|
|
423
|
+
defaultQualifier,
|
|
424
|
+
ambiguousColumns
|
|
425
|
+
) || transformed;
|
|
426
|
+
}
|
|
427
|
+
}
|
|
428
|
+
}
|
|
235
429
|
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
430
|
+
transformed =
|
|
431
|
+
qualifyAmbiguousInExpression(
|
|
432
|
+
select.where,
|
|
433
|
+
defaultQualifier,
|
|
434
|
+
ambiguousColumns
|
|
435
|
+
) || transformed;
|
|
436
|
+
|
|
437
|
+
if (Array.isArray(select.orderby)) {
|
|
438
|
+
for (const order of select.orderby as OrderBy[]) {
|
|
439
|
+
if (order.expr) {
|
|
440
|
+
transformed =
|
|
441
|
+
qualifyAmbiguousInExpression(
|
|
442
|
+
order.expr,
|
|
443
|
+
defaultQualifier,
|
|
444
|
+
ambiguousColumns
|
|
445
|
+
) || transformed;
|
|
446
|
+
}
|
|
245
447
|
}
|
|
246
448
|
}
|
|
247
449
|
}
|
|
@@ -271,6 +473,91 @@ export function qualifyJoinColumns(ast: AST | AST[]): boolean {
|
|
|
271
473
|
for (const stmt of statements) {
|
|
272
474
|
if (stmt.type === 'select') {
|
|
273
475
|
transformed = walkSelect(stmt as Select) || transformed;
|
|
476
|
+
} else if (stmt.type === 'insert') {
|
|
477
|
+
const insert = stmt as unknown as { values?: unknown };
|
|
478
|
+
if (
|
|
479
|
+
insert.values &&
|
|
480
|
+
typeof insert.values === 'object' &&
|
|
481
|
+
'type' in insert.values &&
|
|
482
|
+
(insert.values as { type: string }).type === 'select'
|
|
483
|
+
) {
|
|
484
|
+
transformed =
|
|
485
|
+
walkSelect(insert.values as unknown as Select) || transformed;
|
|
486
|
+
}
|
|
487
|
+
} else if (stmt.type === 'update') {
|
|
488
|
+
const update = stmt as unknown as {
|
|
489
|
+
table?: From[];
|
|
490
|
+
from?: From[];
|
|
491
|
+
where?: ExpressionValue;
|
|
492
|
+
returning?: ExpressionValue | ExpressionValue[];
|
|
493
|
+
};
|
|
494
|
+
const mainSource = update.table?.[0]
|
|
495
|
+
? getTableSource(update.table[0] as From)
|
|
496
|
+
: null;
|
|
497
|
+
const defaultQualifier = mainSource ? getQualifier(mainSource) : null;
|
|
498
|
+
const fromSources = update.from ?? [];
|
|
499
|
+
const firstFrom = fromSources[0] ? getTableSource(fromSources[0]) : null;
|
|
500
|
+
if (update.where && defaultQualifier && firstFrom) {
|
|
501
|
+
const ambiguous = new Set<string>();
|
|
502
|
+
transformed =
|
|
503
|
+
walkOnClause(
|
|
504
|
+
update.where as Binary,
|
|
505
|
+
defaultQualifier,
|
|
506
|
+
getQualifier(firstFrom),
|
|
507
|
+
ambiguous
|
|
508
|
+
) || transformed;
|
|
509
|
+
transformed =
|
|
510
|
+
qualifyAmbiguousInExpression(
|
|
511
|
+
update.where,
|
|
512
|
+
defaultQualifier,
|
|
513
|
+
ambiguous
|
|
514
|
+
) || transformed;
|
|
515
|
+
}
|
|
516
|
+
if (Array.isArray(update.returning) && defaultQualifier) {
|
|
517
|
+
for (const ret of update.returning) {
|
|
518
|
+
transformed =
|
|
519
|
+
qualifyAmbiguousInExpression(
|
|
520
|
+
ret,
|
|
521
|
+
defaultQualifier,
|
|
522
|
+
new Set<string>()
|
|
523
|
+
) || transformed;
|
|
524
|
+
}
|
|
525
|
+
}
|
|
526
|
+
} else if (stmt.type === 'delete') {
|
|
527
|
+
const del = stmt as unknown as {
|
|
528
|
+
table?: From[];
|
|
529
|
+
from?: From[];
|
|
530
|
+
where?: ExpressionValue;
|
|
531
|
+
};
|
|
532
|
+
const mainSource = del.table?.[0]
|
|
533
|
+
? getTableSource(del.table[0] as From)
|
|
534
|
+
: null;
|
|
535
|
+
const defaultQualifier = mainSource ? getQualifier(mainSource) : null;
|
|
536
|
+
const fromSources = del.from ?? [];
|
|
537
|
+
const firstFrom = fromSources[0] ? getTableSource(fromSources[0]) : null;
|
|
538
|
+
if (del.where && defaultQualifier && firstFrom) {
|
|
539
|
+
const ambiguous = new Set<string>();
|
|
540
|
+
transformed =
|
|
541
|
+
walkOnClause(
|
|
542
|
+
del.where as Binary,
|
|
543
|
+
defaultQualifier,
|
|
544
|
+
getQualifier(firstFrom),
|
|
545
|
+
ambiguous
|
|
546
|
+
) || transformed;
|
|
547
|
+
transformed =
|
|
548
|
+
qualifyAmbiguousInExpression(
|
|
549
|
+
del.where,
|
|
550
|
+
defaultQualifier,
|
|
551
|
+
ambiguous
|
|
552
|
+
) || transformed;
|
|
553
|
+
} else if (del.where && defaultQualifier) {
|
|
554
|
+
transformed =
|
|
555
|
+
qualifyAmbiguousInExpression(
|
|
556
|
+
del.where,
|
|
557
|
+
defaultQualifier,
|
|
558
|
+
new Set<string>()
|
|
559
|
+
) || transformed;
|
|
560
|
+
}
|
|
274
561
|
}
|
|
275
562
|
}
|
|
276
563
|
|