@duckdbfan/drizzle-duckdb 0.0.7 → 1.3.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +349 -62
- package/dist/bin/duckdb-introspect.d.ts +2 -0
- package/dist/client.d.ts +42 -0
- package/dist/columns.d.ts +100 -9
- package/dist/dialect.d.ts +27 -2
- package/dist/driver.d.ts +53 -37
- package/dist/duckdb-introspect.mjs +2890 -0
- package/dist/helpers.d.ts +1 -0
- package/dist/helpers.mjs +360 -0
- package/dist/index.d.ts +7 -0
- package/dist/index.mjs +3015 -228
- package/dist/introspect.d.ts +74 -0
- package/dist/migrator.d.ts +3 -2
- package/dist/olap.d.ts +46 -0
- package/dist/operators.d.ts +8 -0
- package/dist/options.d.ts +7 -0
- package/dist/pool.d.ts +30 -0
- package/dist/select-builder.d.ts +31 -0
- package/dist/session.d.ts +33 -8
- package/dist/sql/ast-transformer.d.ts +33 -0
- package/dist/sql/result-mapper.d.ts +9 -0
- package/dist/sql/selection.d.ts +2 -0
- package/dist/sql/visitors/array-operators.d.ts +5 -0
- package/dist/sql/visitors/column-qualifier.d.ts +10 -0
- package/dist/sql/visitors/generate-series-alias.d.ts +13 -0
- package/dist/sql/visitors/union-with-hoister.d.ts +11 -0
- package/dist/utils.d.ts +2 -5
- package/dist/value-wrappers-core.d.ts +42 -0
- package/dist/value-wrappers.d.ts +8 -0
- package/package.json +53 -16
- package/src/bin/duckdb-introspect.ts +181 -0
- package/src/client.ts +528 -0
- package/src/columns.ts +420 -65
- package/src/dialect.ts +111 -15
- package/src/driver.ts +266 -180
- package/src/helpers.ts +18 -0
- package/src/index.ts +8 -1
- package/src/introspect.ts +935 -0
- package/src/migrator.ts +10 -5
- package/src/olap.ts +190 -0
- package/src/operators.ts +27 -0
- package/src/options.ts +25 -0
- package/src/pool.ts +274 -0
- package/src/select-builder.ts +110 -0
- package/src/session.ts +306 -66
- package/src/sql/ast-transformer.ts +170 -0
- package/src/sql/result-mapper.ts +303 -0
- package/src/sql/selection.ts +60 -0
- package/src/sql/visitors/array-operators.ts +214 -0
- package/src/sql/visitors/column-qualifier.ts +586 -0
- package/src/sql/visitors/generate-series-alias.ts +291 -0
- package/src/sql/visitors/union-with-hoister.ts +106 -0
- package/src/utils.ts +2 -222
- package/src/value-wrappers-core.ts +168 -0
- package/src/value-wrappers.ts +165 -0
package/src/driver.ts
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { DuckDBInstance } from '@duckdb/node-api';
|
|
2
|
+
import { entityKind } from 'drizzle-orm/entity';
|
|
2
3
|
import type { Logger } from 'drizzle-orm/logger';
|
|
3
4
|
import { DefaultLogger } from 'drizzle-orm/logger';
|
|
4
5
|
import { PgDatabase } from 'drizzle-orm/pg-core/db';
|
|
5
|
-
import {
|
|
6
|
+
import type { SelectedFields } from 'drizzle-orm/pg-core/query-builders';
|
|
7
|
+
import type { PgSession } from 'drizzle-orm/pg-core';
|
|
6
8
|
import {
|
|
7
9
|
createTableRelationsHelpers,
|
|
8
10
|
extractTablesRelationalConfig,
|
|
@@ -10,104 +12,115 @@ import {
|
|
|
10
12
|
type RelationalSchemaConfig,
|
|
11
13
|
type TablesRelationalConfig,
|
|
12
14
|
} from 'drizzle-orm/relations';
|
|
13
|
-
import {
|
|
14
|
-
|
|
15
|
-
type DrizzleConfig,
|
|
16
|
-
type DrizzleTypeError,
|
|
17
|
-
} from 'drizzle-orm/utils';
|
|
15
|
+
import { type DrizzleConfig } from 'drizzle-orm/utils';
|
|
16
|
+
import type { SQL } from 'drizzle-orm/sql/sql';
|
|
18
17
|
import type {
|
|
19
|
-
|
|
18
|
+
DuckDBClientLike,
|
|
20
19
|
DuckDBQueryResultHKT,
|
|
21
20
|
DuckDBTransaction,
|
|
22
|
-
} from './session';
|
|
21
|
+
} from './session.ts';
|
|
23
22
|
import { DuckDBSession } from './session.ts';
|
|
24
23
|
import { DuckDBDialect } from './dialect.ts';
|
|
25
|
-
|
|
24
|
+
import { DuckDBSelectBuilder } from './select-builder.ts';
|
|
25
|
+
import { aliasFields } from './sql/selection.ts';
|
|
26
|
+
import type {
|
|
27
|
+
ExecuteBatchesRawChunk,
|
|
28
|
+
ExecuteInBatchesOptions,
|
|
29
|
+
RowData,
|
|
30
|
+
} from './client.ts';
|
|
31
|
+
import { closeClientConnection, isPool } from './client.ts';
|
|
26
32
|
import {
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
type
|
|
30
|
-
type
|
|
31
|
-
|
|
32
|
-
} from 'drizzle-orm/pg-core/query-builders';
|
|
33
|
+
createDuckDBConnectionPool,
|
|
34
|
+
resolvePoolSize,
|
|
35
|
+
type DuckDBPoolConfig,
|
|
36
|
+
type PoolPreset,
|
|
37
|
+
} from './pool.ts';
|
|
33
38
|
import {
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
type
|
|
37
|
-
|
|
38
|
-
} from 'drizzle-orm/pg-core';
|
|
39
|
-
import { sql, SQL, type ColumnsSelection } from 'drizzle-orm/sql/sql';
|
|
40
|
-
import { Column } from 'drizzle-orm/column';
|
|
41
|
-
import { Subquery, ViewBaseConfig, type SQLWrapper } from 'drizzle-orm';
|
|
42
|
-
import { PgViewBase } from 'drizzle-orm/pg-core/view-base';
|
|
43
|
-
import type {
|
|
44
|
-
GetSelectTableName,
|
|
45
|
-
GetSelectTableSelection,
|
|
46
|
-
} from 'drizzle-orm/query-builders/select.types';
|
|
47
|
-
import { aliasFields } from './utils.ts';
|
|
39
|
+
resolvePrepareCacheOption,
|
|
40
|
+
type PreparedStatementCacheConfig,
|
|
41
|
+
type PrepareCacheOption,
|
|
42
|
+
} from './options.ts';
|
|
48
43
|
|
|
49
44
|
export interface PgDriverOptions {
|
|
50
45
|
logger?: Logger;
|
|
46
|
+
rejectStringArrayLiterals?: boolean;
|
|
47
|
+
prepareCache?: PreparedStatementCacheConfig;
|
|
51
48
|
}
|
|
52
49
|
|
|
53
|
-
const selectionRegex = /select\s+(.+)\s+from/i;
|
|
54
|
-
const aliasRegex = /as\s+(.+)$/i;
|
|
55
|
-
|
|
56
50
|
export class DuckDBDriver {
|
|
57
51
|
static readonly [entityKind]: string = 'DuckDBDriver';
|
|
58
52
|
|
|
59
53
|
constructor(
|
|
60
|
-
private client:
|
|
54
|
+
private client: DuckDBClientLike,
|
|
61
55
|
private dialect: DuckDBDialect,
|
|
62
56
|
private options: PgDriverOptions = {}
|
|
63
|
-
) {
|
|
64
|
-
// const clientProxy = new Proxy(client, {
|
|
65
|
-
// get(target, prop, receiver) {
|
|
66
|
-
// if (prop === 'all') {
|
|
67
|
-
// return (query: string, params: Parameters<typeof target.all>) => {
|
|
68
|
-
// // DuckDB names returned variables differently than Postgres
|
|
69
|
-
// // so we need to remap them to match the Postgres names
|
|
70
|
-
// const selection = selectionRegex.exec(query);
|
|
71
|
-
// if (selection?.length !== 2) {
|
|
72
|
-
// return target.all(query, params);
|
|
73
|
-
// }
|
|
74
|
-
// const fields = selection[1].split(',').map((field) => {});
|
|
75
|
-
// return target.all(query, params);
|
|
76
|
-
// };
|
|
77
|
-
// }
|
|
78
|
-
// return Reflect.get(target, prop, receiver);
|
|
79
|
-
// },
|
|
80
|
-
// });
|
|
81
|
-
}
|
|
57
|
+
) {}
|
|
82
58
|
|
|
83
59
|
createSession(
|
|
84
60
|
schema: RelationalSchemaConfig<TablesRelationalConfig> | undefined
|
|
85
61
|
): DuckDBSession<Record<string, unknown>, TablesRelationalConfig> {
|
|
86
62
|
return new DuckDBSession(this.client, this.dialect, schema, {
|
|
87
63
|
logger: this.options.logger,
|
|
64
|
+
rejectStringArrayLiterals: this.options.rejectStringArrayLiterals,
|
|
65
|
+
prepareCache: this.options.prepareCache,
|
|
88
66
|
});
|
|
89
67
|
}
|
|
90
68
|
}
|
|
91
69
|
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
70
|
+
/** Connection configuration when using path-based connection */
|
|
71
|
+
export interface DuckDBConnectionConfig {
|
|
72
|
+
/** Database path: ':memory:', './file.duckdb', 'md:', 'md:database' */
|
|
73
|
+
path: string;
|
|
74
|
+
/** DuckDB instance options (e.g., motherduck_token) */
|
|
75
|
+
options?: Record<string, string>;
|
|
76
|
+
}
|
|
99
77
|
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
78
|
+
export interface DuckDBDrizzleConfig<
|
|
79
|
+
TSchema extends Record<string, unknown> = Record<string, never>,
|
|
80
|
+
> extends DrizzleConfig<TSchema> {
|
|
81
|
+
rejectStringArrayLiterals?: boolean;
|
|
82
|
+
prepareCache?: PrepareCacheOption;
|
|
83
|
+
/** Pool configuration. Use preset name, size config, or false to disable. */
|
|
84
|
+
pool?: DuckDBPoolConfig | PoolPreset | false;
|
|
85
|
+
}
|
|
103
86
|
|
|
104
|
-
export
|
|
105
|
-
TSchema extends Record<string, unknown> = Record<string, never
|
|
87
|
+
export interface DuckDBDrizzleConfigWithConnection<
|
|
88
|
+
TSchema extends Record<string, unknown> = Record<string, never>,
|
|
89
|
+
> extends DuckDBDrizzleConfig<TSchema> {
|
|
90
|
+
/** Connection string or config object */
|
|
91
|
+
connection: string | DuckDBConnectionConfig;
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
export interface DuckDBDrizzleConfigWithClient<
|
|
95
|
+
TSchema extends Record<string, unknown> = Record<string, never>,
|
|
96
|
+
> extends DuckDBDrizzleConfig<TSchema> {
|
|
97
|
+
/** Explicit client (connection or pool) */
|
|
98
|
+
client: DuckDBClientLike;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
/** Check if a value looks like a config object (not a client) */
|
|
102
|
+
function isConfigObject(data: unknown): data is Record<string, unknown> {
|
|
103
|
+
if (typeof data !== 'object' || data === null) return false;
|
|
104
|
+
if (data.constructor?.name !== 'Object') return false;
|
|
105
|
+
return (
|
|
106
|
+
'connection' in data ||
|
|
107
|
+
'client' in data ||
|
|
108
|
+
'pool' in data ||
|
|
109
|
+
'schema' in data ||
|
|
110
|
+
'logger' in data
|
|
111
|
+
);
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/** Internal: create database from a client (connection or pool) */
|
|
115
|
+
function createFromClient<
|
|
116
|
+
TSchema extends Record<string, unknown> = Record<string, never>,
|
|
106
117
|
>(
|
|
107
|
-
client:
|
|
108
|
-
config:
|
|
118
|
+
client: DuckDBClientLike,
|
|
119
|
+
config: DuckDBDrizzleConfig<TSchema> = {},
|
|
120
|
+
instance?: DuckDBInstance
|
|
109
121
|
): DuckDBDatabase<TSchema, ExtractTablesWithRelations<TSchema>> {
|
|
110
122
|
const dialect = new DuckDBDialect();
|
|
123
|
+
const prepareCache = resolvePrepareCacheOption(config.prepareCache);
|
|
111
124
|
|
|
112
125
|
const logger =
|
|
113
126
|
config.logger === true ? new DefaultLogger() : config.logger || undefined;
|
|
@@ -126,148 +139,221 @@ export function drizzle<
|
|
|
126
139
|
};
|
|
127
140
|
}
|
|
128
141
|
|
|
129
|
-
const driver = new DuckDBDriver(client, dialect, {
|
|
142
|
+
const driver = new DuckDBDriver(client, dialect, {
|
|
143
|
+
logger,
|
|
144
|
+
rejectStringArrayLiterals: config.rejectStringArrayLiterals,
|
|
145
|
+
prepareCache,
|
|
146
|
+
});
|
|
130
147
|
const session = driver.createSession(schema);
|
|
131
148
|
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
149
|
+
const db = new DuckDBDatabase(dialect, session, schema, client, instance);
|
|
150
|
+
return db as DuckDBDatabase<TSchema, ExtractTablesWithRelations<TSchema>>;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/** Internal: create database from a connection string */
|
|
154
|
+
async function createFromConnectionString<
|
|
155
|
+
TSchema extends Record<string, unknown> = Record<string, never>,
|
|
156
|
+
>(
|
|
157
|
+
path: string,
|
|
158
|
+
instanceOptions: Record<string, string> | undefined,
|
|
159
|
+
config: DuckDBDrizzleConfig<TSchema> = {}
|
|
160
|
+
): Promise<DuckDBDatabase<TSchema, ExtractTablesWithRelations<TSchema>>> {
|
|
161
|
+
const instance = await DuckDBInstance.create(path, instanceOptions);
|
|
162
|
+
const poolSize = resolvePoolSize(config.pool);
|
|
163
|
+
|
|
164
|
+
if (poolSize === false) {
|
|
165
|
+
const connection = await instance.connect();
|
|
166
|
+
return createFromClient(connection, config, instance);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
const pool = createDuckDBConnectionPool(instance, { size: poolSize });
|
|
170
|
+
return createFromClient(pool, config, instance);
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// Overload 1: Connection string (async, auto-pools)
|
|
174
|
+
export function drizzle<
|
|
175
|
+
TSchema extends Record<string, unknown> = Record<string, never>,
|
|
176
|
+
>(
|
|
177
|
+
connectionString: string
|
|
178
|
+
): Promise<DuckDBDatabase<TSchema, ExtractTablesWithRelations<TSchema>>>;
|
|
179
|
+
|
|
180
|
+
// Overload 2: Connection string + config (async, auto-pools)
|
|
181
|
+
export function drizzle<
|
|
182
|
+
TSchema extends Record<string, unknown> = Record<string, never>,
|
|
183
|
+
>(
|
|
184
|
+
connectionString: string,
|
|
185
|
+
config: DuckDBDrizzleConfig<TSchema>
|
|
186
|
+
): Promise<DuckDBDatabase<TSchema, ExtractTablesWithRelations<TSchema>>>;
|
|
187
|
+
|
|
188
|
+
// Overload 3: Config with connection (async, auto-pools)
|
|
189
|
+
export function drizzle<
|
|
190
|
+
TSchema extends Record<string, unknown> = Record<string, never>,
|
|
191
|
+
>(
|
|
192
|
+
config: DuckDBDrizzleConfigWithConnection<TSchema>
|
|
193
|
+
): Promise<DuckDBDatabase<TSchema, ExtractTablesWithRelations<TSchema>>>;
|
|
194
|
+
|
|
195
|
+
// Overload 4: Config with explicit client (sync)
|
|
196
|
+
export function drizzle<
|
|
197
|
+
TSchema extends Record<string, unknown> = Record<string, never>,
|
|
198
|
+
>(
|
|
199
|
+
config: DuckDBDrizzleConfigWithClient<TSchema>
|
|
200
|
+
): DuckDBDatabase<TSchema, ExtractTablesWithRelations<TSchema>>;
|
|
201
|
+
|
|
202
|
+
// Overload 5: Explicit client (sync, backward compatible)
|
|
203
|
+
export function drizzle<
|
|
204
|
+
TSchema extends Record<string, unknown> = Record<string, never>,
|
|
205
|
+
>(
|
|
206
|
+
client: DuckDBClientLike,
|
|
207
|
+
config?: DuckDBDrizzleConfig<TSchema>
|
|
208
|
+
): DuckDBDatabase<TSchema, ExtractTablesWithRelations<TSchema>>;
|
|
209
|
+
|
|
210
|
+
// Implementation
|
|
211
|
+
export function drizzle<
|
|
212
|
+
TSchema extends Record<string, unknown> = Record<string, never>,
|
|
213
|
+
>(
|
|
214
|
+
clientOrConfigOrPath:
|
|
215
|
+
| string
|
|
216
|
+
| DuckDBClientLike
|
|
217
|
+
| DuckDBDrizzleConfigWithConnection<TSchema>
|
|
218
|
+
| DuckDBDrizzleConfigWithClient<TSchema>,
|
|
219
|
+
config?: DuckDBDrizzleConfig<TSchema>
|
|
220
|
+
):
|
|
221
|
+
| DuckDBDatabase<TSchema, ExtractTablesWithRelations<TSchema>>
|
|
222
|
+
| Promise<DuckDBDatabase<TSchema, ExtractTablesWithRelations<TSchema>>> {
|
|
223
|
+
// String path -> async with auto-pool
|
|
224
|
+
if (typeof clientOrConfigOrPath === 'string') {
|
|
225
|
+
return createFromConnectionString(clientOrConfigOrPath, undefined, config);
|
|
226
|
+
}
|
|
227
|
+
|
|
228
|
+
// Config object with connection or client
|
|
229
|
+
if (isConfigObject(clientOrConfigOrPath)) {
|
|
230
|
+
const configObj = clientOrConfigOrPath as
|
|
231
|
+
| DuckDBDrizzleConfigWithConnection<TSchema>
|
|
232
|
+
| DuckDBDrizzleConfigWithClient<TSchema>;
|
|
233
|
+
|
|
234
|
+
if ('connection' in configObj) {
|
|
235
|
+
const connConfig =
|
|
236
|
+
configObj as DuckDBDrizzleConfigWithConnection<TSchema>;
|
|
237
|
+
const { connection, ...restConfig } = connConfig;
|
|
238
|
+
if (typeof connection === 'string') {
|
|
239
|
+
return createFromConnectionString(
|
|
240
|
+
connection,
|
|
241
|
+
undefined,
|
|
242
|
+
restConfig as DuckDBDrizzleConfig<TSchema>
|
|
243
|
+
);
|
|
244
|
+
}
|
|
245
|
+
return createFromConnectionString(
|
|
246
|
+
connection.path,
|
|
247
|
+
connection.options,
|
|
248
|
+
restConfig as DuckDBDrizzleConfig<TSchema>
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
|
|
252
|
+
if ('client' in configObj) {
|
|
253
|
+
const clientConfig = configObj as DuckDBDrizzleConfigWithClient<TSchema>;
|
|
254
|
+
const { client: clientValue, ...restConfig } = clientConfig;
|
|
255
|
+
return createFromClient(
|
|
256
|
+
clientValue,
|
|
257
|
+
restConfig as DuckDBDrizzleConfig<TSchema>
|
|
258
|
+
);
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
throw new Error(
|
|
262
|
+
'Invalid drizzle config: either connection or client must be provided'
|
|
263
|
+
);
|
|
264
|
+
}
|
|
265
|
+
|
|
266
|
+
// Direct client (backward compatible)
|
|
267
|
+
return createFromClient(clientOrConfigOrPath as DuckDBClientLike, config);
|
|
136
268
|
}
|
|
137
269
|
|
|
138
270
|
export class DuckDBDatabase<
|
|
139
271
|
TFullSchema extends Record<string, unknown> = Record<string, never>,
|
|
140
|
-
TSchema extends TablesRelationalConfig =
|
|
272
|
+
TSchema extends TablesRelationalConfig =
|
|
273
|
+
ExtractTablesWithRelations<TFullSchema>,
|
|
141
274
|
> extends PgDatabase<DuckDBQueryResultHKT, TFullSchema, TSchema> {
|
|
142
275
|
static readonly [entityKind]: string = 'DuckDBDatabase';
|
|
143
276
|
|
|
277
|
+
/** The underlying connection or pool */
|
|
278
|
+
readonly $client: DuckDBClientLike;
|
|
279
|
+
|
|
280
|
+
/** The DuckDB instance (when created from connection string) */
|
|
281
|
+
readonly $instance?: DuckDBInstance;
|
|
282
|
+
|
|
144
283
|
constructor(
|
|
145
284
|
readonly dialect: DuckDBDialect,
|
|
146
285
|
readonly session: DuckDBSession<TFullSchema, TSchema>,
|
|
147
|
-
schema: RelationalSchemaConfig<TSchema> | undefined
|
|
286
|
+
schema: RelationalSchemaConfig<TSchema> | undefined,
|
|
287
|
+
client: DuckDBClientLike,
|
|
288
|
+
instance?: DuckDBInstance
|
|
148
289
|
) {
|
|
149
290
|
super(dialect, session, schema);
|
|
291
|
+
this.$client = client;
|
|
292
|
+
this.$instance = instance;
|
|
150
293
|
}
|
|
151
294
|
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
if (
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
295
|
+
/**
|
|
296
|
+
* Close the database connection pool and instance.
|
|
297
|
+
* Should be called when shutting down the application.
|
|
298
|
+
*/
|
|
299
|
+
async close(): Promise<void> {
|
|
300
|
+
if (isPool(this.$client) && this.$client.close) {
|
|
301
|
+
await this.$client.close();
|
|
302
|
+
}
|
|
303
|
+
if (!isPool(this.$client)) {
|
|
304
|
+
await closeClientConnection(this.$client);
|
|
305
|
+
}
|
|
306
|
+
if (this.$instance) {
|
|
307
|
+
const maybeClosable = this.$instance as unknown as {
|
|
308
|
+
close?: () => Promise<void> | void;
|
|
309
|
+
closeSync?: () => void;
|
|
310
|
+
};
|
|
311
|
+
if (typeof maybeClosable.close === 'function') {
|
|
312
|
+
await maybeClosable.close();
|
|
313
|
+
} else if (typeof maybeClosable.closeSync === 'function') {
|
|
314
|
+
maybeClosable.closeSync();
|
|
315
|
+
}
|
|
165
316
|
}
|
|
317
|
+
}
|
|
166
318
|
|
|
167
|
-
|
|
319
|
+
select(): DuckDBSelectBuilder<undefined>;
|
|
320
|
+
select<TSelection extends SelectedFields>(
|
|
321
|
+
fields: TSelection
|
|
322
|
+
): DuckDBSelectBuilder<TSelection>;
|
|
323
|
+
select(
|
|
324
|
+
fields?: SelectedFields
|
|
325
|
+
): DuckDBSelectBuilder<SelectedFields | undefined> {
|
|
326
|
+
const selectedFields = fields ? aliasFields(fields) : undefined;
|
|
168
327
|
|
|
328
|
+
// Cast needed: DuckDBSession is compatible but types don't align exactly with PgSession
|
|
169
329
|
return new DuckDBSelectBuilder({
|
|
170
|
-
fields:
|
|
330
|
+
fields: selectedFields ?? undefined,
|
|
171
331
|
session: this.session as unknown as PgSession<DuckDBQueryResultHKT>,
|
|
172
332
|
dialect: this.dialect,
|
|
173
333
|
});
|
|
174
334
|
}
|
|
175
335
|
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
336
|
+
executeBatches<T extends RowData = RowData>(
|
|
337
|
+
query: SQL,
|
|
338
|
+
options: ExecuteInBatchesOptions = {}
|
|
339
|
+
): AsyncGenerator<T[], void, void> {
|
|
340
|
+
return this.session.executeBatches<T>(query, options);
|
|
180
341
|
}
|
|
181
|
-
}
|
|
182
|
-
|
|
183
|
-
interface PgViewBaseInternal<
|
|
184
|
-
TName extends string = string,
|
|
185
|
-
TExisting extends boolean = boolean,
|
|
186
|
-
TSelectedFields extends ColumnsSelection = ColumnsSelection
|
|
187
|
-
> extends PgViewBase<TName, TExisting, TSelectedFields> {
|
|
188
|
-
[ViewBaseConfig]?: {
|
|
189
|
-
selectedFields: SelectedFields;
|
|
190
|
-
};
|
|
191
|
-
}
|
|
192
342
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
private _session: PgSession | undefined;
|
|
199
|
-
private _dialect: DuckDBDialect;
|
|
200
|
-
private _withList: Subquery[] = [];
|
|
201
|
-
private _distinct:
|
|
202
|
-
| boolean
|
|
203
|
-
| {
|
|
204
|
-
on: (PgColumn | SQLWrapper)[];
|
|
205
|
-
}
|
|
206
|
-
| undefined;
|
|
207
|
-
|
|
208
|
-
constructor(config: {
|
|
209
|
-
fields: TSelection;
|
|
210
|
-
session: PgSession | undefined;
|
|
211
|
-
dialect: PgDialect;
|
|
212
|
-
withList?: Subquery[];
|
|
213
|
-
distinct?:
|
|
214
|
-
| boolean
|
|
215
|
-
| {
|
|
216
|
-
on: (PgColumn | SQLWrapper)[];
|
|
217
|
-
};
|
|
218
|
-
}) {
|
|
219
|
-
super(config);
|
|
220
|
-
this._fields = config.fields;
|
|
221
|
-
this._session = config.session;
|
|
222
|
-
this._dialect = config.dialect;
|
|
223
|
-
if (config.withList) {
|
|
224
|
-
this._withList = config.withList;
|
|
225
|
-
}
|
|
226
|
-
this._distinct = config.distinct;
|
|
343
|
+
executeBatchesRaw(
|
|
344
|
+
query: SQL,
|
|
345
|
+
options: ExecuteInBatchesOptions = {}
|
|
346
|
+
): AsyncGenerator<ExecuteBatchesRawChunk, void, void> {
|
|
347
|
+
return this.session.executeBatchesRaw(query, options);
|
|
227
348
|
}
|
|
228
349
|
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
: TFrom
|
|
233
|
-
): CreatePgSelectFromBuilderMode<
|
|
234
|
-
TBuilderMode,
|
|
235
|
-
GetSelectTableName<TFrom>,
|
|
236
|
-
TSelection extends undefined ? GetSelectTableSelection<TFrom> : TSelection,
|
|
237
|
-
TSelection extends undefined ? 'single' : 'partial'
|
|
238
|
-
> {
|
|
239
|
-
const isPartialSelect = !!this._fields;
|
|
240
|
-
const src = source as TFrom;
|
|
241
|
-
|
|
242
|
-
let fields: SelectedFields;
|
|
243
|
-
if (this._fields) {
|
|
244
|
-
fields = this._fields;
|
|
245
|
-
} else if (is(src, Subquery)) {
|
|
246
|
-
// This is required to use the proxy handler to get the correct field values from the subquery
|
|
247
|
-
fields = Object.fromEntries(
|
|
248
|
-
Object.keys(src._.selectedFields).map((key) => [
|
|
249
|
-
key,
|
|
250
|
-
src[
|
|
251
|
-
key as unknown as keyof typeof src
|
|
252
|
-
] as unknown as SelectedFields[string],
|
|
253
|
-
])
|
|
254
|
-
);
|
|
255
|
-
} else if (is(src, PgViewBase)) {
|
|
256
|
-
fields = src[ViewBaseConfig]?.selectedFields as SelectedFields;
|
|
257
|
-
} else if (is(src, SQL)) {
|
|
258
|
-
fields = {};
|
|
259
|
-
} else {
|
|
260
|
-
fields = aliasFields(getTableColumns<PgTable>(src), !isPartialSelect);
|
|
261
|
-
}
|
|
350
|
+
executeArrow(query: SQL): Promise<unknown> {
|
|
351
|
+
return this.session.executeArrow(query);
|
|
352
|
+
}
|
|
262
353
|
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
session: this._session,
|
|
268
|
-
dialect: this._dialect,
|
|
269
|
-
withList: this._withList,
|
|
270
|
-
distinct: this._distinct,
|
|
271
|
-
}) as any;
|
|
354
|
+
override async transaction<T>(
|
|
355
|
+
transaction: (tx: DuckDBTransaction<TFullSchema, TSchema>) => Promise<T>
|
|
356
|
+
): Promise<T> {
|
|
357
|
+
return await this.session.transaction<T>(transaction);
|
|
272
358
|
}
|
|
273
359
|
}
|
package/src/helpers.ts
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
// Client-safe entrypoint exposing schema builder utilities without pulling
|
|
2
|
+
// the DuckDB Node API bindings. Intended for generated schemas and browser use.
|
|
3
|
+
export {
|
|
4
|
+
duckDbList,
|
|
5
|
+
duckDbArray,
|
|
6
|
+
duckDbMap,
|
|
7
|
+
duckDbStruct,
|
|
8
|
+
duckDbJson,
|
|
9
|
+
duckDbBlob,
|
|
10
|
+
duckDbInet,
|
|
11
|
+
duckDbInterval,
|
|
12
|
+
duckDbTimestamp,
|
|
13
|
+
duckDbDate,
|
|
14
|
+
duckDbTime,
|
|
15
|
+
duckDbArrayContains,
|
|
16
|
+
duckDbArrayContained,
|
|
17
|
+
duckDbArrayOverlaps,
|
|
18
|
+
} from './columns.ts';
|
package/src/index.ts
CHANGED
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
export * from './driver.ts';
|
|
2
2
|
export * from './session.ts';
|
|
3
3
|
export * from './columns.ts';
|
|
4
|
-
export * from './migrator.ts';
|
|
4
|
+
export * from './migrator.ts';
|
|
5
|
+
export * from './introspect.ts';
|
|
6
|
+
export * from './client.ts';
|
|
7
|
+
export * from './pool.ts';
|
|
8
|
+
export * from './olap.ts';
|
|
9
|
+
export * from './value-wrappers.ts';
|
|
10
|
+
export * from './options.ts';
|
|
11
|
+
export * from './operators.ts';
|