@leonardovida-md/drizzle-neo-duckdb 1.1.3 → 1.2.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.
package/dist/index.mjs CHANGED
@@ -15,489 +15,6 @@ import { PgTransaction } from "drizzle-orm/pg-core";
15
15
  import { PgPreparedQuery, PgSession } from "drizzle-orm/pg-core/session";
16
16
  import { fillPlaceholders, sql } from "drizzle-orm/sql/sql";
17
17
 
18
- // src/sql/query-rewriters.ts
19
- var OPERATORS = [
20
- { token: "@>", fn: "array_has_all" },
21
- { token: "<@", fn: "array_has_all", swap: true },
22
- { token: "&&", fn: "array_has_any" }
23
- ];
24
- var isWhitespace = (char) => char !== undefined && /\s/.test(char);
25
- function scrubForRewrite(query) {
26
- let scrubbed = "";
27
- let state = "code";
28
- for (let i = 0;i < query.length; i += 1) {
29
- const char = query[i];
30
- const next = query[i + 1];
31
- if (state === "code") {
32
- if (char === "'") {
33
- scrubbed += "'";
34
- state = "single";
35
- continue;
36
- }
37
- if (char === '"') {
38
- scrubbed += '"';
39
- state = "double";
40
- continue;
41
- }
42
- if (char === "-" && next === "-") {
43
- scrubbed += " ";
44
- i += 1;
45
- state = "lineComment";
46
- continue;
47
- }
48
- if (char === "/" && next === "*") {
49
- scrubbed += " ";
50
- i += 1;
51
- state = "blockComment";
52
- continue;
53
- }
54
- scrubbed += char;
55
- continue;
56
- }
57
- if (state === "single") {
58
- if (char === "'" && next === "'") {
59
- scrubbed += "''";
60
- i += 1;
61
- continue;
62
- }
63
- scrubbed += char === "'" ? "'" : ".";
64
- if (char === "'") {
65
- state = "code";
66
- }
67
- continue;
68
- }
69
- if (state === "double") {
70
- if (char === '"' && next === '"') {
71
- scrubbed += '""';
72
- i += 1;
73
- continue;
74
- }
75
- scrubbed += char === '"' ? '"' : ".";
76
- if (char === '"') {
77
- state = "code";
78
- }
79
- continue;
80
- }
81
- if (state === "lineComment") {
82
- scrubbed += char === `
83
- ` ? `
84
- ` : " ";
85
- if (char === `
86
- `) {
87
- state = "code";
88
- }
89
- continue;
90
- }
91
- if (state === "blockComment") {
92
- if (char === "*" && next === "/") {
93
- scrubbed += " ";
94
- i += 1;
95
- state = "code";
96
- } else {
97
- scrubbed += " ";
98
- }
99
- }
100
- }
101
- return scrubbed;
102
- }
103
- function findNextOperator(scrubbed, start) {
104
- for (let idx = start;idx < scrubbed.length; idx += 1) {
105
- for (const operator of OPERATORS) {
106
- if (scrubbed.startsWith(operator.token, idx)) {
107
- return { index: idx, operator };
108
- }
109
- }
110
- }
111
- return null;
112
- }
113
- function walkLeft(source, scrubbed, start) {
114
- let idx = start;
115
- while (idx >= 0 && isWhitespace(scrubbed[idx])) {
116
- idx -= 1;
117
- }
118
- let depth = 0;
119
- for (;idx >= 0; idx -= 1) {
120
- const ch = scrubbed[idx];
121
- if (ch === ")" || ch === "]") {
122
- depth += 1;
123
- } else if (ch === "(" || ch === "[") {
124
- if (depth === 0) {
125
- return [idx + 1, source.slice(idx + 1, start + 1)];
126
- }
127
- depth = Math.max(0, depth - 1);
128
- } else if (depth === 0 && isWhitespace(ch)) {
129
- return [idx + 1, source.slice(idx + 1, start + 1)];
130
- }
131
- }
132
- return [0, source.slice(0, start + 1)];
133
- }
134
- function walkRight(source, scrubbed, start) {
135
- let idx = start;
136
- while (idx < scrubbed.length && isWhitespace(scrubbed[idx])) {
137
- idx += 1;
138
- }
139
- let depth = 0;
140
- for (;idx < scrubbed.length; idx += 1) {
141
- const ch = scrubbed[idx];
142
- if (ch === "(" || ch === "[") {
143
- depth += 1;
144
- } else if (ch === ")" || ch === "]") {
145
- if (depth === 0) {
146
- return [idx, source.slice(start, idx)];
147
- }
148
- depth = Math.max(0, depth - 1);
149
- } else if (depth === 0 && isWhitespace(ch)) {
150
- return [idx, source.slice(start, idx)];
151
- }
152
- }
153
- return [scrubbed.length, source.slice(start)];
154
- }
155
- function adaptArrayOperators(query) {
156
- if (query.indexOf("@>") === -1 && query.indexOf("<@") === -1 && query.indexOf("&&") === -1) {
157
- return query;
158
- }
159
- let rewritten = query;
160
- let scrubbed = scrubForRewrite(query);
161
- let searchStart = 0;
162
- while (true) {
163
- const next = findNextOperator(scrubbed, searchStart);
164
- if (!next)
165
- break;
166
- const { index, operator } = next;
167
- const [leftStart, leftExpr] = walkLeft(rewritten, scrubbed, index - 1);
168
- const [rightEnd, rightExpr] = walkRight(rewritten, scrubbed, index + operator.token.length);
169
- const left = leftExpr.trim();
170
- const right = rightExpr.trim();
171
- const replacement = `${operator.fn}(${operator.swap ? right : left}, ${operator.swap ? left : right})`;
172
- rewritten = rewritten.slice(0, leftStart) + replacement + rewritten.slice(rightEnd);
173
- scrubbed = scrubForRewrite(rewritten);
174
- searchStart = leftStart + replacement.length;
175
- }
176
- return rewritten;
177
- }
178
- function extractQuotedIdentifier(original, start) {
179
- if (original[start] !== '"') {
180
- return null;
181
- }
182
- let pos = start + 1;
183
- while (pos < original.length && original[pos] !== '"') {
184
- if (original[pos] === '"' && original[pos + 1] === '"') {
185
- pos += 2;
186
- continue;
187
- }
188
- pos++;
189
- }
190
- if (pos >= original.length) {
191
- return null;
192
- }
193
- return {
194
- name: original.slice(start + 1, pos),
195
- end: pos + 1
196
- };
197
- }
198
- function findMainFromClause(scrubbed) {
199
- const lowerScrubbed = scrubbed.toLowerCase();
200
- let searchStart = 0;
201
- const withMatch = /\bwith\s+/i.exec(lowerScrubbed);
202
- if (withMatch) {
203
- let depth = 0;
204
- let pos = withMatch.index + withMatch[0].length;
205
- while (pos < scrubbed.length) {
206
- const char = scrubbed[pos];
207
- if (char === "(") {
208
- depth++;
209
- } else if (char === ")") {
210
- depth--;
211
- } else if (depth === 0) {
212
- const remaining = lowerScrubbed.slice(pos);
213
- if (/^\s*select\s+/i.test(remaining)) {
214
- searchStart = pos;
215
- break;
216
- }
217
- }
218
- pos++;
219
- }
220
- }
221
- const fromPattern = /\bfrom\s+/gi;
222
- fromPattern.lastIndex = searchStart;
223
- const fromMatch = fromPattern.exec(lowerScrubbed);
224
- return fromMatch ? fromMatch.index + fromMatch[0].length : -1;
225
- }
226
- function parseTableSources(original, scrubbed) {
227
- const sources = [];
228
- const lowerScrubbed = scrubbed.toLowerCase();
229
- const fromPos = findMainFromClause(scrubbed);
230
- if (fromPos < 0) {
231
- return sources;
232
- }
233
- const fromTable = parseTableRef(original, scrubbed, fromPos);
234
- if (fromTable) {
235
- sources.push(fromTable);
236
- }
237
- const joinPattern = /\b(left\s+|right\s+|inner\s+|full\s+|cross\s+)?join\s+/gi;
238
- joinPattern.lastIndex = fromPos;
239
- let joinMatch;
240
- while ((joinMatch = joinPattern.exec(lowerScrubbed)) !== null) {
241
- const tableStart = joinMatch.index + joinMatch[0].length;
242
- const joinTable = parseTableRef(original, scrubbed, tableStart);
243
- if (joinTable) {
244
- sources.push(joinTable);
245
- }
246
- }
247
- return sources;
248
- }
249
- function parseTableRef(original, scrubbed, start) {
250
- let pos = start;
251
- while (pos < scrubbed.length && isWhitespace(scrubbed[pos])) {
252
- pos++;
253
- }
254
- if (original[pos] !== '"') {
255
- return null;
256
- }
257
- const nameStart = pos;
258
- const firstIdent = extractQuotedIdentifier(original, pos);
259
- if (!firstIdent) {
260
- return null;
261
- }
262
- let name = firstIdent.name;
263
- pos = firstIdent.end;
264
- let afterName = pos;
265
- while (afterName < scrubbed.length && isWhitespace(scrubbed[afterName])) {
266
- afterName++;
267
- }
268
- if (scrubbed[afterName] === ".") {
269
- afterName++;
270
- while (afterName < scrubbed.length && isWhitespace(scrubbed[afterName])) {
271
- afterName++;
272
- }
273
- if (original[afterName] === '"') {
274
- const tableIdent = extractQuotedIdentifier(original, afterName);
275
- if (tableIdent) {
276
- name = tableIdent.name;
277
- pos = tableIdent.end;
278
- }
279
- }
280
- }
281
- let alias;
282
- let aliasPos = pos;
283
- while (aliasPos < scrubbed.length && isWhitespace(scrubbed[aliasPos])) {
284
- aliasPos++;
285
- }
286
- const afterTable = scrubbed.slice(aliasPos).toLowerCase();
287
- if (afterTable.startsWith("as ")) {
288
- aliasPos += 3;
289
- while (aliasPos < scrubbed.length && isWhitespace(scrubbed[aliasPos])) {
290
- aliasPos++;
291
- }
292
- }
293
- if (original[aliasPos] === '"' && !afterTable.startsWith("on ") && !afterTable.startsWith("left ") && !afterTable.startsWith("right ") && !afterTable.startsWith("inner ") && !afterTable.startsWith("full ") && !afterTable.startsWith("cross ") && !afterTable.startsWith("join ") && !afterTable.startsWith("where ") && !afterTable.startsWith("group ") && !afterTable.startsWith("order ") && !afterTable.startsWith("limit ") && !afterTable.startsWith("as ")) {
294
- const aliasIdent = extractQuotedIdentifier(original, aliasPos);
295
- if (aliasIdent) {
296
- alias = aliasIdent.name;
297
- }
298
- }
299
- return {
300
- name,
301
- alias,
302
- position: nameStart
303
- };
304
- }
305
- function findJoinClauses(original, scrubbed, sources) {
306
- const clauses = [];
307
- const lowerScrubbed = scrubbed.toLowerCase();
308
- const joinPattern = /\b(left\s+|right\s+|inner\s+|full\s+|cross\s+)?join\s+"[^"]*"(\s*\.\s*"[^"]*")?(\s+as)?(\s+"[^"]*")?\s+on\s+/gi;
309
- let match;
310
- let sourceIndex = 1;
311
- while ((match = joinPattern.exec(lowerScrubbed)) !== null) {
312
- const joinType = (match[1] || "").trim().toLowerCase();
313
- const joinKeywordEnd = match.index + (match[1] || "").length + "join".length;
314
- let tableStart = joinKeywordEnd;
315
- while (tableStart < original.length && isWhitespace(original[tableStart])) {
316
- tableStart++;
317
- }
318
- const tableIdent = extractQuotedIdentifier(original, tableStart);
319
- if (!tableIdent)
320
- continue;
321
- let tableName = tableIdent.name;
322
- let afterTable = tableIdent.end;
323
- let checkPos = afterTable;
324
- while (checkPos < scrubbed.length && isWhitespace(scrubbed[checkPos])) {
325
- checkPos++;
326
- }
327
- if (scrubbed[checkPos] === ".") {
328
- checkPos++;
329
- while (checkPos < scrubbed.length && isWhitespace(scrubbed[checkPos])) {
330
- checkPos++;
331
- }
332
- const realTableIdent = extractQuotedIdentifier(original, checkPos);
333
- if (realTableIdent) {
334
- tableName = realTableIdent.name;
335
- afterTable = realTableIdent.end;
336
- }
337
- }
338
- let tableAlias;
339
- let aliasPos = afterTable;
340
- while (aliasPos < scrubbed.length && isWhitespace(scrubbed[aliasPos])) {
341
- aliasPos++;
342
- }
343
- const afterTableStr = scrubbed.slice(aliasPos).toLowerCase();
344
- if (afterTableStr.startsWith("as ")) {
345
- aliasPos += 3;
346
- while (aliasPos < scrubbed.length && isWhitespace(scrubbed[aliasPos])) {
347
- aliasPos++;
348
- }
349
- }
350
- if (original[aliasPos] === '"' && !afterTableStr.startsWith("on ")) {
351
- const aliasIdent = extractQuotedIdentifier(original, aliasPos);
352
- if (aliasIdent) {
353
- tableAlias = aliasIdent.name;
354
- }
355
- }
356
- const onStart = match.index + match[0].length;
357
- const endPattern = /\b(left\s+join|right\s+join|inner\s+join|full\s+join|cross\s+join|join|where|group\s+by|order\s+by|limit|$)/i;
358
- const remaining = lowerScrubbed.slice(onStart);
359
- const endMatch = endPattern.exec(remaining);
360
- const onEnd = endMatch ? onStart + endMatch.index : scrubbed.length;
361
- let leftSource = "";
362
- if (sourceIndex > 0 && sourceIndex <= sources.length) {
363
- const prev = sources[sourceIndex - 1];
364
- leftSource = prev?.alias || prev?.name || "";
365
- }
366
- const rightSource = tableAlias || tableName;
367
- clauses.push({
368
- joinType,
369
- tableName,
370
- tableAlias,
371
- onStart,
372
- onEnd,
373
- leftSource,
374
- rightSource
375
- });
376
- sourceIndex++;
377
- }
378
- return clauses;
379
- }
380
- function qualifyJoinColumns(query) {
381
- const lowerQuery = query.toLowerCase();
382
- if (!lowerQuery.includes("join")) {
383
- return query;
384
- }
385
- const scrubbed = scrubForRewrite(query);
386
- const sources = parseTableSources(query, scrubbed);
387
- if (sources.length < 2) {
388
- return query;
389
- }
390
- const joinClauses = findJoinClauses(query, scrubbed, sources);
391
- if (joinClauses.length === 0) {
392
- return query;
393
- }
394
- let result = query;
395
- let offset = 0;
396
- for (const join of joinClauses) {
397
- const scrubbedOnClause = scrubbed.slice(join.onStart, join.onEnd);
398
- const originalOnClause = query.slice(join.onStart, join.onEnd);
399
- let clauseResult = originalOnClause;
400
- let clauseOffset = 0;
401
- let eqPos = -1;
402
- while ((eqPos = scrubbedOnClause.indexOf("=", eqPos + 1)) !== -1) {
403
- let lhsEnd = eqPos - 1;
404
- while (lhsEnd >= 0 && isWhitespace(scrubbedOnClause[lhsEnd])) {
405
- lhsEnd--;
406
- }
407
- if (scrubbedOnClause[lhsEnd] !== '"')
408
- continue;
409
- let lhsStartPos = lhsEnd - 1;
410
- while (lhsStartPos >= 0 && scrubbedOnClause[lhsStartPos] !== '"') {
411
- lhsStartPos--;
412
- }
413
- if (lhsStartPos < 0)
414
- continue;
415
- const lhsIsQualified = lhsStartPos > 0 && scrubbedOnClause[lhsStartPos - 1] === ".";
416
- let rhsStartPos = eqPos + 1;
417
- while (rhsStartPos < scrubbedOnClause.length && isWhitespace(scrubbedOnClause[rhsStartPos])) {
418
- rhsStartPos++;
419
- }
420
- const rhsChar = originalOnClause[rhsStartPos];
421
- const rhsIsParam = rhsChar === "$";
422
- const rhsIsStringLiteral = rhsChar === "'";
423
- const rhsIsColumn = rhsChar === '"';
424
- if (!rhsIsParam && !rhsIsStringLiteral && !rhsIsColumn)
425
- continue;
426
- const rhsIsQualified = !rhsIsColumn || rhsStartPos > 0 && scrubbedOnClause[rhsStartPos - 1] === ".";
427
- if (lhsIsQualified || rhsIsQualified)
428
- continue;
429
- const lhsIdent = extractQuotedIdentifier(originalOnClause, lhsStartPos);
430
- if (!lhsIdent)
431
- continue;
432
- let rhsIdent = null;
433
- let rhsValue = "";
434
- let rhsEnd = rhsStartPos;
435
- if (rhsIsParam) {
436
- let paramEnd = rhsStartPos + 1;
437
- while (paramEnd < originalOnClause.length && /\d/.test(originalOnClause[paramEnd])) {
438
- paramEnd++;
439
- }
440
- rhsValue = originalOnClause.slice(rhsStartPos, paramEnd);
441
- rhsEnd = paramEnd;
442
- } else if (rhsIsStringLiteral) {
443
- let literalEnd = rhsStartPos + 1;
444
- while (literalEnd < originalOnClause.length) {
445
- if (originalOnClause[literalEnd] === "'") {
446
- if (originalOnClause[literalEnd + 1] === "'") {
447
- literalEnd += 2;
448
- continue;
449
- }
450
- break;
451
- }
452
- literalEnd++;
453
- }
454
- rhsValue = originalOnClause.slice(rhsStartPos, literalEnd + 1);
455
- rhsEnd = literalEnd + 1;
456
- } else if (rhsIsColumn) {
457
- rhsIdent = extractQuotedIdentifier(originalOnClause, rhsStartPos);
458
- if (rhsIdent) {
459
- if (rhsIdent.end < scrubbedOnClause.length && scrubbedOnClause[rhsIdent.end] === ".") {
460
- continue;
461
- }
462
- rhsValue = `"${rhsIdent.name}"`;
463
- rhsEnd = rhsIdent.end;
464
- }
465
- }
466
- if (!rhsValue)
467
- continue;
468
- if (!rhsIsColumn || !rhsIdent || lhsIdent.name !== rhsIdent.name) {
469
- continue;
470
- }
471
- const lhsOriginal = `"${lhsIdent.name}"`;
472
- let newLhs = lhsOriginal;
473
- let newRhs = rhsValue;
474
- if (!lhsIsQualified && join.leftSource) {
475
- newLhs = `"${join.leftSource}"."${lhsIdent.name}"`;
476
- }
477
- if (!rhsIsQualified && rhsIsColumn && rhsIdent && join.rightSource) {
478
- newRhs = `"${join.rightSource}"."${rhsIdent.name}"`;
479
- }
480
- if (newLhs !== lhsOriginal || newRhs !== rhsValue) {
481
- const opStart = lhsIdent.end;
482
- let opEnd = opStart;
483
- while (opEnd < rhsEnd && (isWhitespace(originalOnClause[opEnd]) || originalOnClause[opEnd] === "=")) {
484
- opEnd++;
485
- }
486
- const operator = originalOnClause.slice(opStart, opEnd);
487
- const newExpr = `${newLhs}${operator}${newRhs}`;
488
- const oldExprLength = rhsEnd - lhsStartPos;
489
- clauseResult = clauseResult.slice(0, lhsStartPos + clauseOffset) + newExpr + clauseResult.slice(lhsStartPos + oldExprLength + clauseOffset);
490
- clauseOffset += newExpr.length - oldExprLength;
491
- }
492
- }
493
- if (clauseResult !== originalOnClause) {
494
- result = result.slice(0, join.onStart + offset) + clauseResult + result.slice(join.onEnd + offset);
495
- offset += clauseResult.length - originalOnClause.length;
496
- }
497
- }
498
- return result;
499
- }
500
-
501
18
  // src/sql/result-mapper.ts
