Skip to content

Commit 221141d

Browse files
authored
Merge pull request #44 from duckdb/jray/logical-type-alias-and-cleanup
logical type alias and cleanup
2 parents 47d652c + b00b6e2 commit 221141d

File tree

9 files changed

+247
-218
lines changed

9 files changed

+247
-218
lines changed

api/pkgs/@duckdb/node-api/README.md

Lines changed: 38 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@ This is a high-level API meant for applications. It depends on low-level binding
1818
Some features are not yet complete:
1919
- Friendlier APIs for convering results to common JS data structures.
2020
- Friendlier APIs for converting values of specialized and complex DuckDB types to common JS types.
21-
- Automatic memory management (i.e. avoiding the need to call `dispose` manually in most cases).
2221
- Appending and binding advanced data types. (Additional DuckDB C API support needed.)
2322
- Writing to data chunk vectors. (Directly writing to binary buffers is challenging to support using the Node Addon API.)
2423
- User-defined types & functions. (Support for this was added to the DuckDB C API in v1.1.0.)
@@ -70,33 +69,18 @@ Set configuration options:
7069
const instance = await DuckDBInstance.create('my_duckdb.db', { threads: '4' });
7170
```
7271

73-
Dispose:
74-
```ts
75-
await instance.dispose();
76-
```
77-
7872
### Connect
7973

8074
```ts
8175
const connection = await instance.connect();
8276
```
8377

84-
Dispose:
85-
```ts
86-
await connection.dispose();
87-
```
88-
8978
### Run SQL
9079

9180
```ts
9281
const result = await connection.run('from test_all_types()');
9382
```
9483

95-
Dispose:
96-
```ts
97-
result.dispose();
98-
```
99-
10084
### Parameterize SQL
10185

10286
```ts
@@ -106,12 +90,6 @@ prepared.bindInteger(2, 42);
10690
const result = await prepared.run();
10791
```
10892

109-
Dispose:
110-
```ts
111-
result.dispose();
112-
prepared.dispose();
113-
```
114-
11593
### Inspect Result
11694

11795
Get column names and types:
@@ -155,11 +133,6 @@ for (let columnIndex = 0; columnIndex < columnCount; columnIndex++) {
155133
}
156134
```
157135

158-
Dispose data chunk:
159-
```ts
160-
chunk.dispose();
161-
```
162-
163136
### Inspect Data Types
164137

165138
```ts
@@ -197,6 +170,11 @@ if (columnType.typeId === DuckDBTypeId.UNION) {
197170
const unionMemberTags = columnType.memberTags;
198171
const unionMemberTypes = columnType.memberTypes;
199172
}
173+
174+
// For the JSON type (https://duckdb.org/docs/data/json/json_type)
175+
if (columnType.alias === 'JSON') {
176+
const json = JSON.parse(columnValue);
177+
}
200178
```
201179

