@leonardovida-md/drizzle-neo-duckdb 1.0.2 → 1.1.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/README.md +51 -18
- package/dist/client.d.ts +19 -1
- package/dist/columns.d.ts +18 -10
- package/dist/driver.d.ts +37 -1
- package/dist/duckdb-introspect.mjs +382 -60
- package/dist/helpers.d.ts +1 -0
- package/dist/helpers.mjs +319 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.mjs +588 -72
- package/dist/introspect.d.ts +1 -0
- package/dist/olap.d.ts +46 -0
- package/dist/pool.d.ts +22 -0
- package/dist/session.d.ts +5 -0
- package/dist/sql/query-rewriters.d.ts +0 -1
- package/dist/utils.d.ts +1 -1
- package/dist/value-wrappers-core.d.ts +42 -0
- package/dist/value-wrappers.d.ts +8 -0
- package/package.json +12 -4
- package/src/bin/duckdb-introspect.ts +12 -3
- package/src/client.ts +178 -23
- package/src/columns.ts +65 -36
- package/src/dialect.ts +2 -2
- package/src/driver.ts +211 -13
- package/src/helpers.ts +18 -0
- package/src/index.ts +4 -0
- package/src/introspect.ts +39 -33
- package/src/migrator.ts +2 -4
- package/src/olap.ts +190 -0
- package/src/pool.ts +104 -0
- package/src/select-builder.ts +3 -7
- package/src/session.ts +123 -28
- package/src/sql/query-rewriters.ts +4 -54
- package/src/sql/result-mapper.ts +6 -6
- package/src/sql/selection.ts +2 -9
- package/src/utils.ts +1 -1
- package/src/value-wrappers-core.ts +156 -0
- package/src/value-wrappers.ts +155 -0
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
// src/driver.ts
|
|
2
|
+
import { DuckDBInstance as DuckDBInstance2 } from "@duckdb/node-api";
|
|
2
3
|
import { entityKind as entityKind3 } from "drizzle-orm/entity";
|
|
3
4
|
import { DefaultLogger } from "drizzle-orm/logger";
|
|
4
5
|
import { PgDatabase } from "drizzle-orm/pg-core/db";
|
|
@@ -15,10 +16,6 @@ import { PgPreparedQuery, PgSession } from "drizzle-orm/pg-core/session";
|
|
|
15
16
|
import { fillPlaceholders, sql } from "drizzle-orm/sql/sql";
|
|
16
17
|
|
|
17
18
|
// src/sql/query-rewriters.ts
|
|
18
|
-
var tableIdPropSelectionRegex = new RegExp([
|
|
19
|
-
`("(.+)"\\."(.+)")`,
|
|
20
|
-
`(\\s+as\\s+'?(.+?)'?\\.'?(.+?)'?)?`
|
|
21
|
-
].join(""), "i");
|
|
22
19
|
function adaptArrayOperators(query) {
|
|
23
20
|
const operators = [
|
|
24
21
|
{ token: "@>", fn: "array_has_all" },
|
|
@@ -35,6 +32,8 @@ function adaptArrayOperators(query) {
|
|
|
35
32
|
let inString = false;
|
|
36
33
|
for (;idx >= 0; idx--) {
|
|
37
34
|
const ch = source[idx];
|
|
35
|
+
if (ch === undefined)
|
|
36
|
+
break;
|
|
38
37
|
if (ch === "'" && source[idx - 1] !== "\\") {
|
|
39
38
|
inString = !inString;
|
|
40
39
|
}
|
|
@@ -62,6 +61,8 @@ function adaptArrayOperators(query) {
|
|
|
62
61
|
let inString = false;
|
|
63
62
|
for (;idx < source.length; idx++) {
|
|
64
63
|
const ch = source[idx];
|
|
64
|
+
if (ch === undefined)
|
|
65
|
+
break;
|
|
65
66
|
if (ch === "'" && source[idx - 1] !== "\\") {
|
|
66
67
|
inString = !inString;
|
|
67
68
|
}
|
|
@@ -303,8 +304,144 @@ import { TransactionRollbackError } from "drizzle-orm/errors";
|
|
|
303
304
|
|
|
304
305
|
// src/client.ts
|
|
305
306
|
import {
|
|
306
|
-
listValue
|
|
307
|
+
listValue as listValue2,
|
|
308
|
+
timestampValue as timestampValue2
|
|
307
309
|
} from "@duckdb/node-api";
|
|
310
|
+
|
|
311
|
+
// src/value-wrappers.ts
|
|
312
|
+
import {
|
|
313
|
+
listValue,
|
|
314
|
+
arrayValue,
|
|
315
|
+
structValue,
|
|
316
|
+
mapValue,
|
|
317
|
+
blobValue,
|
|
318
|
+
timestampValue,
|
|
319
|
+
timestampTZValue
|
|
320
|
+
} from "@duckdb/node-api";
|
|
321
|
+
|
|
322
|
+
// src/value-wrappers-core.ts
|
|
323
|
+
var DUCKDB_VALUE_MARKER = Symbol.for("drizzle-duckdb:value");
|
|
324
|
+
function isDuckDBWrapper(value) {
|
|
325
|
+
return value !== null && typeof value === "object" && DUCKDB_VALUE_MARKER in value && value[DUCKDB_VALUE_MARKER] === true;
|
|
326
|
+
}
|
|
327
|
+
function wrapList(data, elementType) {
|
|
328
|
+
return {
|
|
329
|
+
[DUCKDB_VALUE_MARKER]: true,
|
|
330
|
+
kind: "list",
|
|
331
|
+
data,
|
|
332
|
+
elementType
|
|
333
|
+
};
|
|
334
|
+
}
|
|
335
|
+
function wrapArray(data, elementType, fixedLength) {
|
|
336
|
+
return {
|
|
337
|
+
[DUCKDB_VALUE_MARKER]: true,
|
|
338
|
+
kind: "array",
|
|
339
|
+
data,
|
|
340
|
+
elementType,
|
|
341
|
+
fixedLength
|
|
342
|
+
};
|
|
343
|
+
}
|
|
344
|
+
function wrapStruct(data, schema) {
|
|
345
|
+
return {
|
|
346
|
+
[DUCKDB_VALUE_MARKER]: true,
|
|
347
|
+
kind: "struct",
|
|
348
|
+
data,
|
|
349
|
+
schema
|
|
350
|
+
};
|
|
351
|
+
}
|
|
352
|
+
function wrapMap(data, valueType) {
|
|
353
|
+
return {
|
|
354
|
+
[DUCKDB_VALUE_MARKER]: true,
|
|
355
|
+
kind: "map",
|
|
356
|
+
data,
|
|
357
|
+
valueType
|
|
358
|
+
};
|
|
359
|
+
}
|
|
360
|
+
function wrapTimestamp(data, withTimezone, precision) {
|
|
361
|
+
return {
|
|
362
|
+
[DUCKDB_VALUE_MARKER]: true,
|
|
363
|
+
kind: "timestamp",
|
|
364
|
+
data,
|
|
365
|
+
withTimezone,
|
|
366
|
+
precision
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
function wrapBlob(data) {
|
|
370
|
+
return {
|
|
371
|
+
[DUCKDB_VALUE_MARKER]: true,
|
|
372
|
+
kind: "blob",
|
|
373
|
+
data
|
|
374
|
+
};
|
|
375
|
+
}
|
|
376
|
+
function wrapJson(data) {
|
|
377
|
+
return {
|
|
378
|
+
[DUCKDB_VALUE_MARKER]: true,
|
|
379
|
+
kind: "json",
|
|
380
|
+
data
|
|
381
|
+
};
|
|
382
|
+
}
|
|
383
|
+
|
|
384
|
+
// src/value-wrappers.ts
|
|
385
|
+
function dateToMicros(value) {
|
|
386
|
+
if (value instanceof Date) {
|
|
387
|
+
return BigInt(value.getTime()) * 1000n;
|
|
388
|
+
}
|
|
389
|
+
let normalized = value;
|
|
390
|
+
if (!value.includes("T") && value.includes(" ")) {
|
|
391
|
+
normalized = value.replace(" ", "T");
|
|
392
|
+
}
|
|
393
|
+
if (!normalized.endsWith("Z") && !/[+-]\d{2}:?\d{2}$/.test(normalized)) {
|
|
394
|
+
normalized += "Z";
|
|
395
|
+
}
|
|
396
|
+
const date = new Date(normalized);
|
|
397
|
+
if (isNaN(date.getTime())) {
|
|
398
|
+
throw new Error(`Invalid timestamp string: ${value}`);
|
|
399
|
+
}
|
|
400
|
+
return BigInt(date.getTime()) * 1000n;
|
|
401
|
+
}
|
|
402
|
+
function toUint8Array(data) {
|
|
403
|
+
return data instanceof Uint8Array && !(data instanceof Buffer) ? data : new Uint8Array(data);
|
|
404
|
+
}
|
|
405
|
+
function convertStructEntries(data, toValue) {
|
|
406
|
+
const entries = {};
|
|
407
|
+
for (const [key, val] of Object.entries(data)) {
|
|
408
|
+
entries[key] = toValue(val);
|
|
409
|
+
}
|
|
410
|
+
return entries;
|
|
411
|
+
}
|
|
412
|
+
function convertMapEntries(data, toValue) {
|
|
413
|
+
return Object.entries(data).map(([key, val]) => ({
|
|
414
|
+
key,
|
|
415
|
+
value: toValue(val)
|
|
416
|
+
}));
|
|
417
|
+
}
|
|
418
|
+
function wrapperToNodeApiValue(wrapper, toValue) {
|
|
419
|
+
switch (wrapper.kind) {
|
|
420
|
+
case "list":
|
|
421
|
+
return listValue(wrapper.data.map(toValue));
|
|
422
|
+
case "array":
|
|
423
|
+
return arrayValue(wrapper.data.map(toValue));
|
|
424
|
+
case "struct":
|
|
425
|
+
return structValue(convertStructEntries(wrapper.data, toValue));
|
|
426
|
+
case "map":
|
|
427
|
+
return mapValue(convertMapEntries(wrapper.data, toValue));
|
|
428
|
+
case "timestamp":
|
|
429
|
+
return wrapper.withTimezone ? timestampTZValue(dateToMicros(wrapper.data)) : timestampValue(dateToMicros(wrapper.data));
|
|
430
|
+
case "blob":
|
|
431
|
+
return blobValue(toUint8Array(wrapper.data));
|
|
432
|
+
case "json":
|
|
433
|
+
return JSON.stringify(wrapper.data);
|
|
434
|
+
default: {
|
|
435
|
+
const _exhaustive = wrapper;
|
|
436
|
+
throw new Error(`Unknown wrapper kind: ${_exhaustive.kind}`);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
}
|
|
440
|
+
|
|
441
|
+
// src/client.ts
|
|
442
|
+
function isPool(client) {
|
|
443
|
+
return typeof client.acquire === "function";
|
|
444
|
+
}
|
|
308
445
|
function isPgArrayLiteral(value) {
|
|
309
446
|
return value.startsWith("{") && value.endsWith("}");
|
|
310
447
|
}
|
|
@@ -316,15 +453,13 @@ function parsePgArrayLiteral(value) {
|
|
|
316
453
|
return value;
|
|
317
454
|
}
|
|
318
455
|
}
|
|
319
|
-
var warnedArrayLiteral = false;
|
|
320
456
|
function prepareParams(params, options = {}) {
|
|
321
457
|
return params.map((param) => {
|
|
322
458
|
if (typeof param === "string" && isPgArrayLiteral(param)) {
|
|
323
459
|
if (options.rejectStringArrayLiterals) {
|
|
324
460
|
throw new Error("Stringified array literals are not supported. Use duckDbList()/duckDbArray() or pass native arrays.");
|
|
325
461
|
}
|
|
326
|
-
if (
|
|
327
|
-
warnedArrayLiteral = true;
|
|
462
|
+
if (options.warnOnStringArrayLiteral) {
|
|
328
463
|
options.warnOnStringArrayLiteral();
|
|
329
464
|
}
|
|
330
465
|
return parsePgArrayLiteral(param);
|
|
@@ -333,30 +468,116 @@ function prepareParams(params, options = {}) {
|
|
|
333
468
|
});
|
|
334
469
|
}
|
|
335
470
|
function toNodeApiValue(value) {
|
|
471
|
+
if (value == null)
|
|
472
|
+
return null;
|
|
473
|
+
const t = typeof value;
|
|
474
|
+
if (t === "string" || t === "number" || t === "bigint" || t === "boolean") {
|
|
475
|
+
return value;
|
|
476
|
+
}
|
|
477
|
+
if (t === "object" && DUCKDB_VALUE_MARKER in value) {
|
|
478
|
+
return wrapperToNodeApiValue(value, toNodeApiValue);
|
|
479
|
+
}
|
|
336
480
|
if (Array.isArray(value)) {
|
|
337
|
-
return
|
|
481
|
+
return listValue2(value.map((inner) => toNodeApiValue(inner)));
|
|
482
|
+
}
|
|
483
|
+
if (value instanceof Date) {
|
|
484
|
+
return timestampValue2(BigInt(value.getTime()) * 1000n);
|
|
338
485
|
}
|
|
339
486
|
return value;
|
|
340
487
|
}
|
|
341
|
-
|
|
342
|
-
const values = params.length > 0 ? params.map((param) => toNodeApiValue(param)) : undefined;
|
|
343
|
-
const result = await client.run(query, values);
|
|
344
|
-
const rows = await result.getRowsJS();
|
|
345
|
-
const columns = result.columnNames();
|
|
488
|
+
function deduplicateColumns(columns) {
|
|
346
489
|
const seen = {};
|
|
347
|
-
|
|
490
|
+
return columns.map((col) => {
|
|
348
491
|
const count = seen[col] ?? 0;
|
|
349
492
|
seen[col] = count + 1;
|
|
350
493
|
return count === 0 ? col : `${col}_${count}`;
|
|
351
494
|
});
|
|
352
|
-
|
|
495
|
+
}
|
|
496
|
+
function mapRowsToObjects(columns, rows) {
|
|
497
|
+
return rows.map((vals) => {
|
|
353
498
|
const obj = {};
|
|
354
|
-
|
|
499
|
+
columns.forEach((col, idx) => {
|
|
355
500
|
obj[col] = vals[idx];
|
|
356
501
|
});
|
|
357
502
|
return obj;
|
|
358
503
|
});
|
|
359
504
|
}
|
|
505
|
+
async function closeClientConnection(connection) {
|
|
506
|
+
if ("close" in connection && typeof connection.close === "function") {
|
|
507
|
+
await connection.close();
|
|
508
|
+
return;
|
|
509
|
+
}
|
|
510
|
+
if ("closeSync" in connection && typeof connection.closeSync === "function") {
|
|
511
|
+
connection.closeSync();
|
|
512
|
+
return;
|
|
513
|
+
}
|
|
514
|
+
if ("disconnectSync" in connection && typeof connection.disconnectSync === "function") {
|
|
515
|
+
connection.disconnectSync();
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
async function executeOnClient(client, query, params) {
|
|
519
|
+
if (isPool(client)) {
|
|
520
|
+
const connection = await client.acquire();
|
|
521
|
+
try {
|
|
522
|
+
return await executeOnClient(connection, query, params);
|
|
523
|
+
} finally {
|
|
524
|
+
await client.release(connection);
|
|
525
|
+
}
|
|
526
|
+
}
|
|
527
|
+
const values = params.length > 0 ? params.map((param) => toNodeApiValue(param)) : undefined;
|
|
528
|
+
const result = await client.run(query, values);
|
|
529
|
+
const rows = await result.getRowsJS();
|
|
530
|
+
const columns = result.deduplicatedColumnNames?.() ?? result.columnNames();
|
|
531
|
+
const uniqueColumns = deduplicateColumns(columns);
|
|
532
|
+
return rows ? mapRowsToObjects(uniqueColumns, rows) : [];
|
|
533
|
+
}
|
|
534
|
+
async function* executeInBatches(client, query, params, options = {}) {
|
|
535
|
+
if (isPool(client)) {
|
|
536
|
+
const connection = await client.acquire();
|
|
537
|
+
try {
|
|
538
|
+
yield* executeInBatches(connection, query, params, options);
|
|
539
|
+
return;
|
|
540
|
+
} finally {
|
|
541
|
+
await client.release(connection);
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
const rowsPerChunk = options.rowsPerChunk && options.rowsPerChunk > 0 ? options.rowsPerChunk : 1e5;
|
|
545
|
+
const values = params.length > 0 ? params.map((param) => toNodeApiValue(param)) : undefined;
|
|
546
|
+
const result = await client.stream(query, values);
|
|
547
|
+
const columns = result.deduplicatedColumnNames?.() ?? result.columnNames();
|
|
548
|
+
const uniqueColumns = deduplicateColumns(columns);
|
|
549
|
+
let buffer = [];
|
|
550
|
+
for await (const chunk of result.yieldRowsJs()) {
|
|
551
|
+
const objects = mapRowsToObjects(uniqueColumns, chunk);
|
|
552
|
+
for (const row of objects) {
|
|
553
|
+
buffer.push(row);
|
|
554
|
+
if (buffer.length >= rowsPerChunk) {
|
|
555
|
+
yield buffer;
|
|
556
|
+
buffer = [];
|
|
557
|
+
}
|
|
558
|
+
}
|
|
559
|
+
}
|
|
560
|
+
if (buffer.length > 0) {
|
|
561
|
+
yield buffer;
|
|
562
|
+
}
|
|
563
|
+
}
|
|
564
|
+
async function executeArrowOnClient(client, query, params) {
|
|
565
|
+
if (isPool(client)) {
|
|
566
|
+
const connection = await client.acquire();
|
|
567
|
+
try {
|
|
568
|
+
return await executeArrowOnClient(connection, query, params);
|
|
569
|
+
} finally {
|
|
570
|
+
await client.release(connection);
|
|
571
|
+
}
|
|
572
|
+
}
|
|
573
|
+
const values = params.length > 0 ? params.map((param) => toNodeApiValue(param)) : undefined;
|
|
574
|
+
const result = await client.run(query, values);
|
|
575
|
+
const maybeArrow = result.toArrow ?? result.getArrowTable;
|
|
576
|
+
if (typeof maybeArrow === "function") {
|
|
577
|
+
return await maybeArrow.call(result);
|
|
578
|
+
}
|
|
579
|
+
return result.getColumnsObjectJS();
|
|
580
|
+
}
|
|
360
581
|
|
|
361
582
|
// src/session.ts
|
|
362
583
|
class DuckDBPreparedQuery extends PgPreparedQuery {
|
|
@@ -397,11 +618,7 @@ class DuckDBPreparedQuery extends PgPreparedQuery {
|
|
|
397
618
|
this.logger.logQuery(`[duckdb] original query before array rewrite: ${this.queryString}`, params);
|
|
398
619
|
}
|
|
399
620
|
this.logger.logQuery(rewrittenQuery, params);
|
|
400
|
-
const {
|
|
401
|
-
fields,
|
|
402
|
-
joinsNotNullableMap,
|
|
403
|
-
customResultMapper
|
|
404
|
-
} = this;
|
|
621
|
+
const { fields, joinsNotNullableMap, customResultMapper } = this;
|
|
405
622
|
const rows = await executeOnClient(this.client, rewrittenQuery, params);
|
|
406
623
|
if (rows.length === 0 || !fields) {
|
|
407
624
|
return rows;
|
|
@@ -441,16 +658,30 @@ class DuckDBSession extends PgSession {
|
|
|
441
658
|
return new DuckDBPreparedQuery(this.client, this.dialect, query.sql, query.params, this.logger, fields, isResponseInArrayMode, customResultMapper, this.rewriteArrays, this.rejectStringArrayLiterals, this.rejectStringArrayLiterals ? undefined : this.warnOnStringArrayLiteral);
|
|
442
659
|
}
|
|
443
660
|
async transaction(transaction) {
|
|
444
|
-
|
|
661
|
+
let pinnedConnection;
|
|
662
|
+
let pool;
|
|
663
|
+
let clientForTx = this.client;
|
|
664
|
+
if (isPool(this.client)) {
|
|
665
|
+
pool = this.client;
|
|
666
|
+
pinnedConnection = await pool.acquire();
|
|
667
|
+
clientForTx = pinnedConnection;
|
|
668
|
+
}
|
|
669
|
+
const session = new DuckDBSession(clientForTx, this.dialect, this.schema, this.options);
|
|
445
670
|
const tx = new DuckDBTransaction(this.dialect, session, this.schema);
|
|
446
|
-
await tx.execute(sql`BEGIN TRANSACTION;`);
|
|
447
671
|
try {
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
672
|
+
await tx.execute(sql`BEGIN TRANSACTION;`);
|
|
673
|
+
try {
|
|
674
|
+
const result = await transaction(tx);
|
|
675
|
+
await tx.execute(sql`commit`);
|
|
676
|
+
return result;
|
|
677
|
+
} catch (error) {
|
|
678
|
+
await tx.execute(sql`rollback`);
|
|
679
|
+
throw error;
|
|
680
|
+
}
|
|
681
|
+
} finally {
|
|
682
|
+
if (pinnedConnection && pool) {
|
|
683
|
+
await pool.release(pinnedConnection);
|
|
684
|
+
}
|
|
454
685
|
}
|
|
455
686
|
}
|
|
456
687
|
warnOnStringArrayLiteral = (query) => {
|
|
@@ -461,6 +692,32 @@ class DuckDBSession extends PgSession {
|
|
|
461
692
|
this.logger.logQuery(`[duckdb] ${arrayLiteralWarning}
|
|
462
693
|
query: ${query}`, []);
|
|
463
694
|
};
|
|
695
|
+
executeBatches(query, options = {}) {
|
|
696
|
+
const builtQuery = this.dialect.sqlToQuery(query);
|
|
697
|
+
const params = prepareParams(builtQuery.params, {
|
|
698
|
+
rejectStringArrayLiterals: this.rejectStringArrayLiterals,
|
|
699
|
+
warnOnStringArrayLiteral: this.rejectStringArrayLiterals ? undefined : () => this.warnOnStringArrayLiteral(builtQuery.sql)
|
|
700
|
+
});
|
|
701
|
+
const rewrittenQuery = this.rewriteArrays ? adaptArrayOperators(builtQuery.sql) : builtQuery.sql;
|
|
702
|
+
if (this.rewriteArrays && rewrittenQuery !== builtQuery.sql) {
|
|
703
|
+
this.logger.logQuery(`[duckdb] original query before array rewrite: ${builtQuery.sql}`, params);
|
|
704
|
+
}
|
|
705
|
+
this.logger.logQuery(rewrittenQuery, params);
|
|
706
|
+
return executeInBatches(this.client, rewrittenQuery, params, options);
|
|
707
|
+
}
|
|
708
|
+
async executeArrow(query) {
|
|
709
|
+
const builtQuery = this.dialect.sqlToQuery(query);
|
|
710
|
+
const params = prepareParams(builtQuery.params, {
|
|
711
|
+
rejectStringArrayLiterals: this.rejectStringArrayLiterals,
|
|
712
|
+
warnOnStringArrayLiteral: this.rejectStringArrayLiterals ? undefined : () => this.warnOnStringArrayLiteral(builtQuery.sql)
|
|
713
|
+
});
|
|
714
|
+
const rewrittenQuery = this.rewriteArrays ? adaptArrayOperators(builtQuery.sql) : builtQuery.sql;
|
|
715
|
+
if (this.rewriteArrays && rewrittenQuery !== builtQuery.sql) {
|
|
716
|
+
this.logger.logQuery(`[duckdb] original query before array rewrite: ${builtQuery.sql}`, params);
|
|
717
|
+
}
|
|
718
|
+
this.logger.logQuery(rewrittenQuery, params);
|
|
719
|
+
return executeArrowOnClient(this.client, rewrittenQuery, params);
|
|
720
|
+
}
|
|
464
721
|
}
|
|
465
722
|
|
|
466
723
|
class DuckDBTransaction extends PgTransaction {
|
|
@@ -484,6 +741,12 @@ class DuckDBTransaction extends PgTransaction {
|
|
|
484
741
|
setTransaction(config) {
|
|
485
742
|
return this.session.execute(sql`set transaction ${this.getTransactionConfigSQL(config)}`);
|
|
486
743
|
}
|
|
744
|
+
executeBatches(query, options = {}) {
|
|
745
|
+
return this.session.executeBatches(query, options);
|
|
746
|
+
}
|
|
747
|
+
executeArrow(query) {
|
|
748
|
+
return this.session.executeArrow(query);
|
|
749
|
+
}
|
|
487
750
|
async transaction(transaction) {
|
|
488
751
|
const nestedTx = new DuckDBTransaction(this.dialect, this.session, this.schema, this.nestedIndex + 1);
|
|
489
752
|
return transaction(nestedTx);
|
|
@@ -582,13 +845,7 @@ import { PgViewBase } from "drizzle-orm/pg-core/view-base";
|
|
|
582
845
|
import { SQL as SQL4 } from "drizzle-orm/sql/sql";
|
|
583
846
|
|
|
584
847
|
// src/sql/selection.ts
|
|
585
|
-
import {
|
|
586
|
-
Column as Column2,
|
|
587
|
-
SQL as SQL3,
|
|
588
|
-
getTableName as getTableName2,
|
|
589
|
-
is as is3,
|
|
590
|
-
sql as sql3
|
|
591
|
-
} from "drizzle-orm";
|
|
848
|
+
import { Column as Column2, SQL as SQL3, getTableName as getTableName2, is as is3, sql as sql3 } from "drizzle-orm";
|
|
592
849
|
function mapEntries(obj, prefix, fullJoin = false) {
|
|
593
850
|
return Object.fromEntries(Object.entries(obj).filter(([key]) => key !== "enableRLS").map(([key, value]) => {
|
|
594
851
|
const qualified = prefix ? `${prefix}.${key}` : key;
|
|
@@ -672,6 +929,72 @@ class DuckDBSelectBuilder extends PgSelectBuilder {
|
|
|
672
929
|
}
|
|
673
930
|
}
|
|
674
931
|
|
|
932
|
+
// src/pool.ts
|
|
933
|
+
import { DuckDBConnection } from "@duckdb/node-api";
|
|
934
|
+
var POOL_PRESETS = {
|
|
935
|
+
pulse: 4,
|
|
936
|
+
standard: 6,
|
|
937
|
+
jumbo: 8,
|
|
938
|
+
mega: 12,
|
|
939
|
+
giga: 16,
|
|
940
|
+
local: 8,
|
|
941
|
+
memory: 4
|
|
942
|
+
};
|
|
943
|
+
function resolvePoolSize(pool) {
|
|
944
|
+
if (pool === false)
|
|
945
|
+
return false;
|
|
946
|
+
if (pool === undefined)
|
|
947
|
+
return 4;
|
|
948
|
+
if (typeof pool === "string")
|
|
949
|
+
return POOL_PRESETS[pool];
|
|
950
|
+
return pool.size ?? 4;
|
|
951
|
+
}
|
|
952
|
+
function createDuckDBConnectionPool(instance, options = {}) {
|
|
953
|
+
const size = options.size && options.size > 0 ? options.size : 4;
|
|
954
|
+
const idle = [];
|
|
955
|
+
const waiting = [];
|
|
956
|
+
let total = 0;
|
|
957
|
+
let closed = false;
|
|
958
|
+
const acquire = async () => {
|
|
959
|
+
if (closed) {
|
|
960
|
+
throw new Error("DuckDB connection pool is closed");
|
|
961
|
+
}
|
|
962
|
+
if (idle.length > 0) {
|
|
963
|
+
return idle.pop();
|
|
964
|
+
}
|
|
965
|
+
if (total < size) {
|
|
966
|
+
total += 1;
|
|
967
|
+
return await DuckDBConnection.create(instance);
|
|
968
|
+
}
|
|
969
|
+
return await new Promise((resolve) => {
|
|
970
|
+
waiting.push(resolve);
|
|
971
|
+
});
|
|
972
|
+
};
|
|
973
|
+
const release = async (connection) => {
|
|
974
|
+
if (closed) {
|
|
975
|
+
await closeClientConnection(connection);
|
|
976
|
+
return;
|
|
977
|
+
}
|
|
978
|
+
const waiter = waiting.shift();
|
|
979
|
+
if (waiter) {
|
|
980
|
+
waiter(connection);
|
|
981
|
+
return;
|
|
982
|
+
}
|
|
983
|
+
idle.push(connection);
|
|
984
|
+
};
|
|
985
|
+
const close = async () => {
|
|
986
|
+
closed = true;
|
|
987
|
+
const toClose = idle.splice(0, idle.length);
|
|
988
|
+
await Promise.all(toClose.map((conn) => closeClientConnection(conn)));
|
|
989
|
+
};
|
|
990
|
+
return {
|
|
991
|
+
acquire,
|
|
992
|
+
release,
|
|
993
|
+
close,
|
|
994
|
+
size
|
|
995
|
+
};
|
|
996
|
+
}
|
|
997
|
+
|
|
675
998
|
// src/driver.ts
|
|
676
999
|
class DuckDBDriver {
|
|
677
1000
|
client;
|
|
@@ -691,7 +1014,14 @@ class DuckDBDriver {
|
|
|
691
1014
|
});
|
|
692
1015
|
}
|
|
693
1016
|
}
|
|
694
|
-
function
|
|
1017
|
+
function isConfigObject(data) {
|
|
1018
|
+
if (typeof data !== "object" || data === null)
|
|
1019
|
+
return false;
|
|
1020
|
+
if (data.constructor?.name !== "Object")
|
|
1021
|
+
return false;
|
|
1022
|
+
return "connection" in data || "client" in data || "pool" in data || "schema" in data || "logger" in data;
|
|
1023
|
+
}
|
|
1024
|
+
function createFromClient(client, config = {}, instance) {
|
|
695
1025
|
const dialect = new DuckDBDialect;
|
|
696
1026
|
const logger = config.logger === true ? new DefaultLogger : config.logger || undefined;
|
|
697
1027
|
let schema;
|
|
@@ -709,17 +1039,60 @@ function drizzle(client, config = {}) {
|
|
|
709
1039
|
rejectStringArrayLiterals: config.rejectStringArrayLiterals
|
|
710
1040
|
});
|
|
711
1041
|
const session = driver.createSession(schema);
|
|
712
|
-
|
|
1042
|
+
const db = new DuckDBDatabase(dialect, session, schema, client, instance);
|
|
1043
|
+
return db;
|
|
1044
|
+
}
|
|
1045
|
+
async function createFromConnectionString(path, instanceOptions, config = {}) {
|
|
1046
|
+
const instance = await DuckDBInstance2.create(path, instanceOptions);
|
|
1047
|
+
const poolSize = resolvePoolSize(config.pool);
|
|
1048
|
+
if (poolSize === false) {
|
|
1049
|
+
const connection = await instance.connect();
|
|
1050
|
+
return createFromClient(connection, config, instance);
|
|
1051
|
+
}
|
|
1052
|
+
const pool = createDuckDBConnectionPool(instance, { size: poolSize });
|
|
1053
|
+
return createFromClient(pool, config, instance);
|
|
1054
|
+
}
|
|
1055
|
+
function drizzle(clientOrConfigOrPath, config) {
|
|
1056
|
+
if (typeof clientOrConfigOrPath === "string") {
|
|
1057
|
+
return createFromConnectionString(clientOrConfigOrPath, undefined, config);
|
|
1058
|
+
}
|
|
1059
|
+
if (isConfigObject(clientOrConfigOrPath)) {
|
|
1060
|
+
const configObj = clientOrConfigOrPath;
|
|
1061
|
+
if ("connection" in configObj) {
|
|
1062
|
+
const connConfig = configObj;
|
|
1063
|
+
const { connection, ...restConfig } = connConfig;
|
|
1064
|
+
if (typeof connection === "string") {
|
|
1065
|
+
return createFromConnectionString(connection, undefined, restConfig);
|
|
1066
|
+
}
|
|
1067
|
+
return createFromConnectionString(connection.path, connection.options, restConfig);
|
|
1068
|
+
}
|
|
1069
|
+
if ("client" in configObj) {
|
|
1070
|
+
const clientConfig = configObj;
|
|
1071
|
+
const { client: clientValue, ...restConfig } = clientConfig;
|
|
1072
|
+
return createFromClient(clientValue, restConfig);
|
|
1073
|
+
}
|
|
1074
|
+
throw new Error("Invalid drizzle config: either connection or client must be provided");
|
|
1075
|
+
}
|
|
1076
|
+
return createFromClient(clientOrConfigOrPath, config);
|
|
713
1077
|
}
|
|
714
1078
|
|
|
715
1079
|
class DuckDBDatabase extends PgDatabase {
|
|
716
1080
|
dialect;
|
|
717
1081
|
session;
|
|
718
1082
|
static [entityKind3] = "DuckDBDatabase";
|
|
719
|
-
|
|
1083
|
+
$client;
|
|
1084
|
+
$instance;
|
|
1085
|
+
constructor(dialect, session, schema, client, instance) {
|
|
720
1086
|
super(dialect, session, schema);
|
|
721
1087
|
this.dialect = dialect;
|
|
722
1088
|
this.session = session;
|
|
1089
|
+
this.$client = client;
|
|
1090
|
+
this.$instance = instance;
|
|
1091
|
+
}
|
|
1092
|
+
async close() {
|
|
1093
|
+
if (isPool(this.$client) && this.$client.close) {
|
|
1094
|
+
await this.$client.close();
|
|
1095
|
+
}
|
|
723
1096
|
}
|
|
724
1097
|
select(fields) {
|
|
725
1098
|
const selectedFields = fields ? aliasFields(fields) : undefined;
|
|
@@ -729,6 +1102,12 @@ class DuckDBDatabase extends PgDatabase {
|
|
|
729
1102
|
dialect: this.dialect
|
|
730
1103
|
});
|
|
731
1104
|
}
|
|
1105
|
+
executeBatches(query, options = {}) {
|
|
1106
|
+
return this.session.executeBatches(query, options);
|
|
1107
|
+
}
|
|
1108
|
+
executeArrow(query) {
|
|
1109
|
+
return this.session.executeArrow(query);
|
|
1110
|
+
}
|
|
732
1111
|
async transaction(transaction) {
|
|
733
1112
|
return await this.session.transaction(transaction);
|
|
734
1113
|
}
|
|
@@ -797,19 +1176,12 @@ function buildStructLiteral(value, schema) {
|
|
|
797
1176
|
});
|
|
798
1177
|
return sql4`struct_pack(${sql4.join(parts, sql4.raw(", "))})`;
|
|
799
1178
|
}
|
|
800
|
-
function buildMapLiteral(value, valueType) {
|
|
801
|
-
const keys = Object.keys(value);
|
|
802
|
-
const vals = Object.values(value);
|
|
803
|
-
const keyList = buildListLiteral(keys, "TEXT");
|
|
804
|
-
const valList = buildListLiteral(vals, valueType?.endsWith("[]") ? valueType.slice(0, -2) : valueType);
|
|
805
|
-
return sql4`map(${keyList}, ${valList})`;
|
|
806
|
-
}
|
|
807
1179
|
var duckDbList = (name, elementType) => customType({
|
|
808
1180
|
dataType() {
|
|
809
1181
|
return `${elementType}[]`;
|
|
810
1182
|
},
|
|
811
1183
|
toDriver(value) {
|
|
812
|
-
return
|
|
1184
|
+
return wrapList(value, elementType);
|
|
813
1185
|
},
|
|
814
1186
|
fromDriver(value) {
|
|
815
1187
|
if (Array.isArray(value)) {
|
|
@@ -829,7 +1201,7 @@ var duckDbArray = (name, elementType, fixedLength) => customType({
|
|
|
829
1201
|
return fixedLength ? `${elementType}[${fixedLength}]` : `${elementType}[]`;
|
|
830
1202
|
},
|
|
831
1203
|
toDriver(value) {
|
|
832
|
-
return
|
|
1204
|
+
return wrapArray(value, elementType, fixedLength);
|
|
833
1205
|
},
|
|
834
1206
|
fromDriver(value) {
|
|
835
1207
|
if (Array.isArray(value)) {
|
|
@@ -849,7 +1221,7 @@ var duckDbMap = (name, valueType) => customType({
|
|
|
849
1221
|
return `MAP (STRING, ${valueType})`;
|
|
850
1222
|
},
|
|
851
1223
|
toDriver(value) {
|
|
852
|
-
return
|
|
1224
|
+
return wrapMap(value, valueType);
|
|
853
1225
|
},
|
|
854
1226
|
fromDriver(value) {
|
|
855
1227
|
return value;
|
|
@@ -885,7 +1257,7 @@ var duckDbJson = (name) => customType({
|
|
|
885
1257
|
if (value !== null && typeof value === "object" && "queryChunks" in value) {
|
|
886
1258
|
return value;
|
|
887
1259
|
}
|
|
888
|
-
return
|
|
1260
|
+
return wrapJson(value);
|
|
889
1261
|
},
|
|
890
1262
|
fromDriver(value) {
|
|
891
1263
|
if (typeof value !== "string") {
|
|
@@ -907,8 +1279,7 @@ var duckDbBlob = customType({
|
|
|
907
1279
|
return "BLOB";
|
|
908
1280
|
},
|
|
909
1281
|
toDriver(value) {
|
|
910
|
-
|
|
911
|
-
return sql4`from_hex(${hexString})`;
|
|
1282
|
+
return wrapBlob(value);
|
|
912
1283
|
}
|
|
913
1284
|
});
|
|
914
1285
|
var duckDbInet = (name) => customType({
|
|
@@ -1010,7 +1381,7 @@ async function migrate(db, config) {
|
|
|
1010
1381
|
// src/introspect.ts
|
|
1011
1382
|
import { sql as sql5 } from "drizzle-orm";
|
|
1012
1383
|
var SYSTEM_SCHEMAS = new Set(["information_schema", "pg_catalog"]);
|
|
1013
|
-
var DEFAULT_IMPORT_BASE = "@leonardovida-md/drizzle-neo-duckdb";
|
|
1384
|
+
var DEFAULT_IMPORT_BASE = "@leonardovida-md/drizzle-neo-duckdb/helpers";
|
|
1014
1385
|
async function introspect(db, opts = {}) {
|
|
1015
1386
|
const database = await resolveDatabase(db, opts.database, opts.allDatabases);
|
|
1016
1387
|
const schemas = await resolveSchemas(db, database, opts.schemas);
|
|
@@ -1311,7 +1682,9 @@ function mapDuckDbType(column, imports, options) {
|
|
|
1311
1682
|
}
|
|
1312
1683
|
if (upper === "BIGINT" || upper === "INT8" || upper === "UBIGINT") {
|
|
1313
1684
|
imports.pgCore.add("bigint");
|
|
1314
|
-
return {
|
|
1685
|
+
return {
|
|
1686
|
+
builder: `bigint(${columnName(column.name)}, { mode: 'number' })`
|
|
1687
|
+
};
|
|
1315
1688
|
}
|
|
1316
1689
|
const decimalMatch = /^DECIMAL\((\d+),(\d+)\)/i.exec(upper);
|
|
1317
1690
|
const numericMatch = /^NUMERIC\((\d+),(\d+)\)/i.exec(upper);
|
|
@@ -1344,6 +1717,22 @@ function mapDuckDbType(column, imports, options) {
|
|
|
1344
1717
|
imports.pgCore.add("doublePrecision");
|
|
1345
1718
|
return { builder: `doublePrecision(${columnName(column.name)})` };
|
|
1346
1719
|
}
|
|
1720
|
+
const arrayMatch = /^(.*)\[(\d+)\]$/.exec(upper);
|
|
1721
|
+
if (arrayMatch) {
|
|
1722
|
+
imports.local.add("duckDbArray");
|
|
1723
|
+
const [, base, length] = arrayMatch;
|
|
1724
|
+
return {
|
|
1725
|
+
builder: `duckDbArray(${columnName(column.name)}, ${JSON.stringify(base)}, ${Number(length)})`
|
|
1726
|
+
};
|
|
1727
|
+
}
|
|
1728
|
+
const listMatch = /^(.*)\[\]$/.exec(upper);
|
|
1729
|
+
if (listMatch) {
|
|
1730
|
+
imports.local.add("duckDbList");
|
|
1731
|
+
const [, base] = listMatch;
|
|
1732
|
+
return {
|
|
1733
|
+
builder: `duckDbList(${columnName(column.name)}, ${JSON.stringify(base)})`
|
|
1734
|
+
};
|
|
1735
|
+
}
|
|
1347
1736
|
if (upper.startsWith("CHAR(") || upper === "CHAR") {
|
|
1348
1737
|
imports.pgCore.add("char");
|
|
1349
1738
|
const length = column.characterLength;
|
|
@@ -1384,22 +1773,6 @@ function mapDuckDbType(column, imports, options) {
|
|
|
1384
1773
|
imports.local.add("duckDbBlob");
|
|
1385
1774
|
return { builder: `duckDbBlob(${columnName(column.name)})` };
|
|
1386
1775
|
}
|
|
1387
|
-
const arrayMatch = /^(.*)\[(\d+)\]$/.exec(upper);
|
|
1388
|
-
if (arrayMatch) {
|
|
1389
|
-
imports.local.add("duckDbArray");
|
|
1390
|
-
const [, base, length] = arrayMatch;
|
|
1391
|
-
return {
|
|
1392
|
-
builder: `duckDbArray(${columnName(column.name)}, ${JSON.stringify(base)}, ${Number(length)})`
|
|
1393
|
-
};
|
|
1394
|
-
}
|
|
1395
|
-
const listMatch = /^(.*)\[\]$/.exec(upper);
|
|
1396
|
-
if (listMatch) {
|
|
1397
|
-
imports.local.add("duckDbList");
|
|
1398
|
-
const [, base] = listMatch;
|
|
1399
|
-
return {
|
|
1400
|
-
builder: `duckDbList(${columnName(column.name)}, ${JSON.stringify(base)})`
|
|
1401
|
-
};
|
|
1402
|
-
}
|
|
1403
1776
|
if (upper.startsWith("STRUCT")) {
|
|
1404
1777
|
imports.local.add("duckDbStruct");
|
|
1405
1778
|
const inner = upper.replace(/^STRUCT\s*\(/i, "").replace(/\)$/, "");
|
|
@@ -1558,9 +1931,142 @@ function renderImports(imports, importBasePath) {
|
|
|
1558
1931
|
return lines.join(`
|
|
1559
1932
|
`);
|
|
1560
1933
|
}
|
|
1934
|
+
// src/olap.ts
|
|
1935
|
+
import { is as is5 } from "drizzle-orm/entity";
|
|
1936
|
+
import { sql as sql6 } from "drizzle-orm";
|
|
1937
|
+
import { SQL as SQL5 } from "drizzle-orm/sql/sql";
|
|
1938
|
+
import { Column as Column3, getTableName as getTableName3 } from "drizzle-orm";
|
|
1939
|
+
var countN = (expr = sql6`*`) => sql6`count(${expr})`.mapWith(Number);
|
|
1940
|
+
var sumN = (expr) => sql6`sum(${expr})`.mapWith(Number);
|
|
1941
|
+
var avgN = (expr) => sql6`avg(${expr})`.mapWith(Number);
|
|
1942
|
+
var sumDistinctN = (expr) => sql6`sum(distinct ${expr})`.mapWith(Number);
|
|
1943
|
+
var percentileCont = (p, expr) => sql6`percentile_cont(${p}) within group (order by ${expr})`.mapWith(Number);
|
|
1944
|
+
var median = (expr) => percentileCont(0.5, expr);
|
|
1945
|
+
var anyValue = (expr) => sql6`any_value(${expr})`;
|
|
1946
|
+
function normalizeArray(value) {
|
|
1947
|
+
if (!value)
|
|
1948
|
+
return [];
|
|
1949
|
+
return Array.isArray(value) ? value : [value];
|
|
1950
|
+
}
|
|
1951
|
+
function overClause(options) {
|
|
1952
|
+
const partitions = normalizeArray(options?.partitionBy);
|
|
1953
|
+
const orders = normalizeArray(options?.orderBy);
|
|
1954
|
+
const chunks = [];
|
|
1955
|
+
if (partitions.length > 0) {
|
|
1956
|
+
chunks.push(sql6`partition by ${sql6.join(partitions, sql6`, `)}`);
|
|
1957
|
+
}
|
|
1958
|
+
if (orders.length > 0) {
|
|
1959
|
+
chunks.push(sql6`order by ${sql6.join(orders, sql6`, `)}`);
|
|
1960
|
+
}
|
|
1961
|
+
if (chunks.length === 0) {
|
|
1962
|
+
return sql6``;
|
|
1963
|
+
}
|
|
1964
|
+
return sql6`over (${sql6.join(chunks, sql6` `)})`;
|
|
1965
|
+
}
|
|
1966
|
+
var rowNumber = (options) => sql6`row_number() ${overClause(options)}`.mapWith(Number);
|
|
1967
|
+
var rank = (options) => sql6`rank() ${overClause(options)}`.mapWith(Number);
|
|
1968
|
+
var denseRank = (options) => sql6`dense_rank() ${overClause(options)}`.mapWith(Number);
|
|
1969
|
+
var lag = (expr, offset = 1, defaultValue, options) => defaultValue ? sql6`lag(${expr}, ${offset}, ${defaultValue}) ${overClause(options)}` : sql6`lag(${expr}, ${offset}) ${overClause(options)}`;
|
|
1970
|
+
var lead = (expr, offset = 1, defaultValue, options) => defaultValue ? sql6`lead(${expr}, ${offset}, ${defaultValue}) ${overClause(options)}` : sql6`lead(${expr}, ${offset}) ${overClause(options)}`;
|
|
1971
|
+
function keyAlias(key, fallback) {
|
|
1972
|
+
if (is5(key, SQL5.Aliased)) {
|
|
1973
|
+
return key.fieldAlias ?? fallback;
|
|
1974
|
+
}
|
|
1975
|
+
if (is5(key, Column3)) {
|
|
1976
|
+
return `${getTableName3(key.table)}.${key.name}`;
|
|
1977
|
+
}
|
|
1978
|
+
return fallback;
|
|
1979
|
+
}
|
|
1980
|
+
|
|
1981
|
+
class OlapBuilder {
|
|
1982
|
+
db;
|
|
1983
|
+
source;
|
|
1984
|
+
keys = [];
|
|
1985
|
+
measureMap = {};
|
|
1986
|
+
nonAggregates = {};
|
|
1987
|
+
wrapNonAggWithAnyValue = false;
|
|
1988
|
+
orderByClauses = [];
|
|
1989
|
+
constructor(db) {
|
|
1990
|
+
this.db = db;
|
|
1991
|
+
}
|
|
1992
|
+
from(source) {
|
|
1993
|
+
this.source = source;
|
|
1994
|
+
return this;
|
|
1995
|
+
}
|
|
1996
|
+
groupBy(keys) {
|
|
1997
|
+
this.keys = keys;
|
|
1998
|
+
return this;
|
|
1999
|
+
}
|
|
2000
|
+
measures(measures) {
|
|
2001
|
+
this.measureMap = measures;
|
|
2002
|
+
return this;
|
|
2003
|
+
}
|
|
2004
|
+
selectNonAggregates(fields, options = {}) {
|
|
2005
|
+
this.nonAggregates = fields;
|
|
2006
|
+
this.wrapNonAggWithAnyValue = options.anyValue ?? false;
|
|
2007
|
+
return this;
|
|
2008
|
+
}
|
|
2009
|
+
orderBy(...clauses) {
|
|
2010
|
+
this.orderByClauses = clauses;
|
|
2011
|
+
return this;
|
|
2012
|
+
}
|
|
2013
|
+
build() {
|
|
2014
|
+
if (!this.source) {
|
|
2015
|
+
throw new Error("olap: .from() is required");
|
|
2016
|
+
}
|
|
2017
|
+
if (this.keys.length === 0) {
|
|
2018
|
+
throw new Error("olap: .groupBy() is required");
|
|
2019
|
+
}
|
|
2020
|
+
if (Object.keys(this.measureMap).length === 0) {
|
|
2021
|
+
throw new Error("olap: .measures() is required");
|
|
2022
|
+
}
|
|
2023
|
+
const selection = {};
|
|
2024
|
+
this.keys.forEach((key, idx) => {
|
|
2025
|
+
const alias = keyAlias(key, `key_${idx}`);
|
|
2026
|
+
selection[alias] = key;
|
|
2027
|
+
});
|
|
2028
|
+
Object.entries(this.nonAggregates).forEach(([alias, expr]) => {
|
|
2029
|
+
selection[alias] = this.wrapNonAggWithAnyValue ? anyValue(expr) : expr;
|
|
2030
|
+
});
|
|
2031
|
+
Object.assign(selection, this.measureMap);
|
|
2032
|
+
let query = this.db.select(selection).from(this.source).groupBy(...this.keys);
|
|
2033
|
+
if (this.orderByClauses.length > 0) {
|
|
2034
|
+
query = query.orderBy(...this.orderByClauses);
|
|
2035
|
+
}
|
|
2036
|
+
return query;
|
|
2037
|
+
}
|
|
2038
|
+
run() {
|
|
2039
|
+
return this.build();
|
|
2040
|
+
}
|
|
2041
|
+
}
|
|
2042
|
+
var olap = (db) => new OlapBuilder(db);
|
|
1561
2043
|
export {
|
|
2044
|
+
wrapperToNodeApiValue,
|
|
2045
|
+
wrapTimestamp,
|
|
2046
|
+
wrapStruct,
|
|
2047
|
+
wrapMap,
|
|
2048
|
+
wrapList,
|
|
2049
|
+
wrapJson,
|
|
2050
|
+
wrapBlob,
|
|
2051
|
+
wrapArray,
|
|
2052
|
+
sumN,
|
|
2053
|
+
sumDistinctN,
|
|
2054
|
+
rowNumber,
|
|
2055
|
+
resolvePoolSize,
|
|
2056
|
+
rank,
|
|
2057
|
+
prepareParams,
|
|
2058
|
+
percentileCont,
|
|
2059
|
+
olap,
|
|
1562
2060
|
migrate,
|
|
2061
|
+
median,
|
|
2062
|
+
lead,
|
|
2063
|
+
lag,
|
|
2064
|
+
isPool,
|
|
2065
|
+
isDuckDBWrapper,
|
|
1563
2066
|
introspect,
|
|
2067
|
+
executeOnClient,
|
|
2068
|
+
executeInBatches,
|
|
2069
|
+
executeArrowOnClient,
|
|
1564
2070
|
duckDbTimestamp,
|
|
1565
2071
|
duckDbTime,
|
|
1566
2072
|
duckDbStruct,
|
|
@@ -1576,9 +2082,19 @@ export {
|
|
|
1576
2082
|
duckDbArrayContained,
|
|
1577
2083
|
duckDbArray,
|
|
1578
2084
|
drizzle,
|
|
2085
|
+
denseRank,
|
|
2086
|
+
createDuckDBConnectionPool,
|
|
2087
|
+
countN,
|
|
2088
|
+
closeClientConnection,
|
|
2089
|
+
avgN,
|
|
2090
|
+
anyValue,
|
|
2091
|
+
POOL_PRESETS,
|
|
2092
|
+
OlapBuilder,
|
|
1579
2093
|
DuckDBTransaction,
|
|
1580
2094
|
DuckDBSession,
|
|
1581
2095
|
DuckDBPreparedQuery,
|
|
1582
2096
|
DuckDBDriver,
|
|
1583
|
-
DuckDBDatabase
|
|
2097
|
+
DuckDBDatabase,
|
|
2098
|
+
DUCKDB_VALUE_MARKER,
|
|
2099
|
+
DEFAULT_IMPORT_BASE
|
|
1584
2100
|
};
|