502
19
  import {
503
20
  Column,
@@ -1133,24 +650,6 @@ function isSavepointSyntaxError(error) {
1133
650
  }
1134
651
  return error.message.toLowerCase().includes("savepoint") && error.message.toLowerCase().includes("syntax error");
1135
652
  }
1136
- function rewriteQuery(mode, query) {
1137
- if (mode === "never") {
1138
- return { sql: query, rewritten: false };
1139
- }
1140
- let result = query;
1141
- let wasRewritten = false;
1142
- const arrayRewritten = adaptArrayOperators(result);
1143
- if (arrayRewritten !== result) {
1144
- result = arrayRewritten;
1145
- wasRewritten = true;
1146
- }
1147
- const joinQualified = qualifyJoinColumns(result);
1148
- if (joinQualified !== result) {
1149
- result = joinQualified;
1150
- wasRewritten = true;
1151
- }
1152
- return { sql: result, rewritten: wasRewritten };
1153
- }
1154
653
 
1155
654
  class DuckDBPreparedQuery extends PgPreparedQuery {
1156
655
  client;
@@ -1161,12 +660,11 @@ class DuckDBPreparedQuery extends PgPreparedQuery {
1161
660
  fields;
1162
661
  _isResponseInArrayMode;
1163
662
  customResultMapper;
1164
- rewriteArraysMode;
1165
663
  rejectStringArrayLiterals;
1166
664
  prepareCache;
1167
665
  warnOnStringArrayLiteral;
1168
666
  static [entityKind] = "DuckDBPreparedQuery";
1169
- constructor(client, dialect, queryString, params, logger, fields, _isResponseInArrayMode, customResultMapper, rewriteArraysMode, rejectStringArrayLiterals, prepareCache, warnOnStringArrayLiteral) {
667
+ constructor(client, dialect, queryString, params, logger, fields, _isResponseInArrayMode, customResultMapper, rejectStringArrayLiterals, prepareCache, warnOnStringArrayLiteral) {
1170
668
  super({ sql: queryString, params });
1171
669
  this.client = client;
1172
670
  this.dialect = dialect;
@@ -1176,7 +674,6 @@ class DuckDBPreparedQuery extends PgPreparedQuery {
1176
674
  this.fields = fields;
1177
675
  this._isResponseInArrayMode = _isResponseInArrayMode;
1178
676
  this.customResultMapper = customResultMapper;
1179
- this.rewriteArraysMode = rewriteArraysMode;
1180
677
  this.rejectStringArrayLiterals = rejectStringArrayLiterals;
1181
678
  this.prepareCache = prepareCache;
1182
679
  this.warnOnStringArrayLiteral = warnOnStringArrayLiteral;
@@ -1187,20 +684,16 @@ class DuckDBPreparedQuery extends PgPreparedQuery {
1187
684
  rejectStringArrayLiterals: this.rejectStringArrayLiterals,
1188
685
  warnOnStringArrayLiteral: this.warnOnStringArrayLiteral ? () => this.warnOnStringArrayLiteral?.(this.queryString) : undefined
1189
686
  });
1190
- const { sql: rewrittenQuery, rewritten: didRewrite } = rewriteQuery(this.rewriteArraysMode, this.queryString);
1191
- if (didRewrite) {
1192
- this.logger.logQuery(`[duckdb] original query before array rewrite: ${this.queryString}`, params);
1193
- }
1194
- this.logger.logQuery(rewrittenQuery, params);
687
+ this.logger.logQuery(this.queryString, params);
1195
688
  const { fields, joinsNotNullableMap, customResultMapper } = this;
1196
689
  if (fields) {
1197
- const { rows: rows2 } = await executeArraysOnClient(this.client, rewrittenQuery, params, { prepareCache: this.prepareCache });
690
+ const { rows: rows2 } = await executeArraysOnClient(this.client, this.queryString, params, { prepareCache: this.prepareCache });
1198
691
  if (rows2.length === 0) {
1199
692
  return [];
1200
693
  }
1201
694
  return customResultMapper ? customResultMapper(rows2) : rows2.map((row) => mapResultRow(fields, row, joinsNotNullableMap));
1202
695
  }
1203
- const rows = await executeOnClient(this.client, rewrittenQuery, params, {
696
+ const rows = await executeOnClient(this.client, this.queryString, params, {
1204
697
  prepareCache: this.prepareCache
1205
698
  });
1206
699
  return rows;
@@ -1220,7 +713,6 @@ class DuckDBSession extends PgSession {
1220
713
  static [entityKind] = "DuckDBSession";
1221
714
  dialect;
1222
715
  logger;
1223
- rewriteArraysMode;
1224
716
  rejectStringArrayLiterals;
1225
717
  prepareCache;
1226
718
  hasWarnedArrayLiteral = false;
@@ -1232,17 +724,15 @@ class DuckDBSession extends PgSession {
1232
724
  this.options = options;
1233
725
  this.dialect = dialect;
1234
726
  this.logger = options.logger ?? new NoopLogger;
1235
- this.rewriteArraysMode = options.rewriteArrays ?? "auto";
1236
727
  this.rejectStringArrayLiterals = options.rejectStringArrayLiterals ?? false;
1237
728
  this.prepareCache = options.prepareCache;
1238
729
  this.options = {
1239
730
  ...options,
1240
- rewriteArrays: this.rewriteArraysMode,
1241
731
  prepareCache: this.prepareCache
1242
732
  };
1243
733
  }
1244
734
  prepareQuery(query, fields, name, isResponseInArrayMode, customResultMapper) {
1245
- return new DuckDBPreparedQuery(this.client, this.dialect, query.sql, query.params, this.logger, fields, isResponseInArrayMode, customResultMapper, this.rewriteArraysMode, this.rejectStringArrayLiterals, this.prepareCache, this.rejectStringArrayLiterals ? undefined : this.warnOnStringArrayLiteral);
735
+ return new DuckDBPreparedQuery(this.client, this.dialect, query.sql, query.params, this.logger, fields, isResponseInArrayMode, customResultMapper, this.rejectStringArrayLiterals, this.prepareCache, this.rejectStringArrayLiterals ? undefined : this.warnOnStringArrayLiteral);
1246
736
  }
1247
737
  execute(query) {
1248
738
  this.dialect.resetPgJsonFlag();
@@ -1302,12 +792,8 @@ query: ${query}`, []);
1302
792
  rejectStringArrayLiterals: this.rejectStringArrayLiterals,
1303
793
  warnOnStringArrayLiteral: this.rejectStringArrayLiterals ? undefined : () => this.warnOnStringArrayLiteral(builtQuery.sql)
1304
794
  });
1305
- const { sql: rewrittenQuery, rewritten: didRewrite } = rewriteQuery(this.rewriteArraysMode, builtQuery.sql);
1306
- if (didRewrite) {
1307
- this.logger.logQuery(`[duckdb] original query before array rewrite: ${builtQuery.sql}`, params);
1308
- }
1309
- this.logger.logQuery(rewrittenQuery, params);
1310
- return executeInBatches(this.client, rewrittenQuery, params, options);
795
+ this.logger.logQuery(builtQuery.sql, params);
796
+ return executeInBatches(this.client, builtQuery.sql, params, options);
1311
797
  }
1312
798
  executeBatchesRaw(query, options = {}) {
1313
799
  this.dialect.resetPgJsonFlag();
@@ -1317,12 +803,8 @@ query: ${query}`, []);
1317
803
  rejectStringArrayLiterals: this.rejectStringArrayLiterals,
1318
804
  warnOnStringArrayLiteral: this.rejectStringArrayLiterals ? undefined : () => this.warnOnStringArrayLiteral(builtQuery.sql)
1319
805
  });
1320
- const { sql: rewrittenQuery, rewritten: didRewrite } = rewriteQuery(this.rewriteArraysMode, builtQuery.sql);
1321
- if (didRewrite) {
1322
- this.logger.logQuery(`[duckdb] original query before array rewrite: ${builtQuery.sql}`, params);
1323
- }
1324
- this.logger.logQuery(rewrittenQuery, params);
1325
- return executeInBatchesRaw(this.client, rewrittenQuery, params, options);
806
+ this.logger.logQuery(builtQuery.sql, params);
807
+ return executeInBatchesRaw(this.client, builtQuery.sql, params, options);
1326
808
  }
1327
809
  async executeArrow(query) {
1328
810
  this.dialect.resetPgJsonFlag();
@@ -1332,12 +814,8 @@ query: ${query}`, []);
1332
814
  rejectStringArrayLiterals: this.rejectStringArrayLiterals,
1333
815
  warnOnStringArrayLiteral: this.rejectStringArrayLiterals ? undefined : () => this.warnOnStringArrayLiteral(builtQuery.sql)
1334
816
  });
1335
- const { sql: rewrittenQuery, rewritten: didRewrite } = rewriteQuery(this.rewriteArraysMode, builtQuery.sql);
1336
- if (didRewrite) {
1337
- this.logger.logQuery(`[duckdb] original query before array rewrite: ${builtQuery.sql}`, params);
1338
- }
1339
- this.logger.logQuery(rewrittenQuery, params);
1340
- return executeArrowOnClient(this.client, rewrittenQuery, params);
817
+ this.logger.logQuery(builtQuery.sql, params);
818
+ return executeArrowOnClient(this.client, builtQuery.sql, params);
1341
819
  }
1342
820
  markRollbackOnly() {
1343
821
  this.rollbackOnly = true;
@@ -1439,6 +917,335 @@ import {
1439
917
  import {
1440
918
  sql as sql2
1441
919
  } from "drizzle-orm";
920
+
921
+ // src/sql/ast-transformer.ts
922
+ import nodeSqlParser from "node-sql-parser";
923
+
924
+ // src/sql/visitors/array-operators.ts
925
+ var OPERATOR_MAP = {
926
+ "@>": { fn: "array_has_all" },
927
+ "<@": { fn: "array_has_all", swap: true },
928
+ "&&": { fn: "array_has_any" }
929
+ };
930
+ function walkExpression(expr, parent, key) {
931
+ if (!expr || typeof expr !== "object")
932
+ return false;
933
+ let transformed = false;
934
+ const exprObj = expr;
935
+ if ("type" in expr && exprObj.type === "binary_expr") {
936
+ const binary = expr;
937
+ const mapping = OPERATOR_MAP[binary.operator];
938
+ if (mapping) {
939
+ const fnExpr = {
940
+ type: "function",
941
+ name: { name: [{ type: "default", value: mapping.fn }] },
942
+ args: {
943
+ type: "expr_list",
944
+ value: mapping.swap ? [binary.right, binary.left] : [binary.left, binary.right]
945
+ }
946
+ };
947
+ if (parent && key) {
948
+ parent[key] = fnExpr;
949
+ }
950
+ transformed = true;
951
+ } else {
952
+ transformed = walkExpression(binary.left, binary, "left") || transformed;
953
+ transformed = walkExpression(binary.right, binary, "right") || transformed;
954
+ }
955
+ }
956
+ if ("type" in expr && exprObj.type === "unary_expr") {
957
+ if ("expr" in exprObj) {
958
+ transformed = walkExpression(exprObj.expr, exprObj, "expr") || transformed;
959
+ }
960
+ }
961
+ if ("type" in expr && exprObj.type === "case") {
962
+ if ("expr" in exprObj && exprObj.expr) {
963
+ transformed = walkExpression(exprObj.expr, exprObj, "expr") || transformed;
964
+ }
965
+ if ("args" in exprObj && Array.isArray(exprObj.args)) {
966
+ for (let i = 0;i < exprObj.args.length; i++) {
967
+ const whenClause = exprObj.args[i];
968
+ if (whenClause.cond) {
969
+ transformed = walkExpression(whenClause.cond, whenClause, "cond") || transformed;
970
+ }
971
+ if (whenClause.result) {
972
+ transformed = walkExpression(whenClause.result, whenClause, "result") || transformed;
973
+ }
974
+ }
975
+ }
976
+ }
977
+ if ("args" in expr && exprObj.args) {
978
+ const args = exprObj.args;
979
+ if ("value" in args && Array.isArray(args.value)) {
980
+ for (let i = 0;i < args.value.length; i++) {
981
+ transformed = walkExpression(args.value[i], args.value, String(i)) || transformed;
982
+ }
983
+ } else if ("expr" in args) {
984
+ transformed = walkExpression(args.expr, args, "expr") || transformed;
985
+ }
986
+ }
987
+ if ("ast" in exprObj && exprObj.ast) {
988
+ const subAst = exprObj.ast;
989
+ if (subAst.type === "select") {
990
+ transformed = walkSelectImpl(subAst) || transformed;
991
+ }
992
+ }
993
+ if ("type" in expr && exprObj.type === "expr_list") {
994
+ if ("value" in exprObj && Array.isArray(exprObj.value)) {
995
+ for (let i = 0;i < exprObj.value.length; i++) {
996
+ transformed = walkExpression(exprObj.value[i], exprObj.value, String(i)) || transformed;
997
+ }
998
+ }
999
+ }
1000
+ return transformed;
1001
+ }
1002
+ function walkFrom(from) {
1003
+ if (!from || !Array.isArray(from))
1004
+ return false;
1005
+ let transformed = false;
1006
+ for (const f of from) {
1007
+ if ("join" in f) {
1008
+ const join = f;
1009
+ transformed = walkExpression(join.on, join, "on") || transformed;
1010
+ }
1011
+ if ("expr" in f && f.expr && "ast" in f.expr) {
1012
+ transformed = walkSelectImpl(f.expr.ast) || transformed;
1013
+ }
1014
+ }
1015
+ return transformed;
1016
+ }
1017
+ function walkSelectImpl(select) {
1018
+ let transformed = false;
1019
+ if (select.with) {
1020
+ for (const cte of select.with) {
1021
+ const cteSelect = cte.stmt?.ast ?? cte.stmt;
1022
+ if (cteSelect && cteSelect.type === "select") {
1023
+ transformed = walkSelectImpl(cteSelect) || transformed;
1024
+ }
1025
+ }
1026
+ }
1027
+ if (Array.isArray(select.from)) {
1028
+ transformed = walkFrom(select.from) || transformed;
1029
+ }
1030
+ transformed = walkExpression(select.where, select, "where") || transformed;
1031
+ if (select.having) {
1032
+ if (Array.isArray(select.having)) {
1033
+ for (let i = 0;i < select.having.length; i++) {
1034
+ transformed = walkExpression(select.having[i], select.having, String(i)) || transformed;
1035
+ }
1036
+ } else {
1037
+ transformed = walkExpression(select.having, select, "having") || transformed;
1038
+ }
1039
+ }
1040
+ if (Array.isArray(select.columns)) {
1041
+ for (const col of select.columns) {
1042
+ if ("expr" in col) {
1043
+ transformed = walkExpression(col.expr, col, "expr") || transformed;
1044
+ }
1045
+ }
1046
+ }
1047
+ if (select._next) {
1048
+ transformed = walkSelectImpl(select._next) || transformed;
1049
+ }
1050
+ return transformed;
1051
+ }
1052
+ function transformArrayOperators(ast) {
1053
+ const statements = Array.isArray(ast) ? ast : [ast];
1054
+ let transformed = false;
1055
+ for (const stmt of statements) {
1056
+ if (stmt.type === "select") {
1057
+ transformed = walkSelectImpl(stmt) || transformed;
1058
+ }
1059
+ }
1060
+ return transformed;
1061
+ }
1062
+
1063
+ // src/sql/visitors/column-qualifier.ts
1064
+ function getTableSource(from) {
1065
+ if ("table" in from && from.table) {
1066
+ return {
1067
+ name: from.table,
1068
+ alias: from.as ?? null
1069
+ };
1070
+ }
1071
+ if ("expr" in from && from.as) {
1072
+ return {
1073
+ name: from.as,
1074
+ alias: from.as
1075
+ };
1076
+ }
1077
+ return null;
1078
+ }
1079
+ function getQualifier(source) {
1080
+ return source.alias ?? source.name;
1081
+ }
1082
+ function isUnqualifiedColumnRef(expr) {
1083
+ return typeof expr === "object" && expr !== null && "type" in expr && expr.type === "column_ref" && !(("table" in expr) && expr.table);
1084
+ }
1085
+ function getColumnName(col) {
1086
+ if (typeof col.column === "string") {
1087
+ return col.column;
1088
+ }
1089
+ if (col.column && "expr" in col.column && col.column.expr?.value) {
1090
+ return String(col.column.expr.value);
1091
+ }
1092
+ return null;
1093
+ }
1094
+ function walkOnClause(expr, leftSource, rightSource, ambiguousColumns) {
1095
+ if (!expr || typeof expr !== "object")
1096
+ return false;
1097
+ let transformed = false;
1098
+ if (expr.type === "binary_expr") {
1099
+ if (expr.operator === "=") {
1100
+ const left = expr.left;
1101
+ const right = expr.right;
1102
+ if (isUnqualifiedColumnRef(left) && isUnqualifiedColumnRef(right)) {
1103
+ const leftColName = getColumnName(left);
1104
+ const rightColName = getColumnName(right);
1105
+ if (leftColName && rightColName && leftColName === rightColName) {
1106
+ left.table = leftSource;
1107
+ right.table = rightSource;
1108
+ ambiguousColumns.add(leftColName);
1109
+ transformed = true;
1110
+ }
1111
+ }
1112
+ }
1113
+ if (expr.operator === "AND" || expr.operator === "OR") {
1114
+ transformed = walkOnClause(expr.left, leftSource, rightSource, ambiguousColumns) || transformed;
1115
+ transformed = walkOnClause(expr.right, leftSource, rightSource, ambiguousColumns) || transformed;
1116
+ }
1117
+ }
1118
+ return transformed;
1119
+ }
1120
+ function qualifyAmbiguousInExpression(expr, defaultQualifier, ambiguousColumns) {
1121
+ if (!expr || typeof expr !== "object")
1122
+ return false;
1123
+ let transformed = false;
1124
+ if (isUnqualifiedColumnRef(expr)) {
1125
+ const colName = getColumnName(expr);
1126
+ if (colName && ambiguousColumns.has(colName)) {
1127
+ expr.table = defaultQualifier;
1128
+ transformed = true;
1129
+ }
1130
+ return transformed;
1131
+ }
1132
+ if ("type" in expr && expr.type === "binary_expr") {
1133
+ const binary = expr;
1134
+ transformed = qualifyAmbiguousInExpression(binary.left, defaultQualifier, ambiguousColumns) || transformed;
1135
+ transformed = qualifyAmbiguousInExpression(binary.right, defaultQualifier, ambiguousColumns) || transformed;
1136
+ return transformed;
1137
+ }
1138
+ if ("args" in expr && expr.args) {
1139
+ const args = expr.args;
1140
+ if (args.value && Array.isArray(args.value)) {
1141
+ for (const arg of args.value) {
1142
+ transformed = qualifyAmbiguousInExpression(arg, defaultQualifier, ambiguousColumns) || transformed;
1143
+ }
1144
+ }
1145
+ if (args.expr) {
1146
+ transformed = qualifyAmbiguousInExpression(args.expr, defaultQualifier, ambiguousColumns) || transformed;
1147
+ }
1148
+ }
1149
+ return transformed;
1150
+ }
1151
+ function walkSelect(select) {
1152
+ let transformed = false;
1153
+ const ambiguousColumns = new Set;
1154
+ if (Array.isArray(select.from) && select.from.length >= 2) {
1155
+ const firstSource = getTableSource(select.from[0]);
1156
+ const defaultQualifier = firstSource ? getQualifier(firstSource) : "";
1157
+ let prevSource = firstSource;
1158
+ for (const from of select.from) {
1159
+ if ("join" in from) {
1160
+ const join = from;
1161
+ const currentSource = getTableSource(join);
1162
+ if (join.on && prevSource && currentSource) {
1163
+ const leftQualifier = getQualifier(prevSource);
1164
+ const rightQualifier = getQualifier(currentSource);
1165
+ transformed = walkOnClause(join.on, leftQualifier, rightQualifier, ambiguousColumns) || transformed;
1166
+ }
1167
+ prevSource = currentSource;
1168
+ } else {
1169
+ const source = getTableSource(from);
1170
+ if (source) {
1171
+ prevSource = source;
1172
+ }
1173
+ }
1174
+ if ("expr" in from && from.expr && "ast" in from.expr) {
1175
+ transformed = walkSelect(from.expr.ast) || transformed;
1176
+ }
1177
+ }
1178
+ if (ambiguousColumns.size > 0 && defaultQualifier) {
1179
+ if (Array.isArray(select.columns)) {
1180
+ for (const col of select.columns) {
1181
+ if ("expr" in col) {
1182
+ transformed = qualifyAmbiguousInExpression(col.expr, defaultQualifier, ambiguousColumns) || transformed;
1183
+ }
1184
+ }
1185
+ }
1186
+ transformed = qualifyAmbiguousInExpression(select.where, defaultQualifier, ambiguousColumns) || transformed;
1187
+ if (Array.isArray(select.orderby)) {
1188
+ for (const order of select.orderby) {
1189
+ if (order.expr) {
1190
+ transformed = qualifyAmbiguousInExpression(order.expr, defaultQualifier, ambiguousColumns) || transformed;
1191
+ }
1192
+ }
1193
+ }
1194
+ }
1195
+ }
1196
+ if (select.with) {
1197
+ for (const cte of select.with) {
1198
+ const cteSelect = cte.stmt?.ast ?? cte.stmt;
1199
+ if (cteSelect && cteSelect.type === "select") {
1200
+ transformed = walkSelect(cteSelect) || transformed;
1201
+ }
1202
+ }
1203
+ }
1204
+ if (select._next) {
1205
+ transformed = walkSelect(select._next) || transformed;
1206
+ }
1207
+ return transformed;
1208
+ }
1209
+ function qualifyJoinColumns(ast) {
1210
+ const statements = Array.isArray(ast) ? ast : [ast];
1211
+ let transformed = false;
1212
+ for (const stmt of statements) {
1213
+ if (stmt.type === "select") {
1214
+ transformed = walkSelect(stmt) || transformed;
1215
+ }
1216
+ }
1217
+ return transformed;
1218
+ }
1219
+
1220
+ // src/sql/ast-transformer.ts
1221
+ var { Parser } = nodeSqlParser;
1222
+ var parser = new Parser;
1223
+ function transformSQL(query) {
1224
+ const needsArrayTransform = query.includes("@>") || query.includes("<@") || query.includes("&&");
1225
+ const needsJoinTransform = query.toLowerCase().includes("join");
1226
+ if (!needsArrayTransform && !needsJoinTransform) {
1227
+ return { sql: query, transformed: false };
1228
+ }
1229
+ try {
1230
+ const ast = parser.astify(query, { database: "PostgreSQL" });
1231
+ let transformed = false;
1232
+ if (needsArrayTransform) {
1233
+ transformed = transformArrayOperators(ast) || transformed;
1234
+ }
1235
+ if (needsJoinTransform) {
1236
+ transformed = qualifyJoinColumns(ast) || transformed;
1237
+ }
1238
+ if (!transformed) {
1239
+ return { sql: query, transformed: false };
1240
+ }
1241
+ const transformedSql = parser.sqlify(ast, { database: "PostgreSQL" });
1242
+ return { sql: transformedSql, transformed: true };
1243
+ } catch {
1244
+ return { sql: query, transformed: false };
1245
+ }
1246
+ }
1247
+
1248
+ // src/dialect.ts
1442
1249
  class DuckDBDialect extends PgDialect {
1443
1250
  static [entityKind2] = "DuckDBPgDialect";
1444
1251
  hasPgJsonColumn = false;
@@ -1515,6 +1322,14 @@ class DuckDBDialect extends PgDialect {
1515
1322
  return "none";
1516
1323
  }
1517
1324
  }
1325
+ sqlToQuery(sqlObj, invokeSource) {
1326
+ const result = super.sqlToQuery(sqlObj, invokeSource);
1327
+ const transformed = transformSQL(result.sql);
1328
+ return {
1329
+ ...result,
1330
+ sql: transformed.sql
1331
+ };
1332
+ }
1518
1333
  }
1519
1334
 
1520
1335
  // src/select-builder.ts
@@ -1525,10 +1340,10 @@ import {
1525
1340
  } from "drizzle-orm/pg-core/query-builders";
1526
1341
  import { Subquery, ViewBaseConfig } from "drizzle-orm";
1527
1342
  import { PgViewBase } from "drizzle-orm/pg-core/view-base";
1528
- import { SQL as SQL4 } from "drizzle-orm/sql/sql";
1343
+ import { SQL as SQL5 } from "drizzle-orm/sql/sql";
1529
1344
 
1530
1345
  // src/sql/selection.ts
1531
- import { Column as Column2, SQL as SQL3, getTableName as getTableName2, is as is3, sql as sql3 } from "drizzle-orm";
1346
+ import { Column as Column2, SQL as SQL4, getTableName as getTableName2, is as is3, sql as sql3 } from "drizzle-orm";
1532
1347
  function mapEntries(obj, prefix, fullJoin = false) {
1533
1348
  return Object.fromEntries(Object.entries(obj).filter(([key]) => key !== "enableRLS").map(([key, value]) => {
1534
1349
  const qualified = prefix ? `${prefix}.${key}` : key;
@@ -1538,16 +1353,16 @@ function mapEntries(obj, prefix, fullJoin = false) {
1538
1353
  sql3`${value}`.mapWith(value).as(`${getTableName2(value.table)}.${value.name}`)
1539
1354
  ];
1540
1355
  }
1541
- if (fullJoin && is3(value, SQL3)) {
1356
+ if (fullJoin && is3(value, SQL4)) {
1542
1357
  const col = value.getSQL().queryChunks.find((chunk) => is3(chunk, Column2));
1543
1358
  const tableName = col?.table && getTableName2(col?.table);
1544
1359
  return [key, value.as(tableName ? `${tableName}.${key}` : key)];
1545
1360
  }
1546
- if (is3(value, SQL3) || is3(value, Column2)) {
1547
- const aliased = is3(value, SQL3) ? value : sql3`${value}`.mapWith(value);
1361
+ if (is3(value, SQL4) || is3(value, Column2)) {
1362
+ const aliased = is3(value, SQL4) ? value : sql3`${value}`.mapWith(value);
1548
1363
  return [key, aliased.as(qualified)];
1549
1364
  }
1550
- if (is3(value, SQL3.Aliased)) {
1365
+ if (is3(value, SQL4.Aliased)) {
1551
1366
  return [key, value];
1552
1367
  }
1553
1368
  if (typeof value === "object" && value !== null) {
@@ -1595,7 +1410,7 @@ class DuckDBSelectBuilder extends PgSelectBuilder {
1595
1410
  ]));
1596
1411
  } else if (is4(src, PgViewBase)) {
1597
1412
  fields = src[ViewBaseConfig]?.selectedFields;
1598
- } else if (is4(src, SQL4)) {
1413
+ } else if (is4(src, SQL5)) {
1599
1414
  fields = {};
1600
1415
  } else {
1601
1416
  fields = aliasFields(getTableColumns(src), !isPartialSelect);
@@ -1786,16 +1601,6 @@ function createDuckDBConnectionPool(instance, options = {}) {
1786
1601
  }
1787
1602
 
1788
1603
  // src/options.ts
1789
- var DEFAULT_REWRITE_ARRAYS_MODE = "auto";
1790
- function resolveRewriteArraysOption(value) {
1791
- if (value === undefined)
1792
- return DEFAULT_REWRITE_ARRAYS_MODE;
1793
- if (value === true)
1794
- return "auto";
1795
- if (value === false)
1796
- return "never";
1797
- return value;
1798
- }
1799
1604
  var DEFAULT_PREPARED_CACHE_SIZE = 32;
1800
1605
  function resolvePrepareCacheOption(option) {
1801
1606
  if (!option)
@@ -1825,7 +1630,6 @@ class DuckDBDriver {
1825
1630
  createSession(schema) {
1826
1631
  return new DuckDBSession(this.client, this.dialect, schema, {
1827
1632
  logger: this.options.logger,
1828
- rewriteArrays: this.options.rewriteArrays ?? "auto",
1829
1633
  rejectStringArrayLiterals: this.options.rejectStringArrayLiterals,
1830
1634
  prepareCache: this.options.prepareCache
1831
1635
  });
@@ -1840,7 +1644,6 @@ function isConfigObject(data) {
1840
1644
  }
1841
1645
  function createFromClient(client, config = {}, instance) {
1842
1646
  const dialect = new DuckDBDialect;
1843
- const rewriteArraysMode = resolveRewriteArraysOption(config.rewriteArrays);
1844
1647
  const prepareCache = resolvePrepareCacheOption(config.prepareCache);
1845
1648
  const logger = config.logger === true ? new DefaultLogger : config.logger || undefined;
1846
1649
  let schema;
@@ -1854,7 +1657,6 @@ function createFromClient(client, config = {}, instance) {
1854
1657
  }
1855
1658
  const driver = new DuckDBDriver(client, dialect, {
1856
1659
  logger,
1857
- rewriteArrays: rewriteArraysMode,
1858
1660
  rejectStringArrayLiterals: config.rejectStringArrayLiterals,
1859
1661
  prepareCache
1860
1662
  });
@@ -2062,6 +1864,9 @@ var duckDbMap = (name, valueType) => customType({
2062
1864
  return `MAP (STRING, ${valueType})`;
2063
1865
  },
2064
1866
  toDriver(value) {
1867
+ if (Object.keys(value).length === 0) {
1868
+ return buildMapLiteral(value, valueType);
1869
+ }
2065
1870
  return wrapMap(value, valueType);
2066
1871
  },
2067
1872
  fromDriver(value) {
@@ -2811,7 +2616,7 @@ function renderImports(imports, importBasePath) {
2811
2616
  // src/olap.ts
2812
2617
  import { is as is5 } from "drizzle-orm/entity";
2813
2618
  import { sql as sql6 } from "drizzle-orm";
2814
- import { SQL as SQL5 } from "drizzle-orm/sql/sql";
2619
+ import { SQL as SQL6 } from "drizzle-orm/sql/sql";
2815
2620
  import { Column as Column3, getTableName as getTableName3 } from "drizzle-orm";
2816
2621
  var countN = (expr = sql6`*`) => sql6`count(${expr})`.mapWith(Number);
2817
2622
  var sumN = (expr) => sql6`sum(${expr})`.mapWith(Number);
@@ -2846,7 +2651,7 @@ var denseRank = (options) => sql6`dense_rank() ${overClause(options)}`.mapWith(N
2846
2651
  var lag = (expr, offset = 1, defaultValue, options) => defaultValue ? sql6`lag(${expr}, ${offset}, ${defaultValue}) ${overClause(options)}` : sql6`lag(${expr}, ${offset}) ${overClause(options)}`;
2847
2652
  var lead = (expr, offset = 1, defaultValue, options) => defaultValue ? sql6`lead(${expr}, ${offset}, ${defaultValue}) ${overClause(options)}` : sql6`lead(${expr}, ${offset}) ${overClause(options)}`;
2848
2653
  function keyAlias(key, fallback) {
2849
- if (is5(key, SQL5.Aliased)) {
2654
+ if (is5(key, SQL6.Aliased)) {
2850
2655
  return key.fieldAlias ?? fallback;
2851
2656
  }
2852
2657
  if (is5(key, Column3)) {
@@ -2917,6 +2722,17 @@ class OlapBuilder {
2917
2722
  }
2918
2723
  }
2919
2724
  var olap = (db) => new OlapBuilder(db);
2725
+ // src/operators.ts
2726
+ import { sql as sql7 } from "drizzle-orm";
2727
+ function arrayHasAll(column, values) {
2728
+ return sql7`array_has_all(${column}, ${values})`;
2729
+ }
2730
+ function arrayHasAny(column, values) {
2731
+ return sql7`array_has_any(${column}, ${values})`;
2732
+ }
2733
+ function arrayContainedBy(column, values) {
2734
+ return sql7`array_has_all(${values}, ${column})`;
2735
+ }
2920
2736
  export {
2921
2737
  wrapperToNodeApiValue,
2922
2738
  wrapTimestamp,
@@ -2931,7 +2747,6 @@ export {
2931
2747
  sumDistinctN,
2932
2748
  splitTopLevel,
2933
2749
  rowNumber,
2934
- resolveRewriteArraysOption,
2935
2750
  resolvePrepareCacheOption,
2936
2751
  resolvePoolSize,
2937
2752
  rank,
@@ -2978,6 +2793,9 @@ export {
2978
2793
  buildListLiteral,
2979
2794
  buildDefault,
2980
2795
  avgN,
2796
+ arrayHasAny,
2797
+ arrayHasAll,
2798
+ arrayContainedBy,
2981
2799
  anyValue,
2982
2800
  POOL_PRESETS,
2983
2801
  OlapBuilder,