@avidian/duckdb-bun 0.0.0-stage → 1.0.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/LICENSE +22 -0
- package/README.md +286 -2
- package/package.json +96 -4
- package/src/bindings/api/appender.ts +288 -0
- package/src/bindings/api/data-chunk.ts +58 -0
- package/src/bindings/api/database.ts +232 -0
- package/src/bindings/api/datetime.ts +158 -0
- package/src/bindings/api/index.ts +13 -0
- package/src/bindings/api/logical-types.ts +227 -0
- package/src/bindings/api/query.ts +616 -0
- package/src/bindings/api/scalar-function.ts +274 -0
- package/src/bindings/api/table-function.ts +339 -0
- package/src/bindings/api/values.ts +546 -0
- package/src/bindings/api/vector.ts +266 -0
- package/src/bindings/generated/capi.ts +695 -0
- package/src/bindings/generated/contract.ts +162 -0
- package/src/bindings/index.ts +10 -0
- package/src/bindings/runtime/convert.ts +307 -0
- package/src/bindings/runtime/diagnostics.ts +45 -0
- package/src/bindings/runtime/dispatch.ts +213 -0
- package/src/bindings/runtime/exception.ts +103 -0
- package/src/bindings/runtime/flags.ts +19 -0
- package/src/bindings/runtime/handle.ts +217 -0
- package/src/bindings/runtime/kinds.ts +53 -0
- package/src/bindings/runtime/marshal.ts +190 -0
- package/src/bindings/runtime/native.ts +153 -0
- package/src/bindings/runtime/ring.ts +54 -0
- package/src/bindings/runtime/scope.ts +133 -0
- package/src/bindings/runtime/trace.ts +65 -0
- package/src/connection.ts +35 -0
- package/src/database.ts +27 -0
- package/src/errors.ts +30 -0
- package/src/file-assets.d.ts +10 -0
- package/src/index.ts +17 -0
- package/src/library.ts +83 -0
- package/src/neo.ts +16 -0
- package/src/reader.ts +47 -0
- package/src/statement.ts +61 -0
- package/src/types.ts +52 -0
- package/src/version.ts +6 -0
- package/vendor/node-api/LICENSE +7 -0
- package/vendor/node-api/PROVENANCE.md +54 -0
- package/vendor/node-api/node-bindings.d.ts +1669 -0
- package/vendor/node-api/src/DuckDBAppender.ts +237 -0
- package/vendor/node-api/src/DuckDBClientContext.ts +13 -0
- package/vendor/node-api/src/DuckDBConnection.ts +315 -0
- package/vendor/node-api/src/DuckDBDataChunk.ts +412 -0
- package/vendor/node-api/src/DuckDBDataChunkWriter.ts +144 -0
- package/vendor/node-api/src/DuckDBExtractedStatements.ts +37 -0
- package/vendor/node-api/src/DuckDBInstance.ts +35 -0
- package/vendor/node-api/src/DuckDBInstanceCache.ts +29 -0
- package/vendor/node-api/src/DuckDBLogicalType.ts +446 -0
- package/vendor/node-api/src/DuckDBMaterializedResult.ts +39 -0
- package/vendor/node-api/src/DuckDBPendingResult.ts +83 -0
- package/vendor/node-api/src/DuckDBPreparedStatement.ts +376 -0
- package/vendor/node-api/src/DuckDBPreparedStatementCollection.ts +5 -0
- package/vendor/node-api/src/DuckDBPreparedStatementWeakRefCollection.ts +31 -0
- package/vendor/node-api/src/DuckDBResult.ts +403 -0
- package/vendor/node-api/src/DuckDBResultReader.ts +283 -0
- package/vendor/node-api/src/DuckDBScalarFunction.ts +149 -0
- package/vendor/node-api/src/DuckDBScalarFunctionBindInfo.ts +34 -0
- package/vendor/node-api/src/DuckDBScalarFunctionInfo.ts +34 -0
- package/vendor/node-api/src/DuckDBScalarFunctionInitInfo.ts +35 -0
- package/vendor/node-api/src/DuckDBTableFunction.ts +149 -0
- package/vendor/node-api/src/DuckDBTableFunctionBindInfo.ts +56 -0
- package/vendor/node-api/src/DuckDBTableFunctionInfo.ts +36 -0
- package/vendor/node-api/src/DuckDBTableFunctionInitInfo.ts +52 -0
- package/vendor/node-api/src/DuckDBType.ts +1 -0
- package/vendor/node-api/src/DuckDBTypeId.ts +46 -0
- package/vendor/node-api/src/DuckDBValueConverter.ts +23 -0
- package/vendor/node-api/src/DuckDBValueConverters.ts +461 -0
- package/vendor/node-api/src/DuckDBVector.ts +1 -0
- package/vendor/node-api/src/JS.ts +11 -0
- package/vendor/node-api/src/JSDuckDBValueConverter.ts +85 -0
- package/vendor/node-api/src/JSInputTypeForTypeId.ts +101 -0
- package/vendor/node-api/src/JSToDuckDBValueConverter.ts +136 -0
- package/vendor/node-api/src/JSTypeForTypeId.ts +78 -0
- package/vendor/node-api/src/Json.ts +7 -0
- package/vendor/node-api/src/JsonDuckDBValueConverter.ts +72 -0
- package/vendor/node-api/src/JsonTypeForTypeId.ts +86 -0
- package/vendor/node-api/src/ToDuckDBValueConverter.ts +68 -0
- package/vendor/node-api/src/ToDuckDBValueConverters.ts +303 -0
- package/vendor/node-api/src/configurationOptionDescriptions.ts +13 -0
- package/vendor/node-api/src/conversion/bytesFromString.ts +5 -0
- package/vendor/node-api/src/conversion/dateTimeStringConversion.ts +343 -0
- package/vendor/node-api/src/conversion/displayStringForDuckDBValue.ts +12 -0
- package/vendor/node-api/src/conversion/stringFromBlob.ts +48 -0
- package/vendor/node-api/src/conversion/stringFromDecimal.ts +129 -0
- package/vendor/node-api/src/conversion/varintDecode.ts +42 -0
- package/vendor/node-api/src/convertColumnsFromChunks.ts +28 -0
- package/vendor/node-api/src/convertColumnsObjectFromChunks.ts +29 -0
- package/vendor/node-api/src/convertRowObjectsFromChunks.ts +21 -0
- package/vendor/node-api/src/convertRowsFromChunks.ts +16 -0
- package/vendor/node-api/src/createConfig.ts +14 -0
- package/vendor/node-api/src/createDuckDBValueConverter.ts +17 -0
- package/vendor/node-api/src/createResult.ts +15 -0
- package/vendor/node-api/src/createValue.ts +355 -0
- package/vendor/node-api/src/duckdb.ts +51 -0
- package/vendor/node-api/src/enums.ts +7 -0
- package/vendor/node-api/src/getColumnsFromChunks.ts +13 -0
- package/vendor/node-api/src/getColumnsObjectFromChunks.ts +16 -0
- package/vendor/node-api/src/getRowObjectsFromChunks.ts +13 -0
- package/vendor/node-api/src/getRowsFromChunks.ts +12 -0
- package/vendor/node-api/src/index.ts +3 -0
- package/vendor/node-api/src/readValue.ts +31 -0
- package/vendor/node-api/src/sleep.ts +5 -0
- package/vendor/node-api/src/sql.ts +7 -0
- package/vendor/node-api/src/tsconfig.json +7 -0
- package/vendor/node-api/src/typeForValue.ts +144 -0
- package/vendor/node-api/src/types/BaseDuckDBType.ts +31 -0
- package/vendor/node-api/src/types/DuckDBAnyType.ts +13 -0
- package/vendor/node-api/src/types/DuckDBArrayType.ts +43 -0
- package/vendor/node-api/src/types/DuckDBBigIntType.ts +21 -0
- package/vendor/node-api/src/types/DuckDBBigNumType.ts +21 -0
- package/vendor/node-api/src/types/DuckDBBitType.ts +13 -0
- package/vendor/node-api/src/types/DuckDBBlobType.ts +13 -0
- package/vendor/node-api/src/types/DuckDBBooleanType.ts +13 -0
- package/vendor/node-api/src/types/DuckDBDateType.ts +29 -0
- package/vendor/node-api/src/types/DuckDBDecimalType.ts +46 -0
- package/vendor/node-api/src/types/DuckDBDoubleType.ts +21 -0
- package/vendor/node-api/src/types/DuckDBEnumType.ts +111 -0
- package/vendor/node-api/src/types/DuckDBFloatType.ts +21 -0
- package/vendor/node-api/src/types/DuckDBGeometryType.ts +36 -0
- package/vendor/node-api/src/types/DuckDBHugeIntType.ts +21 -0
- package/vendor/node-api/src/types/DuckDBIntegerLiteralType.ts +13 -0
- package/vendor/node-api/src/types/DuckDBIntegerType.ts +21 -0
- package/vendor/node-api/src/types/DuckDBIntervalType.ts +13 -0
- package/vendor/node-api/src/types/DuckDBListType.ts +35 -0
- package/vendor/node-api/src/types/DuckDBMapType.ts +47 -0
- package/vendor/node-api/src/types/DuckDBSQLNullType.ts +17 -0
- package/vendor/node-api/src/types/DuckDBSmallIntType.ts +21 -0
- package/vendor/node-api/src/types/DuckDBStringLiteralType.ts +13 -0
- package/vendor/node-api/src/types/DuckDBStructType.ts +104 -0
- package/vendor/node-api/src/types/DuckDBTimeNSType.ts +20 -0
- package/vendor/node-api/src/types/DuckDBTimeTZType.ts +23 -0
- package/vendor/node-api/src/types/DuckDBTimeType.ts +20 -0
- package/vendor/node-api/src/types/DuckDBTimestampMillisecondsType.ts +29 -0
- package/vendor/node-api/src/types/DuckDBTimestampNanosecondsType.ts +29 -0
- package/vendor/node-api/src/types/DuckDBTimestampSecondsType.ts +29 -0
- package/vendor/node-api/src/types/DuckDBTimestampTZNanosecondsType.ts +32 -0
- package/vendor/node-api/src/types/DuckDBTimestampTZType.ts +32 -0
- package/vendor/node-api/src/types/DuckDBTimestampType.ts +32 -0
- package/vendor/node-api/src/types/DuckDBTinyIntType.ts +21 -0
- package/vendor/node-api/src/types/DuckDBType.ts +86 -0
- package/vendor/node-api/src/types/DuckDBUBigIntType.ts +21 -0
- package/vendor/node-api/src/types/DuckDBUHugeIntType.ts +21 -0
- package/vendor/node-api/src/types/DuckDBUIntegerType.ts +21 -0
- package/vendor/node-api/src/types/DuckDBUSmallIntType.ts +21 -0
- package/vendor/node-api/src/types/DuckDBUTinyIntType.ts +21 -0
- package/vendor/node-api/src/types/DuckDBUUIDType.ts +20 -0
- package/vendor/node-api/src/types/DuckDBUnionType.ts +74 -0
- package/vendor/node-api/src/types/DuckDBVarCharType.ts +13 -0
- package/vendor/node-api/src/types/DuckDBVariantType.ts +13 -0
- package/vendor/node-api/src/types/index.ts +44 -0
- package/vendor/node-api/src/values/DuckDBArrayValue.ts +18 -0
- package/vendor/node-api/src/values/DuckDBBitValue.ts +117 -0
- package/vendor/node-api/src/values/DuckDBBlobValue.ts +26 -0
- package/vendor/node-api/src/values/DuckDBDateValue.ts +43 -0
- package/vendor/node-api/src/values/DuckDBDecimalValue.ts +44 -0
- package/vendor/node-api/src/values/DuckDBGeometryValue.ts +30 -0
- package/vendor/node-api/src/values/DuckDBIntervalValue.ts +22 -0
- package/vendor/node-api/src/values/DuckDBListValue.ts +18 -0
- package/vendor/node-api/src/values/DuckDBMapValue.ts +25 -0
- package/vendor/node-api/src/values/DuckDBStructValue.ts +22 -0
- package/vendor/node-api/src/values/DuckDBTimeNSValue.ts +23 -0
- package/vendor/node-api/src/values/DuckDBTimeTZValue.ts +96 -0
- package/vendor/node-api/src/values/DuckDBTimeValue.ts +34 -0
- package/vendor/node-api/src/values/DuckDBTimestampMillisecondsValue.ts +29 -0
- package/vendor/node-api/src/values/DuckDBTimestampNanosecondsValue.ts +28 -0
- package/vendor/node-api/src/values/DuckDBTimestampSecondsValue.ts +28 -0
- package/vendor/node-api/src/values/DuckDBTimestampTZNanosecondsValue.ts +44 -0
- package/vendor/node-api/src/values/DuckDBTimestampTZValue.ts +54 -0
- package/vendor/node-api/src/values/DuckDBTimestampValue.ts +45 -0
- package/vendor/node-api/src/values/DuckDBTupleValue.ts +22 -0
- package/vendor/node-api/src/values/DuckDBUUIDValue.ts +48 -0
- package/vendor/node-api/src/values/DuckDBUnionValue.ts +22 -0
- package/vendor/node-api/src/values/DuckDBValue.ts +53 -0
- package/vendor/node-api/src/values/DuckDBVariantValue.ts +34 -0
- package/vendor/node-api/src/values/index.ts +24 -0
- package/vendor/node-api/src/vectors/DuckDBArrayVector.ts +107 -0
- package/vendor/node-api/src/vectors/DuckDBBigIntVector.ts +75 -0
- package/vendor/node-api/src/vectors/DuckDBBigNumVector.ts +98 -0
- package/vendor/node-api/src/vectors/DuckDBBitVector.ts +102 -0
- package/vendor/node-api/src/vectors/DuckDBBlobVector.ts +112 -0
- package/vendor/node-api/src/vectors/DuckDBBooleanVector.ts +84 -0
- package/vendor/node-api/src/vectors/DuckDBDateVector.ts +80 -0
- package/vendor/node-api/src/vectors/DuckDBDecimal128Vector.ts +107 -0
- package/vendor/node-api/src/vectors/DuckDBDecimal16Vector.ts +104 -0
- package/vendor/node-api/src/vectors/DuckDBDecimal32Vector.ts +104 -0
- package/vendor/node-api/src/vectors/DuckDBDecimal64Vector.ts +104 -0
- package/vendor/node-api/src/vectors/DuckDBDoubleVector.ts +68 -0
- package/vendor/node-api/src/vectors/DuckDBEnum16Vector.ts +75 -0
- package/vendor/node-api/src/vectors/DuckDBEnum32Vector.ts +75 -0
- package/vendor/node-api/src/vectors/DuckDBEnum8Vector.ts +75 -0
- package/vendor/node-api/src/vectors/DuckDBFloatVector.ts +68 -0
- package/vendor/node-api/src/vectors/DuckDBGeometryVector.ts +97 -0
- package/vendor/node-api/src/vectors/DuckDBHugeIntVector.ts +89 -0
- package/vendor/node-api/src/vectors/DuckDBIntegerVector.ts +75 -0
- package/vendor/node-api/src/vectors/DuckDBIntervalVector.ts +100 -0
- package/vendor/node-api/src/vectors/DuckDBListVector.ts +221 -0
- package/vendor/node-api/src/vectors/DuckDBMapVector.ts +88 -0
- package/vendor/node-api/src/vectors/DuckDBSQLNullVector.ts +53 -0
- package/vendor/node-api/src/vectors/DuckDBSmallIntVector.ts +75 -0
- package/vendor/node-api/src/vectors/DuckDBStructVector.ts +138 -0
- package/vendor/node-api/src/vectors/DuckDBTimeNSVector.ts +80 -0
- package/vendor/node-api/src/vectors/DuckDBTimeTZVector.ts +80 -0
- package/vendor/node-api/src/vectors/DuckDBTimeVector.ts +80 -0
- package/vendor/node-api/src/vectors/DuckDBTimestampMillisecondsVector.ts +88 -0
- package/vendor/node-api/src/vectors/DuckDBTimestampNanosecondsVector.ts +88 -0
- package/vendor/node-api/src/vectors/DuckDBTimestampSecondsVector.ts +88 -0
- package/vendor/node-api/src/vectors/DuckDBTimestampTZNanosecondsVector.ts +88 -0
- package/vendor/node-api/src/vectors/DuckDBTimestampTZVector.ts +86 -0
- package/vendor/node-api/src/vectors/DuckDBTimestampVector.ts +83 -0
- package/vendor/node-api/src/vectors/DuckDBTinyIntVector.ts +75 -0
- package/vendor/node-api/src/vectors/DuckDBTupleVector.ts +125 -0
- package/vendor/node-api/src/vectors/DuckDBUBigIntVector.ts +75 -0
- package/vendor/node-api/src/vectors/DuckDBUHugeIntVector.ts +89 -0
- package/vendor/node-api/src/vectors/DuckDBUIntegerVector.ts +75 -0
- package/vendor/node-api/src/vectors/DuckDBUSmallIntVector.ts +75 -0
- package/vendor/node-api/src/vectors/DuckDBUTinyIntVector.ts +75 -0
- package/vendor/node-api/src/vectors/DuckDBUUIDVector.ts +89 -0
- package/vendor/node-api/src/vectors/DuckDBUnionVector.ts +84 -0
- package/vendor/node-api/src/vectors/DuckDBValidity.ts +104 -0
- package/vendor/node-api/src/vectors/DuckDBVarCharVector.ts +100 -0
- package/vendor/node-api/src/vectors/DuckDBVariantVector.ts +609 -0
- package/vendor/node-api/src/vectors/DuckDBVector.ts +33 -0
- package/vendor/node-api/src/vectors/createVector.ts +269 -0
- package/vendor/node-api/src/vectors/dataAccessors.ts +387 -0
- package/vendor/node-api/src/vectors/index.ts +50 -0
- package/vendor/node-api/src/vectors/vectorRegistry.ts +24 -0
- package/vendor/node-api/src/version.ts +5 -0
|
@@ -0,0 +1,412 @@
|
|
|
1
|
+
import duckdb from "../../../src/bindings/index.ts";
|
|
2
|
+
import { DuckDBType } from './DuckDBType';
|
|
3
|
+
import { DuckDBValueConverter } from './DuckDBValueConverter';
|
|
4
|
+
import { ToDuckDBValueConverter } from './ToDuckDBValueConverter';
|
|
5
|
+
import { DuckDBVector } from './DuckDBVector';
|
|
6
|
+
import { DuckDBValue } from './values';
|
|
7
|
+
|
|
8
|
+
export class DuckDBDataChunk {
|
|
9
|
+
public readonly chunk: duckdb.DataChunk;
|
|
10
|
+
private readonly vectors: DuckDBVector[] = [];
|
|
11
|
+
constructor(chunk: duckdb.DataChunk) {
|
|
12
|
+
this.chunk = chunk;
|
|
13
|
+
}
|
|
14
|
+
public static create(
|
|
15
|
+
types: readonly DuckDBType[],
|
|
16
|
+
rowCount?: number
|
|
17
|
+
): DuckDBDataChunk {
|
|
18
|
+
let chunk: DuckDBDataChunk;
|
|
19
|
+
try {
|
|
20
|
+
chunk = new DuckDBDataChunk(
|
|
21
|
+
duckdb.create_data_chunk(
|
|
22
|
+
types.map((t) => t.toLogicalType().logical_type)
|
|
23
|
+
)
|
|
24
|
+
);
|
|
25
|
+
} catch (cause) {
|
|
26
|
+
// The binding knows the chunk was refused but not which type did it, so
|
|
27
|
+
// name them here. Zero columns is a legitimate chunk, so there is
|
|
28
|
+
// nothing to check on the way out; only the refusal is an error.
|
|
29
|
+
throw new Error(
|
|
30
|
+
`Cannot create a data chunk with these column types: ${types.join(', ')}`,
|
|
31
|
+
{ cause }
|
|
32
|
+
);
|
|
33
|
+
}
|
|
34
|
+
if (rowCount != undefined) {
|
|
35
|
+
chunk.rowCount = rowCount;
|
|
36
|
+
}
|
|
37
|
+
return chunk;
|
|
38
|
+
}
|
|
39
|
+
public reset() {
|
|
40
|
+
duckdb.data_chunk_reset(this.chunk);
|
|
41
|
+
}
|
|
42
|
+
public get columnCount(): number {
|
|
43
|
+
return duckdb.data_chunk_get_column_count(this.chunk);
|
|
44
|
+
}
|
|
45
|
+
public get rowCount(): number {
|
|
46
|
+
return duckdb.data_chunk_get_size(this.chunk);
|
|
47
|
+
}
|
|
48
|
+
public set rowCount(count: number) {
|
|
49
|
+
const maxRowCount = duckdb.vector_size();
|
|
50
|
+
if (count > maxRowCount) {
|
|
51
|
+
throw new Error(`A data chunk cannot have more than ${maxRowCount} rows`);
|
|
52
|
+
}
|
|
53
|
+
duckdb.data_chunk_set_size(this.chunk, count);
|
|
54
|
+
// Cached vectors were built for the previous row count, so they are the
|
|
55
|
+
// wrong size now. This matters most for a table function's output chunk,
|
|
56
|
+
// which arrives empty and is sized by the function on every call.
|
|
57
|
+
this.vectors.length = 0;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* Refuses a column count that does not match the chunk's.
|
|
61
|
+
*
|
|
62
|
+
* A short array would leave the remaining vectors never written and never
|
|
63
|
+
* flushed while the chunk reports a non-zero row count, and reading or
|
|
64
|
+
* appending it then crashes the process instead of raising.
|
|
65
|
+
*/
|
|
66
|
+
private assertColumnCount(count: number) {
|
|
67
|
+
const columnCount = this.columnCount;
|
|
68
|
+
if (count !== columnCount) {
|
|
69
|
+
throw new Error(
|
|
70
|
+
`Provided number of columns (${count}) does not match chunk column count (${columnCount})`
|
|
71
|
+
);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
public getColumnVector(columnIndex: number): DuckDBVector {
|
|
75
|
+
if (this.vectors[columnIndex]) {
|
|
76
|
+
return this.vectors[columnIndex];
|
|
77
|
+
}
|
|
78
|
+
const vector = DuckDBVector.create(
|
|
79
|
+
duckdb.data_chunk_get_vector(this.chunk, columnIndex),
|
|
80
|
+
this.rowCount
|
|
81
|
+
);
|
|
82
|
+
this.vectors[columnIndex] = vector;
|
|
83
|
+
return vector;
|
|
84
|
+
}
|
|
85
|
+
public visitColumnValues(
|
|
86
|
+
columnIndex: number,
|
|
87
|
+
visitValue: (
|
|
88
|
+
value: DuckDBValue,
|
|
89
|
+
rowIndex: number,
|
|
90
|
+
columnIndex: number,
|
|
91
|
+
type: DuckDBType
|
|
92
|
+
) => void
|
|
93
|
+
) {
|
|
94
|
+
const vector = this.getColumnVector(columnIndex);
|
|
95
|
+
const type = vector.type;
|
|
96
|
+
for (let rowIndex = 0; rowIndex < vector.itemCount; rowIndex++) {
|
|
97
|
+
visitValue(vector.getItem(rowIndex), rowIndex, columnIndex, type);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
public appendColumnValues(columnIndex: number, values: DuckDBValue[]) {
|
|
101
|
+
this.visitColumnValues(columnIndex, (value) => values.push(value));
|
|
102
|
+
}
|
|
103
|
+
public getColumnValues(columnIndex: number): DuckDBValue[] {
|
|
104
|
+
const values: DuckDBValue[] = [];
|
|
105
|
+
this.appendColumnValues(columnIndex, values);
|
|
106
|
+
return values;
|
|
107
|
+
}
|
|
108
|
+
public convertColumnValues<T>(
|
|
109
|
+
columnIndex: number,
|
|
110
|
+
converter: DuckDBValueConverter<T>
|
|
111
|
+
): (T | null)[] {
|
|
112
|
+
const convertedValues: (T | null)[] = [];
|
|
113
|
+
this.visitColumnValues(columnIndex, (value, _r, _c, type) =>
|
|
114
|
+
convertedValues.push(converter(value, type, converter))
|
|
115
|
+
);
|
|
116
|
+
return convertedValues;
|
|
117
|
+
}
|
|
118
|
+
public setColumnValues(columnIndex: number, values: readonly DuckDBValue[]) {
|
|
119
|
+
const vector = this.getColumnVector(columnIndex);
|
|
120
|
+
if (vector.itemCount !== values.length) {
|
|
121
|
+
throw new Error(`number of values must equal chunk row count`);
|
|
122
|
+
}
|
|
123
|
+
for (let i = 0; i < values.length; i++) {
|
|
124
|
+
vector.setItem(i, values[i]);
|
|
125
|
+
}
|
|
126
|
+
vector.flush();
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* `setColumnValues` with each value converted on the way in: the write
|
|
130
|
+
* counterpart of `convertColumnValues`.
|
|
131
|
+
*
|
|
132
|
+
* The column's type comes from its vector, so the converter is the only
|
|
133
|
+
* thing the caller supplies.
|
|
134
|
+
*/
|
|
135
|
+
public setColumnValuesConverted<T>(
|
|
136
|
+
columnIndex: number,
|
|
137
|
+
values: readonly (T | null)[],
|
|
138
|
+
converter: ToDuckDBValueConverter<T>
|
|
139
|
+
) {
|
|
140
|
+
const vector = this.getColumnVector(columnIndex);
|
|
141
|
+
if (vector.itemCount !== values.length) {
|
|
142
|
+
throw new Error(`number of values must equal chunk row count`);
|
|
143
|
+
}
|
|
144
|
+
const { type } = vector;
|
|
145
|
+
try {
|
|
146
|
+
for (let i = 0; i < values.length; i++) {
|
|
147
|
+
vector.setItem(i, converter(values[i] as T, type, converter));
|
|
148
|
+
}
|
|
149
|
+
} catch (cause) {
|
|
150
|
+
throw new Error(`Failed to set column ${columnIndex} (${type})`, {
|
|
151
|
+
cause,
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
vector.flush();
|
|
155
|
+
}
|
|
156
|
+
public visitColumns(
|
|
157
|
+
visitColumn: (
|
|
158
|
+
column: DuckDBValue[],
|
|
159
|
+
columnIndex: number,
|
|
160
|
+
type: DuckDBType
|
|
161
|
+
) => void
|
|
162
|
+
) {
|
|
163
|
+
const columnCount = this.columnCount;
|
|
164
|
+
for (let columnIndex = 0; columnIndex < columnCount; columnIndex++) {
|
|
165
|
+
visitColumn(
|
|
166
|
+
this.getColumnValues(columnIndex),
|
|
167
|
+
columnIndex,
|
|
168
|
+
this.getColumnVector(columnIndex).type
|
|
169
|
+
);
|
|
170
|
+
}
|
|
171
|
+
}
|
|
172
|
+
public appendToColumns(columns: (DuckDBValue[] | undefined)[]) {
|
|
173
|
+
const columnCount = this.columnCount;
|
|
174
|
+
for (let columnIndex = 0; columnIndex < columnCount; columnIndex++) {
|
|
175
|
+
let column = columns[columnIndex];
|
|
176
|
+
if (!column) {
|
|
177
|
+
column = [];
|
|
178
|
+
columns[columnIndex] = column;
|
|
179
|
+
}
|
|
180
|
+
this.appendColumnValues(columnIndex, column);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
public getColumns(): DuckDBValue[][] {
|
|
184
|
+
const columns: DuckDBValue[][] = [];
|
|
185
|
+
this.visitColumns((column) => columns.push(column));
|
|
186
|
+
return columns;
|
|
187
|
+
}
|
|
188
|
+
public convertColumns<T>(converter: DuckDBValueConverter<T>): (T | null)[][] {
|
|
189
|
+
const convertedColumns: (T | null)[][] = [];
|
|
190
|
+
const columnCount = this.columnCount;
|
|
191
|
+
for (let columnIndex = 0; columnIndex < columnCount; columnIndex++) {
|
|
192
|
+
convertedColumns.push(this.convertColumnValues(columnIndex, converter));
|
|
193
|
+
}
|
|
194
|
+
return convertedColumns;
|
|
195
|
+
}
|
|
196
|
+
public setColumns(columns: readonly (readonly DuckDBValue[])[]) {
|
|
197
|
+
this.assertColumnCount(columns.length);
|
|
198
|
+
if (columns.length > 0) {
|
|
199
|
+
this.rowCount = columns[0].length;
|
|
200
|
+
}
|
|
201
|
+
for (let columnIndex = 0; columnIndex < columns.length; columnIndex++) {
|
|
202
|
+
this.setColumnValues(columnIndex, columns[columnIndex]);
|
|
203
|
+
}
|
|
204
|
+
}
|
|
205
|
+
/**
|
|
206
|
+
* `setColumns` with each value converted on the way in: the write
|
|
207
|
+
* counterpart of `convertColumns`.
|
|
208
|
+
*/
|
|
209
|
+
public setColumnsConverted<T>(
|
|
210
|
+
columns: readonly (readonly (T | null)[])[],
|
|
211
|
+
converter: ToDuckDBValueConverter<T>
|
|
212
|
+
) {
|
|
213
|
+
this.assertColumnCount(columns.length);
|
|
214
|
+
if (columns.length > 0) {
|
|
215
|
+
this.rowCount = columns[0].length;
|
|
216
|
+
}
|
|
217
|
+
for (let columnIndex = 0; columnIndex < columns.length; columnIndex++) {
|
|
218
|
+
this.setColumnValuesConverted(
|
|
219
|
+
columnIndex,
|
|
220
|
+
columns[columnIndex],
|
|
221
|
+
converter
|
|
222
|
+
);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
public appendToColumnsObject(
|
|
226
|
+
columnNames: readonly string[],
|
|
227
|
+
columnsObject: Record<string, DuckDBValue[] | undefined>
|
|
228
|
+
) {
|
|
229
|
+
const columnCount = this.columnCount;
|
|
230
|
+
if (columnNames.length !== columnCount) {
|
|
231
|
+
throw new Error(
|
|
232
|
+
`Provided number of column names (${columnNames.length}) does not match column count (${this.columnCount})`
|
|
233
|
+
);
|
|
234
|
+
}
|
|
235
|
+
for (let columnIndex = 0; columnIndex < columnCount; columnIndex++) {
|
|
236
|
+
const columnName = columnNames[columnIndex];
|
|
237
|
+
let columnValues = columnsObject[columnName];
|
|
238
|
+
if (!columnValues) {
|
|
239
|
+
columnValues = [];
|
|
240
|
+
columnsObject[columnName] = columnValues;
|
|
241
|
+
}
|
|
242
|
+
this.appendColumnValues(columnIndex, columnValues);
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
public getColumnsObject(
|
|
246
|
+
columnNames: readonly string[]
|
|
247
|
+
): Record<string, DuckDBValue[]> {
|
|
248
|
+
const columnsObject: Record<string, DuckDBValue[]> = {};
|
|
249
|
+
this.appendToColumnsObject(columnNames, columnsObject);
|
|
250
|
+
return columnsObject;
|
|
251
|
+
}
|
|
252
|
+
public visitColumnMajor(
|
|
253
|
+
visitValue: (
|
|
254
|
+
value: DuckDBValue,
|
|
255
|
+
rowIndex: number,
|
|
256
|
+
columnIndex: number,
|
|
257
|
+
type: DuckDBType
|
|
258
|
+
) => void
|
|
259
|
+
) {
|
|
260
|
+
const columnCount = this.columnCount;
|
|
261
|
+
for (let columnIndex = 0; columnIndex < columnCount; columnIndex++) {
|
|
262
|
+
this.visitColumnValues(columnIndex, visitValue);
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
public visitRowValues(
|
|
266
|
+
rowIndex: number,
|
|
267
|
+
visitValue: (
|
|
268
|
+
value: DuckDBValue,
|
|
269
|
+
rowIndex: number,
|
|
270
|
+
columnIndex: number,
|
|
271
|
+
type: DuckDBType
|
|
272
|
+
) => void
|
|
273
|
+
) {
|
|
274
|
+
const columnCount = this.columnCount;
|
|
275
|
+
for (let columnIndex = 0; columnIndex < columnCount; columnIndex++) {
|
|
276
|
+
const vector = this.getColumnVector(columnIndex);
|
|
277
|
+
visitValue(vector.getItem(rowIndex), rowIndex, columnIndex, vector.type);
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
public appendRowValues(rowIndex: number, values: DuckDBValue[]) {
|
|
281
|
+
this.visitRowValues(rowIndex, (value) => values.push(value));
|
|
282
|
+
}
|
|
283
|
+
public getRowValues(rowIndex: number): DuckDBValue[] {
|
|
284
|
+
const values: DuckDBValue[] = [];
|
|
285
|
+
this.appendRowValues(rowIndex, values);
|
|
286
|
+
return values;
|
|
287
|
+
}
|
|
288
|
+
public convertRowValues<T>(
|
|
289
|
+
rowIndex: number,
|
|
290
|
+
converter: DuckDBValueConverter<T>
|
|
291
|
+
): (T | null)[] {
|
|
292
|
+
const convertedValues: (T | null)[] = [];
|
|
293
|
+
this.visitRowValues(rowIndex, (value, _, columnIndex) =>
|
|
294
|
+
convertedValues.push(
|
|
295
|
+
converter(value, this.getColumnVector(columnIndex).type, converter)
|
|
296
|
+
)
|
|
297
|
+
);
|
|
298
|
+
return convertedValues;
|
|
299
|
+
}
|
|
300
|
+
public visitRows(visitRow: (row: DuckDBValue[], rowIndex: number) => void) {
|
|
301
|
+
const rowCount = this.rowCount;
|
|
302
|
+
for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) {
|
|
303
|
+
visitRow(this.getRowValues(rowIndex), rowIndex);
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
public appendToRows(rows: DuckDBValue[][]) {
|
|
307
|
+
this.visitRows((row) => rows.push(row));
|
|
308
|
+
}
|
|
309
|
+
public getRows(): DuckDBValue[][] {
|
|
310
|
+
const rows: DuckDBValue[][] = [];
|
|
311
|
+
this.appendToRows(rows);
|
|
312
|
+
return rows;
|
|
313
|
+
}
|
|
314
|
+
public convertRows<T>(converter: DuckDBValueConverter<T>): (T | null)[][] {
|
|
315
|
+
const convertedRows: (T | null)[][] = [];
|
|
316
|
+
const rowCount = this.rowCount;
|
|
317
|
+
for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) {
|
|
318
|
+
convertedRows.push(this.convertRowValues(rowIndex, converter));
|
|
319
|
+
}
|
|
320
|
+
return convertedRows;
|
|
321
|
+
}
|
|
322
|
+
public setRows(rows: readonly (readonly DuckDBValue[])[]) {
|
|
323
|
+
this.rowCount = rows.length;
|
|
324
|
+
const columnCount = this.columnCount;
|
|
325
|
+
for (let columnIndex = 0; columnIndex < columnCount; columnIndex++) {
|
|
326
|
+
const vector = this.getColumnVector(columnIndex);
|
|
327
|
+
for (let rowIndex = 0; rowIndex < rows.length; rowIndex++) {
|
|
328
|
+
vector.setItem(rowIndex, rows[rowIndex][columnIndex]);
|
|
329
|
+
}
|
|
330
|
+
vector.flush();
|
|
331
|
+
}
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* `setRows` with each value converted on the way in: the write counterpart
|
|
335
|
+
* of `convertRows`.
|
|
336
|
+
*
|
|
337
|
+
* Each column's type comes from its vector, so the converter is the only
|
|
338
|
+
* thing the caller supplies.
|
|
339
|
+
*/
|
|
340
|
+
public setRowsConverted<T>(
|
|
341
|
+
rows: readonly (readonly (T | null)[])[],
|
|
342
|
+
converter: ToDuckDBValueConverter<T>
|
|
343
|
+
) {
|
|
344
|
+
this.rowCount = rows.length;
|
|
345
|
+
const columnCount = this.columnCount;
|
|
346
|
+
for (let columnIndex = 0; columnIndex < columnCount; columnIndex++) {
|
|
347
|
+
const vector = this.getColumnVector(columnIndex);
|
|
348
|
+
const { type } = vector;
|
|
349
|
+
// Wrapped per column rather than per value: a conversion failure names
|
|
350
|
+
// the column it came from without a try/catch in the inner loop.
|
|
351
|
+
try {
|
|
352
|
+
for (let rowIndex = 0; rowIndex < rows.length; rowIndex++) {
|
|
353
|
+
vector.setItem(
|
|
354
|
+
rowIndex,
|
|
355
|
+
converter(rows[rowIndex][columnIndex] as T, type, converter)
|
|
356
|
+
);
|
|
357
|
+
}
|
|
358
|
+
} catch (cause) {
|
|
359
|
+
throw new Error(`Failed to set column ${columnIndex} (${type})`, {
|
|
360
|
+
cause,
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
vector.flush();
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
public appendToRowObjects(
|
|
367
|
+
columnNames: readonly string[],
|
|
368
|
+
rowObjects: Record<string, DuckDBValue>[]
|
|
369
|
+
) {
|
|
370
|
+
const columnCount = this.columnCount;
|
|
371
|
+
if (columnNames.length !== columnCount) {
|
|
372
|
+
throw new Error(
|
|
373
|
+
`Provided number of column names (${columnNames.length}) does not match column count (${this.columnCount})`
|
|
374
|
+
);
|
|
375
|
+
}
|
|
376
|
+
const rowCount = this.rowCount;
|
|
377
|
+
for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) {
|
|
378
|
+
let rowObject: Record<string, DuckDBValue> = {};
|
|
379
|
+
this.visitRowValues(rowIndex, (value, _, columnIndex) => {
|
|
380
|
+
rowObject[columnNames[columnIndex]] = value;
|
|
381
|
+
});
|
|
382
|
+
rowObjects.push(rowObject);
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
public getRowObjects(columnNames: readonly string[]) {
|
|
386
|
+
const rowObjects: Record<string, DuckDBValue>[] = [];
|
|
387
|
+
this.appendToRowObjects(columnNames, rowObjects);
|
|
388
|
+
return rowObjects;
|
|
389
|
+
}
|
|
390
|
+
public visitRowMajor(
|
|
391
|
+
visitValue: (
|
|
392
|
+
value: DuckDBValue,
|
|
393
|
+
rowIndex: number,
|
|
394
|
+
columnIndex: number,
|
|
395
|
+
type: DuckDBType
|
|
396
|
+
) => void
|
|
397
|
+
) {
|
|
398
|
+
const rowCount = this.rowCount;
|
|
399
|
+
const columnCount = this.columnCount;
|
|
400
|
+
for (let rowIndex = 0; rowIndex < rowCount; rowIndex++) {
|
|
401
|
+
for (let columnIndex = 0; columnIndex < columnCount; columnIndex++) {
|
|
402
|
+
const vector = this.getColumnVector(columnIndex);
|
|
403
|
+
visitValue(
|
|
404
|
+
vector.getItem(rowIndex),
|
|
405
|
+
rowIndex,
|
|
406
|
+
columnIndex,
|
|
407
|
+
vector.type
|
|
408
|
+
);
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
}
|
|
412
|
+
}
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
import duckdb from "../../../src/bindings/index.ts";
|
|
2
|
+
import type { DuckDBAppender } from './DuckDBAppender';
|
|
3
|
+
import { DuckDBDataChunk } from './DuckDBDataChunk';
|
|
4
|
+
import { DuckDBType } from './DuckDBType';
|
|
5
|
+
import { ToDuckDBValueConverter } from './ToDuckDBValueConverter';
|
|
6
|
+
import { DuckDBValue } from './values';
|
|
7
|
+
|
|
8
|
+
/** Receives each data chunk a `DuckDBDataChunkWriter` fills. */
|
|
9
|
+
export type DuckDBDataChunkSink = (chunk: DuckDBDataChunk) => void;
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* `converter` is optional only when the rows are already `DuckDBValue`s, which
|
|
13
|
+
* is what `T` defaults to. Supply one to write some other representation —
|
|
14
|
+
* `JSToDuckDBValueConverter` for plain JS — and `T` follows from it.
|
|
15
|
+
*/
|
|
16
|
+
export type DuckDBDataChunkWriterOptions<T> = {
|
|
17
|
+
/**
|
|
18
|
+
* How many rows each emitted data chunk holds — its `rowCount`. Defaults to
|
|
19
|
+
* the DuckDB vector size, which is also the most a data chunk can hold.
|
|
20
|
+
*/
|
|
21
|
+
readonly rowsPerDataChunk?: number;
|
|
22
|
+
} & ([DuckDBValue] extends [T]
|
|
23
|
+
? { readonly converter?: ToDuckDBValueConverter<T> }
|
|
24
|
+
: { readonly converter: ToDuckDBValueConverter<T> });
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Accumulates rows and emits them as filled data chunks, one per
|
|
28
|
+
* `rowsPerDataChunk` rows, passing each to `sink`.
|
|
29
|
+
*
|
|
30
|
+
* Rows are `DuckDBValue`s by default. Supply a converter to write some other
|
|
31
|
+
* representation; the row type follows from it.
|
|
32
|
+
*
|
|
33
|
+
* const writer = DuckDBDataChunkWriter.forAppender(appender, {
|
|
34
|
+
* converter: JSToDuckDBValueConverter,
|
|
35
|
+
* });
|
|
36
|
+
* for (const row of rows) {
|
|
37
|
+
* writer.appendRow(row);
|
|
38
|
+
* }
|
|
39
|
+
* writer.flush();
|
|
40
|
+
*
|
|
41
|
+
* `flush` emits whatever is buffered, so call it when done: the last chunk is
|
|
42
|
+
* usually a partial one. Rows already grouped into chunk-sized batches need no
|
|
43
|
+
* writer — fill a `DuckDBDataChunk` and pass it to the destination directly.
|
|
44
|
+
*/
|
|
45
|
+
export class DuckDBDataChunkWriter<T = DuckDBValue> {
|
|
46
|
+
private readonly types: readonly DuckDBType[];
|
|
47
|
+
private readonly sink: DuckDBDataChunkSink;
|
|
48
|
+
private readonly rowsPerDataChunk: number;
|
|
49
|
+
private readonly converter?: ToDuckDBValueConverter<T>;
|
|
50
|
+
private rows: (T | null)[][] = [];
|
|
51
|
+
|
|
52
|
+
public constructor(
|
|
53
|
+
types: readonly DuckDBType[],
|
|
54
|
+
sink: DuckDBDataChunkSink,
|
|
55
|
+
options: DuckDBDataChunkWriterOptions<T> = {} as DuckDBDataChunkWriterOptions<T>
|
|
56
|
+
) {
|
|
57
|
+
this.types = types;
|
|
58
|
+
this.sink = sink;
|
|
59
|
+
const maxRowCount = duckdb.vector_size();
|
|
60
|
+
this.rowsPerDataChunk = options.rowsPerDataChunk ?? maxRowCount;
|
|
61
|
+
// Checked here rather than left to the first flush, which is where the
|
|
62
|
+
// chunk itself would refuse it — a whole buffer's worth of rows later.
|
|
63
|
+
if (this.rowsPerDataChunk < 1 || this.rowsPerDataChunk > maxRowCount) {
|
|
64
|
+
throw new Error(
|
|
65
|
+
`rowsPerDataChunk must be between 1 and ${maxRowCount}, got ${this.rowsPerDataChunk}`
|
|
66
|
+
);
|
|
67
|
+
}
|
|
68
|
+
this.converter = options.converter;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
/**
|
|
72
|
+
* A writer that appends each filled data chunk to `appender`, using the
|
|
73
|
+
* appender's own column types.
|
|
74
|
+
*
|
|
75
|
+
* Equivalent to constructing one with those types and a sink that calls
|
|
76
|
+
* `appendDataChunk`, but with nothing to keep in step by hand.
|
|
77
|
+
*/
|
|
78
|
+
public static forAppender<T = DuckDBValue>(
|
|
79
|
+
appender: DuckDBAppender,
|
|
80
|
+
options: DuckDBDataChunkWriterOptions<T> = {} as DuckDBDataChunkWriterOptions<T>
|
|
81
|
+
): DuckDBDataChunkWriter<T> {
|
|
82
|
+
const types: DuckDBType[] = [];
|
|
83
|
+
const columnCount = appender.columnCount;
|
|
84
|
+
for (let columnIndex = 0; columnIndex < columnCount; columnIndex++) {
|
|
85
|
+
types.push(appender.columnType(columnIndex));
|
|
86
|
+
}
|
|
87
|
+
return new DuckDBDataChunkWriter<T>(
|
|
88
|
+
types,
|
|
89
|
+
(chunk) => appender.appendDataChunk(chunk),
|
|
90
|
+
options
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
public get bufferedRowCount(): number {
|
|
95
|
+
return this.rows.length;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* Buffers one row, emitting a data chunk once `rowsPerDataChunk` are held.
|
|
100
|
+
*
|
|
101
|
+
* The row is copied, so the same array can be reused across calls.
|
|
102
|
+
*/
|
|
103
|
+
public appendRow(values: readonly (T | null)[]): void {
|
|
104
|
+
if (values.length !== this.types.length) {
|
|
105
|
+
throw new Error(
|
|
106
|
+
`Provided number of values (${values.length}) does not match number of types (${this.types.length})`
|
|
107
|
+
);
|
|
108
|
+
}
|
|
109
|
+
this.rows.push(values.slice());
|
|
110
|
+
if (this.rows.length >= this.rowsPerDataChunk) {
|
|
111
|
+
this.flush();
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
/**
|
|
116
|
+
* Emits the buffered rows as one data chunk. A no-op when none are
|
|
117
|
+
* buffered, so it is safe to call more than once.
|
|
118
|
+
*
|
|
119
|
+
* The buffer is emptied either way: if converting the rows fails, or the
|
|
120
|
+
* sink rejects the chunk, those rows are discarded along with the error.
|
|
121
|
+
* Appending afterwards starts a fresh chunk.
|
|
122
|
+
*/
|
|
123
|
+
public flush(): void {
|
|
124
|
+
if (this.rows.length === 0) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
// Taken before anything that can throw. Left in place, a batch that failed
|
|
128
|
+
// to convert or that the sink rejected would still be buffered, and later
|
|
129
|
+
// appends would grow it past `rowsPerDataChunk` and eventually past what a
|
|
130
|
+
// data chunk can hold at all — by which point the writer can no longer
|
|
131
|
+
// flush and the original error is long gone.
|
|
132
|
+
const rows = this.rows;
|
|
133
|
+
this.rows = [];
|
|
134
|
+
const chunk = DuckDBDataChunk.create(this.types);
|
|
135
|
+
if (this.converter) {
|
|
136
|
+
chunk.setRowsConverted(rows, this.converter);
|
|
137
|
+
} else {
|
|
138
|
+
// Without a converter the options type has already constrained `T` to
|
|
139
|
+
// `DuckDBValue`, which is the only thing that makes this cast sound.
|
|
140
|
+
chunk.setRows(rows as readonly (readonly DuckDBValue[])[]);
|
|
141
|
+
}
|
|
142
|
+
this.sink(chunk);
|
|
143
|
+
}
|
|
144
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
import duckdb from "../../../src/bindings/index.ts";
|
|
2
|
+
import { DuckDBPreparedStatement } from './DuckDBPreparedStatement';
|
|
3
|
+
import { DuckDBPreparedStatementCollection } from './DuckDBPreparedStatementCollection';
|
|
4
|
+
|
|
5
|
+
export class DuckDBExtractedStatements {
|
|
6
|
+
private readonly connection: duckdb.Connection;
|
|
7
|
+
private readonly extracted_statements: duckdb.ExtractedStatements;
|
|
8
|
+
private readonly statement_count: number;
|
|
9
|
+
private readonly preparedStatements?: DuckDBPreparedStatementCollection;
|
|
10
|
+
constructor(
|
|
11
|
+
connection: duckdb.Connection,
|
|
12
|
+
extracted_statements: duckdb.ExtractedStatements,
|
|
13
|
+
statement_count: number,
|
|
14
|
+
preparedStatements?: DuckDBPreparedStatementCollection
|
|
15
|
+
) {
|
|
16
|
+
this.connection = connection;
|
|
17
|
+
this.extracted_statements = extracted_statements;
|
|
18
|
+
this.statement_count = statement_count;
|
|
19
|
+
this.preparedStatements = preparedStatements;
|
|
20
|
+
}
|
|
21
|
+
public get count(): number {
|
|
22
|
+
return this.statement_count;
|
|
23
|
+
}
|
|
24
|
+
public async prepare(index: number): Promise<DuckDBPreparedStatement> {
|
|
25
|
+
const prepared = new DuckDBPreparedStatement(
|
|
26
|
+
await duckdb.prepare_extracted_statement(
|
|
27
|
+
this.connection,
|
|
28
|
+
this.extracted_statements,
|
|
29
|
+
index
|
|
30
|
+
)
|
|
31
|
+
);
|
|
32
|
+
if (this.preparedStatements) {
|
|
33
|
+
this.preparedStatements.add(prepared);
|
|
34
|
+
}
|
|
35
|
+
return prepared;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import duckdb from "../../../src/bindings/index.ts";
|
|
2
|
+
import { createConfig } from './createConfig';
|
|
3
|
+
import { DuckDBConnection } from './DuckDBConnection';
|
|
4
|
+
import { DuckDBInstanceCache } from './DuckDBInstanceCache';
|
|
5
|
+
|
|
6
|
+
export class DuckDBInstance {
|
|
7
|
+
private readonly db: duckdb.Database;
|
|
8
|
+
|
|
9
|
+
constructor(db: duckdb.Database) {
|
|
10
|
+
this.db = db;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
public static async create(
|
|
14
|
+
path?: string,
|
|
15
|
+
options?: Record<string, string>
|
|
16
|
+
): Promise<DuckDBInstance> {
|
|
17
|
+
const config = createConfig(options);
|
|
18
|
+
return new DuckDBInstance(await duckdb.open(path, config));
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
public static async fromCache(
|
|
22
|
+
path?: string,
|
|
23
|
+
options?: Record<string, string>
|
|
24
|
+
): Promise<DuckDBInstance> {
|
|
25
|
+
return DuckDBInstanceCache.singleton.getOrCreateInstance(path, options);
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
public async connect(): Promise<DuckDBConnection> {
|
|
29
|
+
return new DuckDBConnection(await duckdb.connect(this.db));
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
public closeSync() {
|
|
33
|
+
duckdb.close_sync(this.db);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import duckdb from "../../../src/bindings/index.ts";
|
|
2
|
+
import { DuckDBInstance } from './DuckDBInstance';
|
|
3
|
+
import { createConfig } from './createConfig';
|
|
4
|
+
|
|
5
|
+
export class DuckDBInstanceCache {
|
|
6
|
+
private readonly cache: duckdb.InstanceCache;
|
|
7
|
+
|
|
8
|
+
constructor() {
|
|
9
|
+
this.cache = duckdb.create_instance_cache();
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
public async getOrCreateInstance(
|
|
13
|
+
path?: string,
|
|
14
|
+
options?: Record<string, string>
|
|
15
|
+
): Promise<DuckDBInstance> {
|
|
16
|
+
const config = createConfig(options);
|
|
17
|
+
const db = await duckdb.get_or_create_from_cache(this.cache, path, config);
|
|
18
|
+
return new DuckDBInstance(db);
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
private static singletonInstance: DuckDBInstanceCache;
|
|
22
|
+
|
|
23
|
+
public static get singleton(): DuckDBInstanceCache {
|
|
24
|
+
if (!DuckDBInstanceCache.singletonInstance) {
|
|
25
|
+
DuckDBInstanceCache.singletonInstance = new DuckDBInstanceCache();
|
|
26
|
+
}
|
|
27
|
+
return DuckDBInstanceCache.singletonInstance;
|
|
28
|
+
}
|
|
29
|
+
}
|