@leonardovida-md/drizzle-neo-duckdb 1.0.3 → 1.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +20 -5
- package/dist/client.d.ts +7 -1
- package/dist/columns.d.ts +6 -1
- package/dist/dialect.d.ts +21 -0
- package/dist/driver.d.ts +33 -1
- package/dist/duckdb-introspect.mjs +610 -114
- package/dist/helpers.d.ts +1 -0
- package/dist/helpers.mjs +319 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.mjs +603 -117
- package/dist/introspect.d.ts +9 -0
- package/dist/pool.d.ts +30 -0
- package/dist/session.d.ts +7 -1
- package/dist/sql/query-rewriters.d.ts +1 -1
- package/dist/sql/result-mapper.d.ts +7 -0
- package/dist/utils.d.ts +1 -1
- package/dist/value-wrappers-core.d.ts +42 -0
- package/dist/value-wrappers.d.ts +2 -98
- package/package.json +6 -2
- package/src/bin/duckdb-introspect.ts +27 -0
- package/src/client.ts +54 -13
- package/src/columns.ts +10 -10
- package/src/dialect.ts +51 -3
- package/src/driver.ts +204 -7
- package/src/helpers.ts +18 -0
- package/src/index.ts +1 -0
- package/src/introspect.ts +47 -29
- package/src/migrator.ts +1 -1
- package/src/olap.ts +1 -0
- package/src/pool.ts +274 -0
- package/src/session.ts +134 -15
- package/src/sql/query-rewriters.ts +177 -116
- package/src/sql/result-mapper.ts +7 -7
- package/src/utils.ts +1 -1
- package/src/value-wrappers-core.ts +156 -0
- package/src/value-wrappers.ts +60 -219
|
@@ -1,144 +1,205 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
1
|
+
type ArrayOperator = {
|
|
2
|
+
token: '@>' | '<@' | '&&';
|
|
3
|
+
fn: 'array_has_all' | 'array_has_any';
|
|
4
|
+
swap?: boolean;
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
const OPERATORS: ArrayOperator[] = [
|
|
8
|
+
{ token: '@>', fn: 'array_has_all' },
|
|
9
|
+
{ token: '<@', fn: 'array_has_all', swap: true },
|
|
10
|
+
{ token: '&&', fn: 'array_has_any' },
|
|
11
|
+
];
|
|
12
|
+
|
|
13
|
+
const isWhitespace = (char: string | undefined) =>
|
|
14
|
+
char !== undefined && /\s/.test(char);
|
|
15
|
+
|
|
16
|
+
export function scrubForRewrite(query: string): string {
|
|
17
|
+
let scrubbed = '';
|
|
18
|
+
type State = 'code' | 'single' | 'double' | 'lineComment' | 'blockComment';
|
|
19
|
+
let state: State = 'code';
|
|
20
|
+
|
|
21
|
+
for (let i = 0; i < query.length; i += 1) {
|
|
22
|
+
const char = query[i]!;
|
|
23
|
+
const next = query[i + 1];
|
|
24
|
+
|
|
25
|
+
if (state === 'code') {
|
|
26
|
+
if (char === "'") {
|
|
27
|
+
scrubbed += "'";
|
|
28
|
+
state = 'single';
|
|
29
|
+
continue;
|
|
30
|
+
}
|
|
31
|
+
if (char === '"') {
|
|
32
|
+
scrubbed += '"';
|
|
33
|
+
state = 'double';
|
|
34
|
+
continue;
|
|
35
|
+
}
|
|
36
|
+
if (char === '-' && next === '-') {
|
|
37
|
+
scrubbed += ' ';
|
|
38
|
+
i += 1;
|
|
39
|
+
state = 'lineComment';
|
|
40
|
+
continue;
|
|
41
|
+
}
|
|
42
|
+
if (char === '/' && next === '*') {
|
|
43
|
+
scrubbed += ' ';
|
|
44
|
+
i += 1;
|
|
45
|
+
state = 'blockComment';
|
|
46
|
+
continue;
|
|
47
|
+
}
|
|
10
48
|
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
token: '@>' | '<@' | '&&';
|
|
14
|
-
fn: 'array_has_all' | 'array_has_any';
|
|
15
|
-
swap?: boolean;
|
|
16
|
-
};
|
|
17
|
-
|
|
18
|
-
const operators: ArrayOperator[] = [
|
|
19
|
-
{ token: '@>', fn: 'array_has_all' },
|
|
20
|
-
{ token: '<@', fn: 'array_has_all', swap: true },
|
|
21
|
-
{ token: '&&', fn: 'array_has_any' },
|
|
22
|
-
];
|
|
23
|
-
|
|
24
|
-
const isWhitespace = (char: string | undefined) =>
|
|
25
|
-
char !== undefined && /\s/.test(char);
|
|
26
|
-
|
|
27
|
-
const walkLeft = (source: string, start: number): [number, string] => {
|
|
28
|
-
let idx = start;
|
|
29
|
-
while (idx >= 0 && isWhitespace(source[idx])) {
|
|
30
|
-
idx--;
|
|
49
|
+
scrubbed += char;
|
|
50
|
+
continue;
|
|
31
51
|
}
|
|
32
52
|
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
inString = !inString;
|
|
53
|
+
if (state === 'single') {
|
|
54
|
+
if (char === "'" && next === "'") {
|
|
55
|
+
scrubbed += "''";
|
|
56
|
+
i += 1;
|
|
57
|
+
continue;
|
|
39
58
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
if (depth < 0) {
|
|
46
|
-
return [idx + 1, source.slice(idx + 1, start + 1)];
|
|
47
|
-
}
|
|
48
|
-
} else if (depth === 0 && isWhitespace(ch)) {
|
|
49
|
-
return [idx + 1, source.slice(idx + 1, start + 1)];
|
|
59
|
+
// Preserve quote for boundary detection but mask inner chars with a
|
|
60
|
+
// non-whitespace placeholder to avoid false positives on operators.
|
|
61
|
+
scrubbed += char === "'" ? "'" : '.';
|
|
62
|
+
if (char === "'") {
|
|
63
|
+
state = 'code';
|
|
50
64
|
}
|
|
65
|
+
continue;
|
|
51
66
|
}
|
|
52
|
-
return [0, source.slice(0, start + 1)];
|
|
53
|
-
};
|
|
54
67
|
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
68
|
+
if (state === 'double') {
|
|
69
|
+
if (char === '"' && next === '"') {
|
|
70
|
+
scrubbed += '""';
|
|
71
|
+
i += 1;
|
|
72
|
+
continue;
|
|
73
|
+
}
|
|
74
|
+
scrubbed += char === '"' ? '"' : '.';
|
|
75
|
+
if (char === '"') {
|
|
76
|
+
state = 'code';
|
|
77
|
+
}
|
|
78
|
+
continue;
|
|
59
79
|
}
|
|
60
80
|
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
if (ch === "'" && source[idx - 1] !== '\\') {
|
|
66
|
-
inString = !inString;
|
|
67
|
-
}
|
|
68
|
-
if (inString) continue;
|
|
69
|
-
if (ch === '(' || ch === '[') {
|
|
70
|
-
depth++;
|
|
71
|
-
} else if (ch === ')' || ch === ']') {
|
|
72
|
-
depth--;
|
|
73
|
-
if (depth < 0) {
|
|
74
|
-
return [idx, source.slice(start, idx)];
|
|
75
|
-
}
|
|
76
|
-
} else if (depth === 0 && isWhitespace(ch)) {
|
|
77
|
-
return [idx, source.slice(start, idx)];
|
|
81
|
+
if (state === 'lineComment') {
|
|
82
|
+
scrubbed += char === '\n' ? '\n' : ' ';
|
|
83
|
+
if (char === '\n') {
|
|
84
|
+
state = 'code';
|
|
78
85
|
}
|
|
86
|
+
continue;
|
|
79
87
|
}
|
|
80
|
-
return [source.length, source.slice(start)];
|
|
81
|
-
};
|
|
82
88
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
+
if (state === 'blockComment') {
|
|
90
|
+
if (char === '*' && next === '/') {
|
|
91
|
+
scrubbed += ' ';
|
|
92
|
+
i += 1;
|
|
93
|
+
state = 'code';
|
|
94
|
+
} else {
|
|
95
|
+
scrubbed += ' ';
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
89
99
|
|
|
90
|
-
|
|
91
|
-
|
|
100
|
+
return scrubbed;
|
|
101
|
+
}
|
|
92
102
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
103
|
+
function findNextOperator(
|
|
104
|
+
scrubbed: string,
|
|
105
|
+
start: number
|
|
106
|
+
): { index: number; operator: ArrayOperator } | null {
|
|
107
|
+
for (let idx = start; idx < scrubbed.length; idx += 1) {
|
|
108
|
+
for (const operator of OPERATORS) {
|
|
109
|
+
if (scrubbed.startsWith(operator.token, idx)) {
|
|
110
|
+
return { index: idx, operator };
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
return null;
|
|
115
|
+
}
|
|
96
116
|
|
|
97
|
-
|
|
98
|
-
|
|
117
|
+
function walkLeft(
|
|
118
|
+
source: string,
|
|
119
|
+
scrubbed: string,
|
|
120
|
+
start: number
|
|
121
|
+
): [number, string] {
|
|
122
|
+
let idx = start;
|
|
123
|
+
while (idx >= 0 && isWhitespace(scrubbed[idx])) {
|
|
124
|
+
idx -= 1;
|
|
125
|
+
}
|
|
99
126
|
|
|
100
|
-
|
|
127
|
+
let depth = 0;
|
|
128
|
+
for (; idx >= 0; idx -= 1) {
|
|
129
|
+
const ch = scrubbed[idx];
|
|
130
|
+
if (ch === ')' || ch === ']') {
|
|
131
|
+
depth += 1;
|
|
132
|
+
} else if (ch === '(' || ch === '[') {
|
|
133
|
+
if (depth === 0) {
|
|
134
|
+
return [idx + 1, source.slice(idx + 1, start + 1)];
|
|
135
|
+
}
|
|
136
|
+
depth = Math.max(0, depth - 1);
|
|
137
|
+
} else if (depth === 0 && isWhitespace(ch)) {
|
|
138
|
+
return [idx + 1, source.slice(idx + 1, start + 1)];
|
|
101
139
|
}
|
|
102
140
|
}
|
|
103
141
|
|
|
104
|
-
return
|
|
142
|
+
return [0, source.slice(0, start + 1)];
|
|
105
143
|
}
|
|
106
144
|
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
145
|
+
function walkRight(
|
|
146
|
+
source: string,
|
|
147
|
+
scrubbed: string,
|
|
148
|
+
start: number
|
|
149
|
+
): [number, string] {
|
|
150
|
+
let idx = start;
|
|
151
|
+
while (idx < scrubbed.length && isWhitespace(scrubbed[idx])) {
|
|
152
|
+
idx += 1;
|
|
112
153
|
}
|
|
113
154
|
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
const asAlias = `'${aliasTable ?? table}.${aliasColumn ?? column}'`;
|
|
124
|
-
if (tableProp[4]) {
|
|
125
|
-
return trimmedField.replace(tableProp[4], ` as ${asAlias}`);
|
|
126
|
-
}
|
|
127
|
-
return `${identifier} as ${asAlias}`;
|
|
155
|
+
let depth = 0;
|
|
156
|
+
for (; idx < scrubbed.length; idx += 1) {
|
|
157
|
+
const ch = scrubbed[idx];
|
|
158
|
+
if (ch === '(' || ch === '[') {
|
|
159
|
+
depth += 1;
|
|
160
|
+
} else if (ch === ')' || ch === ']') {
|
|
161
|
+
if (depth === 0) {
|
|
162
|
+
return [idx, source.slice(start, idx)];
|
|
128
163
|
}
|
|
164
|
+
depth = Math.max(0, depth - 1);
|
|
165
|
+
} else if (depth === 0 && isWhitespace(ch)) {
|
|
166
|
+
return [idx, source.slice(start, idx)];
|
|
167
|
+
}
|
|
168
|
+
}
|
|
129
169
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
const [, column, alias] = noTableProp;
|
|
133
|
-
const asAlias = ` as '${column}'`;
|
|
134
|
-
return alias
|
|
135
|
-
? trimmedField.replace(alias, asAlias)
|
|
136
|
-
: `${trimmedField}${asAlias}`;
|
|
137
|
-
}
|
|
170
|
+
return [scrubbed.length, source.slice(start)];
|
|
171
|
+
}
|
|
138
172
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
173
|
+
export function adaptArrayOperators(query: string): string {
|
|
174
|
+
let rewritten = query;
|
|
175
|
+
let scrubbed = scrubForRewrite(query);
|
|
176
|
+
let searchStart = 0;
|
|
177
|
+
|
|
178
|
+
// Re-run after each replacement to keep indexes aligned with the current string
|
|
179
|
+
while (true) {
|
|
180
|
+
const next = findNextOperator(scrubbed, searchStart);
|
|
181
|
+
if (!next) break;
|
|
182
|
+
|
|
183
|
+
const { index, operator } = next;
|
|
184
|
+
const [leftStart, leftExpr] = walkLeft(rewritten, scrubbed, index - 1);
|
|
185
|
+
const [rightEnd, rightExpr] = walkRight(
|
|
186
|
+
rewritten,
|
|
187
|
+
scrubbed,
|
|
188
|
+
index + operator.token.length
|
|
189
|
+
);
|
|
190
|
+
|
|
191
|
+
const left = leftExpr.trim();
|
|
192
|
+
const right = rightExpr.trim();
|
|
193
|
+
|
|
194
|
+
const replacement = `${operator.fn}(${operator.swap ? right : left}, ${
|
|
195
|
+
operator.swap ? left : right
|
|
196
|
+
})`;
|
|
197
|
+
|
|
198
|
+
rewritten =
|
|
199
|
+
rewritten.slice(0, leftStart) + replacement + rewritten.slice(rightEnd);
|
|
200
|
+
scrubbed = scrubForRewrite(rewritten);
|
|
201
|
+
searchStart = leftStart + replacement.length;
|
|
202
|
+
}
|
|
142
203
|
|
|
143
|
-
return
|
|
204
|
+
return rewritten;
|
|
144
205
|
}
|
package/src/sql/result-mapper.ts
CHANGED
|
@@ -32,7 +32,7 @@ function toDecoderInput<TDecoder extends DriverValueDecoder<unknown, unknown>>(
|
|
|
32
32
|
return value as DecoderInput<TDecoder>;
|
|
33
33
|
}
|
|
34
34
|
|
|
35
|
-
function normalizeInet(value: unknown): unknown {
|
|
35
|
+
export function normalizeInet(value: unknown): unknown {
|
|
36
36
|
if (
|
|
37
37
|
value &&
|
|
38
38
|
typeof value === 'object' &&
|
|
@@ -70,7 +70,7 @@ function normalizeInet(value: unknown): unknown {
|
|
|
70
70
|
return value;
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
function normalizeTimestampString(
|
|
73
|
+
export function normalizeTimestampString(
|
|
74
74
|
value: unknown,
|
|
75
75
|
withTimezone: boolean
|
|
76
76
|
): string | unknown {
|
|
@@ -88,7 +88,7 @@ function normalizeTimestampString(
|
|
|
88
88
|
return value;
|
|
89
89
|
}
|
|
90
90
|
|
|
91
|
-
function normalizeTimestamp(
|
|
91
|
+
export function normalizeTimestamp(
|
|
92
92
|
value: unknown,
|
|
93
93
|
withTimezone: boolean
|
|
94
94
|
): Date | unknown {
|
|
@@ -105,7 +105,7 @@ function normalizeTimestamp(
|
|
|
105
105
|
return value;
|
|
106
106
|
}
|
|
107
107
|
|
|
108
|
-
function normalizeDateString(value: unknown): string | unknown {
|
|
108
|
+
export function normalizeDateString(value: unknown): string | unknown {
|
|
109
109
|
if (value instanceof Date) {
|
|
110
110
|
return value.toISOString().slice(0, 10);
|
|
111
111
|
}
|
|
@@ -115,7 +115,7 @@ function normalizeDateString(value: unknown): string | unknown {
|
|
|
115
115
|
return value;
|
|
116
116
|
}
|
|
117
117
|
|
|
118
|
-
function normalizeDateValue(value: unknown): Date | unknown {
|
|
118
|
+
export function normalizeDateValue(value: unknown): Date | unknown {
|
|
119
119
|
if (value instanceof Date) {
|
|
120
120
|
return value;
|
|
121
121
|
}
|
|
@@ -125,7 +125,7 @@ function normalizeDateValue(value: unknown): Date | unknown {
|
|
|
125
125
|
return value;
|
|
126
126
|
}
|
|
127
127
|
|
|
128
|
-
function normalizeTime(value: unknown): string | unknown {
|
|
128
|
+
export function normalizeTime(value: unknown): string | unknown {
|
|
129
129
|
if (typeof value === 'bigint') {
|
|
130
130
|
const totalMillis = Number(value) / 1000;
|
|
131
131
|
const date = new Date(totalMillis);
|
|
@@ -137,7 +137,7 @@ function normalizeTime(value: unknown): string | unknown {
|
|
|
137
137
|
return value;
|
|
138
138
|
}
|
|
139
139
|
|
|
140
|
-
function normalizeInterval(value: unknown): string | unknown {
|
|
140
|
+
export function normalizeInterval(value: unknown): string | unknown {
|
|
141
141
|
if (
|
|
142
142
|
value &&
|
|
143
143
|
typeof value === 'object' &&
|
package/src/utils.ts
CHANGED
|
@@ -0,0 +1,156 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* DuckDB wrapper value helpers that are safe for client-side bundles.
|
|
3
|
+
* These utilities only tag values; conversion to native bindings lives
|
|
4
|
+
* in value-wrappers.ts to avoid pulling @duckdb/node-api into browsers.
|
|
5
|
+
*/
|
|
6
|
+
export const DUCKDB_VALUE_MARKER = Symbol.for('drizzle-duckdb:value');
|
|
7
|
+
|
|
8
|
+
export type DuckDBValueKind =
|
|
9
|
+
| 'list'
|
|
10
|
+
| 'array'
|
|
11
|
+
| 'struct'
|
|
12
|
+
| 'map'
|
|
13
|
+
| 'timestamp'
|
|
14
|
+
| 'blob'
|
|
15
|
+
| 'json';
|
|
16
|
+
|
|
17
|
+
export interface DuckDBValueWrapper<
|
|
18
|
+
TKind extends DuckDBValueKind = DuckDBValueKind,
|
|
19
|
+
TData = unknown,
|
|
20
|
+
> {
|
|
21
|
+
readonly [DUCKDB_VALUE_MARKER]: true;
|
|
22
|
+
readonly kind: TKind;
|
|
23
|
+
readonly data: TData;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export interface ListValueWrapper
|
|
27
|
+
extends DuckDBValueWrapper<'list', unknown[]> {
|
|
28
|
+
readonly elementType?: string;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
export interface ArrayValueWrapper
|
|
32
|
+
extends DuckDBValueWrapper<'array', unknown[]> {
|
|
33
|
+
readonly elementType?: string;
|
|
34
|
+
readonly fixedLength?: number;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export interface StructValueWrapper
|
|
38
|
+
extends DuckDBValueWrapper<'struct', Record<string, unknown>> {
|
|
39
|
+
readonly schema?: Record<string, string>;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export interface MapValueWrapper
|
|
43
|
+
extends DuckDBValueWrapper<'map', Record<string, unknown>> {
|
|
44
|
+
readonly valueType?: string;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
export interface TimestampValueWrapper
|
|
48
|
+
extends DuckDBValueWrapper<'timestamp', Date | string | number | bigint> {
|
|
49
|
+
readonly withTimezone: boolean;
|
|
50
|
+
readonly precision?: number;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export interface BlobValueWrapper
|
|
54
|
+
extends DuckDBValueWrapper<'blob', Buffer | Uint8Array> {}
|
|
55
|
+
|
|
56
|
+
export interface JsonValueWrapper extends DuckDBValueWrapper<'json', unknown> {}
|
|
57
|
+
|
|
58
|
+
export type AnyDuckDBValueWrapper =
|
|
59
|
+
| ListValueWrapper
|
|
60
|
+
| ArrayValueWrapper
|
|
61
|
+
| StructValueWrapper
|
|
62
|
+
| MapValueWrapper
|
|
63
|
+
| TimestampValueWrapper
|
|
64
|
+
| BlobValueWrapper
|
|
65
|
+
| JsonValueWrapper;
|
|
66
|
+
|
|
67
|
+
export function isDuckDBWrapper(
|
|
68
|
+
value: unknown
|
|
69
|
+
): value is AnyDuckDBValueWrapper {
|
|
70
|
+
return (
|
|
71
|
+
value !== null &&
|
|
72
|
+
typeof value === 'object' &&
|
|
73
|
+
DUCKDB_VALUE_MARKER in value &&
|
|
74
|
+
(value as DuckDBValueWrapper)[DUCKDB_VALUE_MARKER] === true
|
|
75
|
+
);
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
export function wrapList(
|
|
79
|
+
data: unknown[],
|
|
80
|
+
elementType?: string
|
|
81
|
+
): ListValueWrapper {
|
|
82
|
+
return {
|
|
83
|
+
[DUCKDB_VALUE_MARKER]: true,
|
|
84
|
+
kind: 'list',
|
|
85
|
+
data,
|
|
86
|
+
elementType,
|
|
87
|
+
};
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
export function wrapArray(
|
|
91
|
+
data: unknown[],
|
|
92
|
+
elementType?: string,
|
|
93
|
+
fixedLength?: number
|
|
94
|
+
): ArrayValueWrapper {
|
|
95
|
+
return {
|
|
96
|
+
[DUCKDB_VALUE_MARKER]: true,
|
|
97
|
+
kind: 'array',
|
|
98
|
+
data,
|
|
99
|
+
elementType,
|
|
100
|
+
fixedLength,
|
|
101
|
+
};
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
export function wrapStruct(
|
|
105
|
+
data: Record<string, unknown>,
|
|
106
|
+
schema?: Record<string, string>
|
|
107
|
+
): StructValueWrapper {
|
|
108
|
+
return {
|
|
109
|
+
[DUCKDB_VALUE_MARKER]: true,
|
|
110
|
+
kind: 'struct',
|
|
111
|
+
data,
|
|
112
|
+
schema,
|
|
113
|
+
};
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export function wrapMap(
|
|
117
|
+
data: Record<string, unknown>,
|
|
118
|
+
valueType?: string
|
|
119
|
+
): MapValueWrapper {
|
|
120
|
+
return {
|
|
121
|
+
[DUCKDB_VALUE_MARKER]: true,
|
|
122
|
+
kind: 'map',
|
|
123
|
+
data,
|
|
124
|
+
valueType,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
export function wrapTimestamp(
|
|
129
|
+
data: Date | string | number | bigint,
|
|
130
|
+
withTimezone: boolean,
|
|
131
|
+
precision?: number
|
|
132
|
+
): TimestampValueWrapper {
|
|
133
|
+
return {
|
|
134
|
+
[DUCKDB_VALUE_MARKER]: true,
|
|
135
|
+
kind: 'timestamp',
|
|
136
|
+
data,
|
|
137
|
+
withTimezone,
|
|
138
|
+
precision,
|
|
139
|
+
};
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
export function wrapBlob(data: Buffer | Uint8Array): BlobValueWrapper {
|
|
143
|
+
return {
|
|
144
|
+
[DUCKDB_VALUE_MARKER]: true,
|
|
145
|
+
kind: 'blob',
|
|
146
|
+
data,
|
|
147
|
+
};
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
export function wrapJson(data: unknown): JsonValueWrapper {
|
|
151
|
+
return {
|
|
152
|
+
[DUCKDB_VALUE_MARKER]: true,
|
|
153
|
+
kind: 'json',
|
|
154
|
+
data,
|
|
155
|
+
};
|
|
156
|
+
}
|