@duckdb/node-api 1.2.2-alpha.18 → 1.3.0-alpha.20

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 CHANGED
@@ -140,6 +140,7 @@ const prepared = await connection.prepare('select $1, $2, $3');
140
140
  prepared.bindVarchar(1, 'duck');
141
141
  prepared.bindInteger(2, 42);
142
142
  prepared.bindList(3, listValue([10, 11, 12]), LIST(INTEGER));
143
+ // OR, with type inference: prepared.bindList(3, [10, 11, 12]);
143
144
  const result = await prepared.run();
144
145
  ```
145
146
 
@@ -37,13 +37,13 @@ export declare class DuckDBAppender {
37
37
  appendVarchar(value: string): void;
38
38
  appendBlob(value: Uint8Array): void;
39
39
  appendEnum(value: string, type: DuckDBEnumType): void;
40
- appendList(value: DuckDBListValue, type: DuckDBListType): void;
41
- appendStruct(value: DuckDBStructValue, type: DuckDBStructType): void;
42
- appendArray(value: DuckDBArrayValue, type: DuckDBArrayType): void;
40
+ appendList(value: DuckDBListValue | readonly DuckDBValue[], type?: DuckDBListType): void;
41
+ appendStruct(value: DuckDBStructValue | Readonly<Record<string, DuckDBValue>>, type?: DuckDBStructType): void;
42
+ appendArray(value: DuckDBArrayValue | readonly DuckDBValue[], type?: DuckDBArrayType): void;
43
43
  appendUUID(value: DuckDBUUIDValue): void;
44
44
  appendBit(value: DuckDBBitValue): void;
45
45
  appendVarInt(value: bigint): void;
46
46
  appendNull(): void;
47
- appendValue(value: DuckDBValue, type: DuckDBType): void;
47
+ appendValue(value: DuckDBValue, type?: DuckDBType): void;
48
48
  appendDataChunk(dataChunk: DuckDBDataChunk): void;
49
49
  }
@@ -8,6 +8,8 @@ const node_bindings_1 = __importDefault(require("@duckdb/node-bindings"));
8
8
  const createValue_1 = require("./createValue");
9
9
  const DuckDBLogicalType_1 = require("./DuckDBLogicalType");
10
10
  const DuckDBType_1 = require("./DuckDBType");
11
+ const typeForValue_1 = require("./typeForValue");
12
+ const values_1 = require("./values");
11
13
  class DuckDBAppender {
12
14
  appender;
13
15
  constructor(appender) {
@@ -111,14 +113,14 @@ class DuckDBAppender {
111
113
  this.appendValue(value, type);
112
114
  }
113
115
  appendList(value, type) {
114
- this.appendValue(value, type);
116
+ this.appendValue(value instanceof values_1.DuckDBListValue ? value : (0, values_1.listValue)(value), type);
115
117
  }
116
118
  appendStruct(value, type) {
117
- this.appendValue(value, type);
119
+ this.appendValue(value instanceof values_1.DuckDBStructValue ? value : (0, values_1.structValue)(value), type);
118
120
  }
119
121
  // TODO: MAP (when DuckDB C API supports creating MAP values)
120
122
  appendArray(value, type) {
121
- this.appendValue(value, type);
123
+ this.appendValue(value instanceof values_1.DuckDBArrayValue ? value : (0, values_1.arrayValue)(value), type);
122
124
  }
123
125
  // TODO: UNION (when DuckDB C API supports creating UNION values)
124
126
  appendUUID(value) {
@@ -134,7 +136,7 @@ class DuckDBAppender {
134
136
  node_bindings_1.default.append_null(this.appender);
135
137
  }
136
138
  appendValue(value, type) {
137
- node_bindings_1.default.append_value(this.appender, (0, createValue_1.createValue)(type, value));
139
+ node_bindings_1.default.append_value(this.appender, (0, createValue_1.createValue)(type ? type : (0, typeForValue_1.typeForValue)(value), value));
138
140
  }
139
141
  appendDataChunk(dataChunk) {
140
142
  node_bindings_1.default.append_data_chunk(this.appender, dataChunk.chunk);
@@ -11,6 +11,7 @@ import { DuckDBType } from './DuckDBType';
11
11
  import { DuckDBValue } from './values';
12
12
  export declare class DuckDBConnection {
13
13
  private readonly connection;
14
+ private readonly preparedStatements;
14
15
  constructor(connection: duckdb.Connection);
15
16
  static create(instance?: DuckDBInstance): Promise<DuckDBConnection>;
16
17
  /** Same as disconnectSync. */
@@ -29,6 +30,7 @@ export declare class DuckDBConnection {
29
30
  start(sql: string, values?: DuckDBValue[] | Record<string, DuckDBValue>, types?: DuckDBType[] | Record<string, DuckDBType | undefined>): Promise<DuckDBPendingResult>;
30
31
  startStream(sql: string, values?: DuckDBValue[] | Record<string, DuckDBValue>, types?: DuckDBType[] | Record<string, DuckDBType | undefined>): Promise<DuckDBPendingResult>;
31
32
  prepare(sql: string): Promise<DuckDBPreparedStatement>;
33
+ private createPrepared;
32
34
  extractStatements(sql: string): Promise<DuckDBExtractedStatements>;
33
35
  createAppender(table: string, schema?: string | null, catalog?: string | null): Promise<DuckDBAppender>;
34
36
  }
@@ -10,11 +10,14 @@ const DuckDBExtractedStatements_1 = require("./DuckDBExtractedStatements");
10
10
  const DuckDBInstance_1 = require("./DuckDBInstance");
11
11
  const DuckDBMaterializedResult_1 = require("./DuckDBMaterializedResult");
12
12
  const DuckDBPreparedStatement_1 = require("./DuckDBPreparedStatement");
13
+ const DuckDBPreparedStatementWeakRefCollection_1 = require("./DuckDBPreparedStatementWeakRefCollection");
13
14
  const DuckDBResultReader_1 = require("./DuckDBResultReader");
14
15
  class DuckDBConnection {
15
16
  connection;
17
+ preparedStatements;
16
18
  constructor(connection) {
17
19
  this.connection = connection;
20
+ this.preparedStatements = new DuckDBPreparedStatementWeakRefCollection_1.DuckDBPreparedStatementWeakRefCollection();
18
21
  }
19
22
  static async create(instance) {
20
23
  if (instance) {
@@ -27,6 +30,7 @@ class DuckDBConnection {
27
30
  return this.disconnectSync();
28
31
  }
29
32
  disconnectSync() {
33
+ this.preparedStatements.destroySync();
30
34
  return node_bindings_1.default.disconnect_sync(this.connection);
31
35
  }
32
36
  interrupt() {
@@ -37,9 +41,14 @@ class DuckDBConnection {
37
41
  }
38
42
  async run(sql, values, types) {
39
43
  if (values) {
40
- const prepared = await this.prepare(sql);
41
- prepared.bind(values, types);
42
- return prepared.run();
44
+ const prepared = await this.createPrepared(sql);
45
+ try {
46
+ prepared.bind(values, types);
47
+ return prepared.run();
48
+ }
49
+ finally {
50
+ prepared.destroySync();
51
+ }
43
52
  }
44
53
  else {
45
54
  return new DuckDBMaterializedResult_1.DuckDBMaterializedResult(await node_bindings_1.default.query(this.connection, sql));
@@ -59,11 +68,16 @@ class DuckDBConnection {
59
68
  return reader;
60
69
  }
61
70
  async stream(sql, values, types) {
62
- const prepared = await this.prepare(sql);
63
- if (values) {
64
- prepared.bind(values, types);
71
+ const prepared = await this.createPrepared(sql);
72
+ try {
73
+ if (values) {
74
+ prepared.bind(values, types);
75
+ }
76
+ return prepared.stream();
77
+ }
78
+ finally {
79
+ prepared.destroySync();
65
80
  }
66
- return prepared.stream();
67
81
  }
68
82
  async streamAndRead(sql, values, types) {
69
83
  return new DuckDBResultReader_1.DuckDBResultReader(await this.stream(sql, values, types));
@@ -79,20 +93,35 @@ class DuckDBConnection {
79
93
  return reader;
80
94
  }
81
95
  async start(sql, values, types) {
82
- const prepared = await this.prepare(sql);
83
- if (values) {
84
- prepared.bind(values, types);
96
+ const prepared = await this.createPrepared(sql);
97
+ try {
98
+ if (values) {
99
+ prepared.bind(values, types);
100
+ }
101
+ return prepared.start();
102
+ }
103
+ finally {
104
+ prepared.destroySync();
85
105
  }
86
- return prepared.start();
87
106
  }
88
107
  async startStream(sql, values, types) {
89
- const prepared = await this.prepare(sql);
90
- if (values) {
91
- prepared.bind(values, types);
108
+ const prepared = await this.createPrepared(sql);
109
+ try {
110
+ if (values) {
111
+ prepared.bind(values, types);
112
+ }
113
+ return prepared.startStream();
114
+ }
115
+ finally {
116
+ prepared.destroySync();
92
117
  }
93
- return prepared.startStream();
94
118
  }
95
119
  async prepare(sql) {
120
+ const prepared = await this.createPrepared(sql);
121
+ this.preparedStatements.add(prepared);
122
+ return prepared;
123
+ }
124
+ async createPrepared(sql) {
96
125
  return new DuckDBPreparedStatement_1.DuckDBPreparedStatement(await node_bindings_1.default.prepare(this.connection, sql));
97
126
  }
98
127
  async extractStatements(sql) {
@@ -100,7 +129,7 @@ class DuckDBConnection {
100
129
  if (statement_count === 0) {
101
130
  throw new Error(`Failed to extract statements: ${node_bindings_1.default.extract_statements_error(extracted_statements)}`);
102
131
  }
103
- return new DuckDBExtractedStatements_1.DuckDBExtractedStatements(this.connection, extracted_statements, statement_count);
132
+ return new DuckDBExtractedStatements_1.DuckDBExtractedStatements(this.connection, extracted_statements, statement_count, this.preparedStatements);
104
133
  }
105
134
  async createAppender(table, schema, catalog) {
106
135
  return new DuckDBAppender_1.DuckDBAppender(node_bindings_1.default.appender_create_ext(this.connection, catalog ?? null, schema ?? null, table));
@@ -29,6 +29,10 @@ class DuckDBDataChunk {
29
29
  return node_bindings_1.default.data_chunk_get_size(this.chunk);
30
30
  }
31
31
  set rowCount(count) {
32
+ const maxRowCount = node_bindings_1.default.vector_size();
33
+ if (count > maxRowCount) {
34
+ throw new Error(`A data chunk cannot have more than ${maxRowCount} rows`);
35
+ }
32
36
  node_bindings_1.default.data_chunk_set_size(this.chunk, count);
33
37
  }
34
38
  getColumnVector(columnIndex) {
@@ -1,10 +1,12 @@
1
1
  import duckdb from '@duckdb/node-bindings';
2
2
  import { DuckDBPreparedStatement } from './DuckDBPreparedStatement';
3
+ import { DuckDBPreparedStatementCollection } from './DuckDBPreparedStatementCollection';
3
4
  export declare class DuckDBExtractedStatements {
4
5
  private readonly connection;
5
6
  private readonly extracted_statements;
6
7
  private readonly statement_count;
7
- constructor(connection: duckdb.Connection, extracted_statements: duckdb.ExtractedStatements, statement_count: number);
8
+ private readonly preparedStatements?;
9
+ constructor(connection: duckdb.Connection, extracted_statements: duckdb.ExtractedStatements, statement_count: number, preparedStatements?: DuckDBPreparedStatementCollection);
8
10
  get count(): number;
9
11
  prepare(index: number): Promise<DuckDBPreparedStatement>;
10
12
  }
@@ -10,16 +10,22 @@ class DuckDBExtractedStatements {
10
10
  connection;
11
11
  extracted_statements;
12
12
  statement_count;
13
- constructor(connection, extracted_statements, statement_count) {
13
+ preparedStatements;
14
+ constructor(connection, extracted_statements, statement_count, preparedStatements) {
14
15
  this.connection = connection;
15
16
  this.extracted_statements = extracted_statements;
16
17
  this.statement_count = statement_count;
18
+ this.preparedStatements = preparedStatements;
17
19
  }
18
20
  get count() {
19
21
  return this.statement_count;
20
22
  }
21
23
  async prepare(index) {
22
- return new DuckDBPreparedStatement_1.DuckDBPreparedStatement(await node_bindings_1.default.prepare_extracted_statement(this.connection, this.extracted_statements, index));
24
+ const prepared = new DuckDBPreparedStatement_1.DuckDBPreparedStatement(await node_bindings_1.default.prepare_extracted_statement(this.connection, this.extracted_statements, index));
25
+ if (this.preparedStatements) {
26
+ this.preparedStatements.add(prepared);
27
+ }
28
+ return prepared;
23
29
  }
24
30
  }
25
31
  exports.DuckDBExtractedStatements = DuckDBExtractedStatements;
@@ -10,6 +10,7 @@ import { DuckDBArrayValue, DuckDBBitValue, DuckDBDateValue, DuckDBDecimalValue,
10
10
  export declare class DuckDBPreparedStatement {
11
11
  private readonly prepared_statement;
12
12
  constructor(prepared_statement: duckdb.PreparedStatement);
13
+ destroySync(): void;
13
14
  get statementType(): StatementType;
14
15
  get parameterCount(): number;
15
16
  parameterName(parameterIndex: number): string;
@@ -44,13 +45,13 @@ export declare class DuckDBPreparedStatement {
44
45
  bindVarchar(parameterIndex: number, value: string): void;
45
46
  bindBlob(parameterIndex: number, value: Uint8Array): void;
46
47
  bindEnum(parameterIndex: number, value: string, type: DuckDBEnumType): void;
47
- bindArray(parameterIndex: number, value: DuckDBArrayValue, type: DuckDBArrayType): void;
48
- bindList(parameterIndex: number, value: DuckDBListValue, type: DuckDBListType): void;
49
- bindStruct(parameterIndex: number, value: DuckDBStructValue, type: DuckDBStructType): void;
48
+ bindArray(parameterIndex: number, value: DuckDBArrayValue | readonly DuckDBValue[], type?: DuckDBArrayType): void;
49
+ bindList(parameterIndex: number, value: DuckDBListValue | readonly DuckDBValue[], type?: DuckDBListType): void;
50
+ bindStruct(parameterIndex: number, value: DuckDBStructValue | Readonly<Record<string, DuckDBValue>>, type?: DuckDBStructType): void;
50
51
  bindUUID(parameterIndex: number, value: DuckDBUUIDValue): void;
51
52
  bindBit(parameterIndex: number, value: DuckDBBitValue): void;
52
53
  bindNull(parameterIndex: number): void;
53
- bindValue(parameterIndex: number, value: DuckDBValue, type: DuckDBType): void;
54
+ bindValue(parameterIndex: number, value: DuckDBValue, type?: DuckDBType): void;
54
55
  bind(values: DuckDBValue[] | Record<string, DuckDBValue>, types?: DuckDBType[] | Record<string, DuckDBType | undefined>): void;
55
56
  run(): Promise<DuckDBMaterializedResult>;
56
57
  runAndRead(): Promise<DuckDBResultReader>;
@@ -13,11 +13,15 @@ const DuckDBResult_1 = require("./DuckDBResult");
13
13
  const DuckDBResultReader_1 = require("./DuckDBResultReader");
14
14
  const DuckDBType_1 = require("./DuckDBType");
15
15
  const typeForValue_1 = require("./typeForValue");
16
+ const values_1 = require("./values");
16
17
  class DuckDBPreparedStatement {
17
18
  prepared_statement;
18
19
  constructor(prepared_statement) {
19
20
  this.prepared_statement = prepared_statement;
20
21
  }
22
+ destroySync() {
23
+ return node_bindings_1.default.destroy_prepare_sync(this.prepared_statement);
24
+ }
21
25
  get statementType() {
22
26
  return node_bindings_1.default.prepared_statement_type(this.prepared_statement);
23
27
  }
@@ -121,13 +125,13 @@ class DuckDBPreparedStatement {
121
125
  this.bindValue(parameterIndex, value, type);
122
126
  }
123
127
  bindArray(parameterIndex, value, type) {
124
- this.bindValue(parameterIndex, value, type);
128
+ this.bindValue(parameterIndex, value instanceof values_1.DuckDBArrayValue ? value : (0, values_1.arrayValue)(value), type);
125
129
  }
126
130
  bindList(parameterIndex, value, type) {
127
- this.bindValue(parameterIndex, value, type);
131
+ this.bindValue(parameterIndex, value instanceof values_1.DuckDBListValue ? value : (0, values_1.listValue)(value), type);
128
132
  }
129
133
  bindStruct(parameterIndex, value, type) {
130
- this.bindValue(parameterIndex, value, type);
134
+ this.bindValue(parameterIndex, value instanceof values_1.DuckDBStructValue ? value : (0, values_1.structValue)(value), type);
131
135
  }
132
136
  // TODO: bind MAP, UNION
133
137
  bindUUID(parameterIndex, value) {
@@ -140,24 +144,19 @@ class DuckDBPreparedStatement {
140
144
  node_bindings_1.default.bind_null(this.prepared_statement, parameterIndex);
141
145
  }
142
146
  bindValue(parameterIndex, value, type) {
143
- node_bindings_1.default.bind_value(this.prepared_statement, parameterIndex, (0, createValue_1.createValue)(type, value));
147
+ node_bindings_1.default.bind_value(this.prepared_statement, parameterIndex, (0, createValue_1.createValue)(type ? type : (0, typeForValue_1.typeForValue)(value), value));
144
148
  }
145
149
  bind(values, types) {
146
150
  if (Array.isArray(values)) {
147
151
  const typesIsArray = Array.isArray(types);
148
152
  for (let i = 0; i < values.length; i++) {
149
- this.bindValue(i + 1, values[i], typesIsArray ? types[i] : (0, typeForValue_1.typeForValue)(values[i]));
153
+ this.bindValue(i + 1, values[i], typesIsArray ? types[i] : undefined);
150
154
  }
151
155
  }
152
156
  else {
153
157
  const typesIsRecord = types && !Array.isArray(types);
154
158
  for (const key in values) {
155
- const index = this.parameterIndex(key);
156
- let type = typesIsRecord ? types[key] : undefined;
157
- if (type === undefined) {
158
- type = (0, typeForValue_1.typeForValue)(values[key]);
159
- }
160
- this.bindValue(index, values[key], type);
159
+ this.bindValue(this.parameterIndex(key), values[key], typesIsRecord ? types[key] : undefined);
161
160
  }
162
161
  }
163
162
  }
@@ -0,0 +1,4 @@
1
+ import { DuckDBPreparedStatement } from './DuckDBPreparedStatement';
2
+ export interface DuckDBPreparedStatementCollection {
3
+ add(prepared: DuckDBPreparedStatement): void;
4
+ }
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,8 @@
1
+ import { DuckDBPreparedStatement } from './DuckDBPreparedStatement';
2
+ import { DuckDBPreparedStatementCollection } from './DuckDBPreparedStatementCollection';
3
+ export declare class DuckDBPreparedStatementWeakRefCollection implements DuckDBPreparedStatementCollection {
4
+ preparedStatements: WeakRef<DuckDBPreparedStatement>[];
5
+ add(prepared: DuckDBPreparedStatement): void;
6
+ destroySync(): void;
7
+ private prune;
8
+ }
@@ -0,0 +1,23 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DuckDBPreparedStatementWeakRefCollection = void 0;
4
+ class DuckDBPreparedStatementWeakRefCollection {
5
+ preparedStatements = [];
6
+ add(prepared) {
7
+ this.prune();
8
+ this.preparedStatements.push(new WeakRef(prepared));
9
+ }
10
+ destroySync() {
11
+ for (const preparedRef of this.preparedStatements) {
12
+ const prepared = preparedRef.deref();
13
+ if (prepared) {
14
+ prepared.destroySync();
15
+ }
16
+ }
17
+ this.preparedStatements = [];
18
+ }
19
+ prune() {
20
+ this.preparedStatements = this.preparedStatements.filter((ref) => !!ref.deref());
21
+ }
22
+ }
23
+ exports.DuckDBPreparedStatementWeakRefCollection = DuckDBPreparedStatementWeakRefCollection;
package/lib/duckdb.d.ts CHANGED
@@ -10,6 +10,7 @@ export * from './DuckDBLogicalType';
10
10
  export * from './DuckDBMaterializedResult';
11
11
  export * from './DuckDBPendingResult';
12
12
  export * from './DuckDBPreparedStatement';
13
+ export * from './DuckDBPreparedStatementCollection';
13
14
  export * from './DuckDBResult';
14
15
  export * from './DuckDBType';
15
16
  export * from './DuckDBTypeId';
package/lib/duckdb.js CHANGED
@@ -31,6 +31,7 @@ __exportStar(require("./DuckDBLogicalType"), exports);
31
31
  __exportStar(require("./DuckDBMaterializedResult"), exports);
32
32
  __exportStar(require("./DuckDBPendingResult"), exports);
33
33
  __exportStar(require("./DuckDBPreparedStatement"), exports);
34
+ __exportStar(require("./DuckDBPreparedStatementCollection"), exports);
34
35
  __exportStar(require("./DuckDBResult"), exports);
35
36
  __exportStar(require("./DuckDBType"), exports);
36
37
  __exportStar(require("./DuckDBTypeId"), exports);
package/package.json CHANGED
@@ -1,11 +1,11 @@
1
1
  {
2
2
  "name": "@duckdb/node-api",
3
- "version": "1.2.2-alpha.18",
3
+ "version": "1.3.0-alpha.20",
4
4
  "license": "MIT",
5
5
  "main": "./lib/index.js",
6
6
  "types": "./lib/index.d.ts",
7
7
  "dependencies": {
8
- "@duckdb/node-bindings": "1.2.2-alpha.18"
8
+ "@duckdb/node-bindings": "1.3.0-alpha.20"
9
9
  },
10
10
  "repository": {
11
11
  "type": "git",