202180
Every type implements toString, matching DuckDB's type-to-string conversion.
@@ -313,25 +291,25 @@ if (columnType.typeId === DuckDBTypeId.UUID) {
313291
### Append To Table
314292

315293
```ts
316-
const createTableResult = await connection.run(`create or replace table target_table(i integer, v varchar)`);
317-
createTableResult.dispose();
294+
await connection.run(`create or replace table target_table(i integer, v varchar)`);
318295

319296
const appender = await connection.createAppender('main', 'target_table');
320-
try {
321-
appender.appendInteger(42);
322-
appender.appendVarchar('duck');
323-
appender.endRow();
324-
appender.appendInteger(123);
325-
appender.appendVarchar('mallard');
326-
appender.endRow();
327-
appender.flush();
328-
appender.appendInteger(17);
329-
appender.appendVarchar('goose');
330-
appender.endRow();
331-
appender.close(); // also flushes
332-
} finally {
333-
appender.dispose();
334-
}
297+
298+
appender.appendInteger(42);
299+
appender.appendVarchar('duck');
300+
appender.endRow();
301+
302+
appender.appendInteger(123);
303+
appender.appendVarchar('mallard');
304+
appender.endRow();
305+
306+
appender.flush();
307+
308+
appender.appendInteger(17);
309+
appender.appendVarchar('goose');
310+
appender.endRow();
311+
312+
appender.close(); // also flushes
335313
```
336314

337315
### Extract Statements
@@ -343,24 +321,15 @@ const extractedStatements = await connection.extractStatements(`
343321
drop table numbers;
344322
`);
345323
const parameterValues = [10, 7];
346-
try {
347-
const statementCount = extractedStatements.count;
348-
for (let statementIndex = 0; statementIndex < statementCount; statementIndex++) {
349-
const prepared = await extractedStatements.prepare(statementIndex);
350-
try {
351-
let parameterCount = prepared.parameterCount;
352-
for (let parameterIndex = 1; parameterIndex <= parameterCount; parameterIndex++) {
353-
prepared.bindInteger(parameterIndex, parameterValues.shift());
354-
}
355-
const result = await prepared.run();
356-
// ...
357-
result.dispose();
358-
} finally {
359-
prepared.dispose();
360-
}
324+
const statementCount = extractedStatements.count;
325+
for (let statementIndex = 0; statementIndex < statementCount; statementIndex++) {
326+
const prepared = await extractedStatements.prepare(statementIndex);
327+
let parameterCount = prepared.parameterCount;
328+
for (let parameterIndex = 1; parameterIndex <= parameterCount; parameterIndex++) {
329+
prepared.bindInteger(parameterIndex, parameterValues.shift());
361330
}
362-
} finally {
363-
extractedStatements.dispose();
331+
const result = await prepared.run();
332+
// ...
364333
}
365334
```
366335

@@ -376,21 +345,12 @@ async function sleep(ms) {
376345
}
377346

378347
const prepared = await connection.prepare('from range(10_000_000)');
379-
try {
380-
const pending = prepared.start();
381-
try {
382-
while (pending.runTask() !== DuckDBPendingResultState.RESULT_READY) {
383-
console.log('not ready');
384-
await sleep(1);
385-
}
386-
console.log('ready');
387-
const result = await pending.getResult();
388-
// ...
389-
result.dispose();
390-
} finally {
391-
pending.dispose();
392-
}
393-
} finally {
394-
prepared.dispose();
395-
}
348+
const pending = prepared.start();
349+
while (pending.runTask() !== DuckDBPendingResultState.RESULT_READY) {
350+
console.log('not ready');
351+
await sleep(1);
352+
}
353+
console.log('ready');
354+
const result = await pending.getResult();
355+
// ...
396356
```

api/src/DuckDBAppender.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,9 @@ export class DuckDBAppender {
2424
return duckdb.appender_column_count(this.appender);
2525
}
2626
public columnType(columnIndex: number): DuckDBType {
27-
return DuckDBLogicalType.consumeAsType(duckdb.appender_column_type(this.appender, columnIndex));
27+
return DuckDBLogicalType.create(
28+
duckdb.appender_column_type(this.appender, columnIndex)
29+
).asType();
2830
}
2931
public endRow() {
3032
duckdb.appender_end_row(this.appender);

api/src/DuckDBLogicalType.ts

Lines changed: 39 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -45,11 +45,6 @@ export class DuckDBLogicalType {
4545
protected constructor(logical_type: duckdb.LogicalType) {
4646
this.logical_type = logical_type;
4747
}
48-
static consumeAsType(logical_type: duckdb.LogicalType): DuckDBType {
49-
const logicalType = DuckDBLogicalType.create(logical_type);
50-
const type = logicalType.asType();
51-
return type;
52-
}
5348
static create(logical_type: duckdb.LogicalType): DuckDBLogicalType {
5449
switch (duckdb.get_type_id(logical_type)) {
5550
case duckdb.Type.DECIMAL:
@@ -147,60 +142,61 @@ export class DuckDBLogicalType {
147142
public get typeId(): DuckDBTypeId {
148143
return duckdb.get_type_id(this.logical_type) as number as DuckDBTypeId;
149144
}
150-
public get alias(): string | null {
151-
return duckdb.logical_type_get_alias(this.logical_type);
145+
public get alias(): string | undefined {
146+
return duckdb.logical_type_get_alias(this.logical_type) || undefined;
152147
}
153148
public set alias(newAlias: string) {
154149
duckdb.logical_type_set_alias(this.logical_type, newAlias);
155150
}
156151
public asType(): DuckDBType {
152+
const alias = this.alias;
157153
switch (this.typeId) {
158154
case DuckDBTypeId.BOOLEAN:
159-
return DuckDBBooleanType.instance;
155+
return DuckDBBooleanType.create(alias);
160156
case DuckDBTypeId.TINYINT:
161-
return DuckDBTinyIntType.instance;
157+
return DuckDBTinyIntType.create(alias);
162158
case DuckDBTypeId.SMALLINT:
163-
return DuckDBSmallIntType.instance;
159+
return DuckDBSmallIntType.create(alias);
164160
case DuckDBTypeId.INTEGER:
165-
return DuckDBIntegerType.instance;
161+
return DuckDBIntegerType.create(alias);
166162
case DuckDBTypeId.BIGINT:
167-
return DuckDBBigIntType.instance;
163+
return DuckDBBigIntType.create(alias);
168164
case DuckDBTypeId.UTINYINT:
169-
return DuckDBUTinyIntType.instance;
165+
return DuckDBUTinyIntType.create(alias);
170166
case DuckDBTypeId.USMALLINT:
171-
return DuckDBUSmallIntType.instance;
167+
return DuckDBUSmallIntType.create(alias);
172168
case DuckDBTypeId.UINTEGER:
173-
return DuckDBUIntegerType.instance;
169+
return DuckDBUIntegerType.create(alias);
174170
case DuckDBTypeId.UBIGINT:
175-
return DuckDBUBigIntType.instance;
171+
return DuckDBUBigIntType.create(alias);
176172
case DuckDBTypeId.FLOAT:
177-
return DuckDBFloatType.instance;
173+
return DuckDBFloatType.create(alias);
178174
case DuckDBTypeId.DOUBLE:
179-
return DuckDBDoubleType.instance;
175+
return DuckDBDoubleType.create(alias);
180176
case DuckDBTypeId.TIMESTAMP:
181-
return DuckDBTimestampType.instance;
177+
return DuckDBTimestampType.create(alias);
182178
case DuckDBTypeId.DATE:
183-
return DuckDBDateType.instance;
179+
return DuckDBDateType.create(alias);
184180
case DuckDBTypeId.TIME:
185-
return DuckDBTimeType.instance;
181+
return DuckDBTimeType.create(alias);
186182
case DuckDBTypeId.INTERVAL:
187-
return DuckDBIntervalType.instance;
183+
return DuckDBIntervalType.create(alias);
188184
case DuckDBTypeId.HUGEINT:
189-
return DuckDBHugeIntType.instance;
185+
return DuckDBHugeIntType.create(alias);
190186
case DuckDBTypeId.UHUGEINT:
191-
return DuckDBUHugeIntType.instance;
187+
return DuckDBUHugeIntType.create(alias);
192188
case DuckDBTypeId.VARCHAR:
193-
return DuckDBVarCharType.instance;
189+
return DuckDBVarCharType.create(alias);
194190
case DuckDBTypeId.BLOB:
195-
return DuckDBBlobType.instance;
191+
return DuckDBBlobType.create(alias);
196192
case DuckDBTypeId.DECIMAL:
197193
throw new Error('Expected override');
198194
case DuckDBTypeId.TIMESTAMP_S:
199-
return DuckDBTimestampSecondsType.instance;
195+
return DuckDBTimestampSecondsType.create(alias);
200196
case DuckDBTypeId.TIMESTAMP_MS:
201-
return DuckDBTimestampMillisecondsType.instance;
197+
return DuckDBTimestampMillisecondsType.create(alias);
202198
case DuckDBTypeId.TIMESTAMP_NS:
203-
return DuckDBTimestampNanosecondsType.instance;
199+
return DuckDBTimestampNanosecondsType.create(alias);
204200
case DuckDBTypeId.ENUM:
205201
throw new Error('Expected override');
206202
case DuckDBTypeId.LIST:
@@ -212,21 +208,21 @@ export class DuckDBLogicalType {
212208
case DuckDBTypeId.ARRAY:
213209
throw new Error('Expected override');
214210
case DuckDBTypeId.UUID:
215-
return DuckDBUUIDType.instance;
211+
return DuckDBUUIDType.create(alias);
216212
case DuckDBTypeId.UNION:
217213
throw new Error('Expected override');
218214
case DuckDBTypeId.BIT:
219-
return DuckDBBitType.instance;
215+
return DuckDBBitType.create(alias);
220216
case DuckDBTypeId.TIME_TZ:
221-
return DuckDBTimeTZType.instance;
217+
return DuckDBTimeTZType.create(alias);
222218
case DuckDBTypeId.TIMESTAMP_TZ:
223-
return DuckDBTimestampTZType.instance;
219+
return DuckDBTimestampTZType.create(alias);
224220
case DuckDBTypeId.ANY:
225-
return DuckDBAnyType.instance;
221+
return DuckDBAnyType.create(alias);
226222
case DuckDBTypeId.VARINT:
227-
return DuckDBVarIntType.instance;
223+
return DuckDBVarIntType.create(alias);
228224
case DuckDBTypeId.SQLNULL:
229-
return DuckDBSQLNullType.instance;
225+
return DuckDBSQLNullType.create(alias);
230226
default:
231227
throw new Error(`Unexpected type id: ${this.typeId}`);
232228
}
@@ -246,7 +242,7 @@ export class DuckDBDecimalLogicalType extends DuckDBLogicalType {
246242
) as number as DuckDBTypeId;
247243
}
248244
public override asType(): DuckDBDecimalType {
249-
return new DuckDBDecimalType(this.width, this.scale);
245+
return new DuckDBDecimalType(this.width, this.scale, this.alias);
250246
}
251247
}
252248

@@ -271,7 +267,7 @@ export class DuckDBEnumLogicalType extends DuckDBLogicalType {
271267
) as number as DuckDBTypeId;
272268
}
273269
public override asType(): DuckDBEnumType {
274-
return new DuckDBEnumType(this.values(), this.internalTypeId);
270+
return new DuckDBEnumType(this.values(), this.internalTypeId, this.alias);
275271
}
276272
}
277273

@@ -282,7 +278,7 @@ export class DuckDBListLogicalType extends DuckDBLogicalType {
282278
);
283279
}
284280
public override asType(): DuckDBListType {
285-
return new DuckDBListType(this.valueType.asType());
281+
return new DuckDBListType(this.valueType.asType(), this.alias);
286282
}
287283
}
288284

@@ -326,7 +322,7 @@ export class DuckDBStructLogicalType extends DuckDBLogicalType {
326322
return valueTypes;
327323
}
328324
public override asType(): DuckDBStructType {
329-
return new DuckDBStructType(this.entryNames(), this.entryTypes());
325+
return new DuckDBStructType(this.entryNames(), this.entryTypes(), this.alias);
330326
}
331327
}
332328

@@ -342,7 +338,7 @@ export class DuckDBMapLogicalType extends DuckDBLogicalType {
342338
);
343339
}
344340
public override asType(): DuckDBMapType {
345-
return new DuckDBMapType(this.keyType.asType(), this.valueType.asType());
341+
return new DuckDBMapType(this.keyType.asType(), this.valueType.asType(), this.alias);
346342
}
347343
}
348344

@@ -356,7 +352,7 @@ export class DuckDBArrayLogicalType extends DuckDBLogicalType {
356352
return duckdb.array_type_array_size(this.logical_type);
357353
}
358354
public override asType(): DuckDBArrayType {
359-
return new DuckDBArrayType(this.valueType.asType(), this.length);
355+
return new DuckDBArrayType(this.valueType.asType(), this.length, this.alias);
360356
}
361357
}
362358

@@ -400,6 +396,6 @@ export class DuckDBUnionLogicalType extends DuckDBLogicalType {
400396
return valueTypes;
401397
}
402398
public override asType(): DuckDBUnionType {
403-
return new DuckDBUnionType(this.memberTags(), this.memberTypes());
399+
return new DuckDBUnionType(this.memberTags(), this.memberTypes(), this.alias);
404400
}
405401
}

api/src/DuckDBResult.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,9 +34,9 @@ export class DuckDBResult {
3434
);
3535
}
3636
public columnType(columnIndex: number): DuckDBType {
37-
return DuckDBLogicalType.consumeAsType(
37+
return DuckDBLogicalType.create(
3838
duckdb.column_logical_type(this.result, columnIndex)
39-
);
39+
).asType();
4040
}
4141
public get rowsChanged(): number {
4242
return duckdb.rows_changed(this.result);

0 commit comments

Comments
 (0)