Skip to content

Commit 323bf1e

Browse files
authored
Merge pull request #187 from duckdb/jray/column-names-and-types-json
column names and types json
2 parents 622aa32 + ee4f7fb commit 323bf1e

File tree

9 files changed

+435
-47
lines changed

9 files changed

+435
-47
lines changed

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

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -405,6 +405,127 @@ const columnsObject = reader.getColumnsObjectJson();
405405
// }
406406
```
407407

408+
Column names and types can also be serialized to JSON:
409+
```ts
410+
const columnNamesAndTypes = reader.columnNamesAndTypesJson();
411+
// {
412+
// "columnNames": [
413+
// "int_array",
414+
// "struct",
415+
// "map",
416+
// "union"
417+
// ],
418+
// "columnTypes": [
419+
// {
420+
// "typeId": 24,
421+
// "valueType": {
422+
// "typeId": 4
423+
// }
424+
// },
425+
// {
426+
// "typeId": 25,
427+
// "entryNames": [
428+
// "a",
429+
// "b"
430+
// ],
431+
// "entryTypes": [
432+
// {
433+
// "typeId": 4
434+
// },
435+
// {
436+
// "typeId": 17
437+
// }
438+
// ]
439+
// },
440+
// {
441+
// "typeId": 26,
442+
// "keyType": {
443+
// "typeId": 17
444+
// },
445+
// "valueType": {
446+
// "typeId": 17
447+
// }
448+
// },
449+
// {
450+
// "typeId": 28,
451+
// "memberTags": [
452+
// "name",
453+
// "age"
454+
// ],
455+
// "memberTypes": [
456+
// {
457+
// "typeId": 17
458+
// },
459+
// {
460+
// "typeId": 3
461+
// }
462+
// ]
463+
// }
464+
// ]
465+
// }
466+
467+
const columnNameAndTypeObjects = reader.columnNameAndTypeObjectsJson();
468+
// [
469+
// {
470+
// "columnName": "int_array",
471+
// "columnType": {
472+
// "typeId": 24,
473+
// "valueType": {
474+
// "typeId": 4
475+
// }
476+
// }
477+
// },
478+
// {
479+
// "columnName": "struct",
480+
// "columnType": {
481+
// "typeId": 25,
482+
// "entryNames": [
483+
// "a",
484+
// "b"
485+
// ],
486+
// "entryTypes": [
487+
// {
488+
// "typeId": 4
489+
// },
490+
// {
491+
// "typeId": 17
492+
// }
493+
// ]
494+
// }
495+
// },
496+
// {
497+
// "columnName": "map",
498+
// "columnType": {
499+
// "typeId": 26,
500+
// "keyType": {
501+
// "typeId": 17
502+
// },
503+
// "valueType": {
504+
// "typeId": 17
505+
// }
506+
// }
507+
// },
508+
// {
509+
// "columnName": "union",
510+
// "columnType": {
511+
// "typeId": 28,
512+
// "memberTags": [
513+
// "name",
514+
// "age"
515+
// ],
516+
// "memberTypes": [
517+
// {
518+
// "typeId": 17
519+
// },
520+
// {
521+
// "typeId": 3
522+
// }
523+
// ]
524+
// }
525+
// }
526+
// ]
527+
```
528+
408529
### Fetch Chunks
409530

410531
Fetch all chunks:

api/src/DuckDBResult.ts

Lines changed: 30 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import { DuckDBDataChunk } from './DuckDBDataChunk';
33
import { DuckDBLogicalType } from './DuckDBLogicalType';
44
import { DuckDBType } from './DuckDBType';
55
import { DuckDBTypeId } from './DuckDBTypeId';
6-
import { DuckDBValueToJsonConverter, Json } from './DuckDBValueToJsonConverter';
6+
import { DuckDBValueToJsonConverter } from './DuckDBValueToJsonConverter';
7+
import { Json } from './Json';
78
import { convertColumnsFromChunks } from './convertColumnsFromChunks';
89
import { convertColumnsObjectFromChunks } from './convertColumnsObjectFromChunks';
910
import { convertRowObjectsFromChunks } from './convertRowObjectsFromChunks';
@@ -72,6 +73,9 @@ export class DuckDBResult {
7273
duckdb.column_logical_type(this.result, columnIndex)
7374
).asType();
7475
}
76+
public columnTypeJson(columnIndex: number): Json {
77+
return this.columnType(columnIndex).toJson();
78+
}
7579
public columnTypes(): DuckDBType[] {
7680
const columnTypes: DuckDBType[] = [];
7781
const columnCount = this.columnCount;
@@ -80,6 +84,31 @@ export class DuckDBResult {
8084
}
8185
return columnTypes;
8286
}
87+
public columnTypesJson(): Json {
88+
const columnTypesJson: Json[] = [];
89+
const columnCount = this.columnCount;
90+
for (let columnIndex = 0; columnIndex < columnCount; columnIndex++) {
91+
columnTypesJson.push(this.columnTypeJson(columnIndex));
92+
}
93+
return columnTypesJson;
94+
}
95+
public columnNamesAndTypesJson(): Json {
96+
return {
97+
columnNames: this.columnNames(),
98+
columnTypes: this.columnTypesJson(),
99+
};
100+
}
101+
public columnNameAndTypeObjectsJson(): Json {
102+
const columnNameAndTypeObjects: Json[] = [];
103+
const columnCount = this.columnCount;
104+
for (let columnIndex = 0; columnIndex < columnCount; columnIndex++) {
105+
columnNameAndTypeObjects.push({
106+
columnName: this.columnName(columnIndex),
107+
columnType: this.columnTypeJson(columnIndex),
108+
});
109+
}
110+
return columnNameAndTypeObjects;
111+
}
83112
public get isStreaming(): boolean {
84113
return duckdb.result_is_streaming(this.result);
85114
}

api/src/DuckDBResultReader.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,12 +7,13 @@ import { DuckDBLogicalType } from './DuckDBLogicalType';
77
import { DuckDBResult } from './DuckDBResult';
88
import { DuckDBType } from './DuckDBType';
99
import { DuckDBTypeId } from './DuckDBTypeId';
10-
import { DuckDBValueToJsonConverter, Json } from './DuckDBValueToJsonConverter';
10+
import { DuckDBValueToJsonConverter } from './DuckDBValueToJsonConverter';
1111
import { ResultReturnType, StatementType } from './enums';
1212
import { getColumnsFromChunks } from './getColumnsFromChunks';
1313
import { getColumnsObjectFromChunks } from './getColumnsObjectFromChunks';
1414
import { getRowObjectsFromChunks } from './getRowObjectsFromChunks';
1515
import { getRowsFromChunks } from './getRowsFromChunks';
16+
import { Json } from './Json';
1617
import { DuckDBValue } from './values';
1718

1819
interface ChunkSizeRun {
@@ -63,9 +64,21 @@ export class DuckDBResultReader {
6364
public columnType(columnIndex: number): DuckDBType {
6465
return this.result.columnType(columnIndex);
6566
}
67+
public columnTypeJson(columnIndex: number): Json {
68+
return this.result.columnTypeJson(columnIndex);
69+
}
6670
public columnTypes(): DuckDBType[] {
6771
return this.result.columnTypes();
6872
}
73+
public columnTypesJson(): Json {
74+
return this.result.columnTypesJson();
75+
}
76+
public columnNamesAndTypesJson(): Json {
77+
return this.result.columnNamesAndTypesJson();
78+
}
79+
public columnNameAndTypeObjectsJson(): Json {
80+
return this.result.columnNameAndTypeObjectsJson();
81+
}
6982
public get rowsChanged(): number {
7083
return this.result.rowsChanged;
7184
}

api/src/DuckDBType.ts

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import duckdb from '@duckdb/node-bindings';
22
import { DuckDBLogicalType } from './DuckDBLogicalType';
33
import { DuckDBTypeId } from './DuckDBTypeId';
4+
import { Json } from './Json';
45
import { quotedIdentifier, quotedString } from './sql';
56
import {
67
DuckDBDateValue,
@@ -33,6 +34,12 @@ export abstract class BaseDuckDBType<T extends DuckDBTypeId> {
3334
}
3435
return logicalType;
3536
}
37+
public toJson(): Json {
38+
return {
39+
typeId: this.typeId,
40+
...(this.alias ? { alias: this.alias } : {}),
41+
};
42+
}
3643
}
3744

3845
export class DuckDBBooleanType extends BaseDuckDBType<DuckDBTypeId.BOOLEAN> {
@@ -401,6 +408,14 @@ export class DuckDBDecimalType extends BaseDuckDBType<DuckDBTypeId.DECIMAL> {
401408
}
402409
return logicalType;
403410
}
411+
public override toJson(): Json {
412+
return {
413+
typeId: this.typeId,
414+
width: this.width,
415+
scale: this.scale,
416+
...(this.alias ? { alias: this.alias } : {}),
417+
};
418+
}
404419
public static readonly default = new DuckDBDecimalType(18, 3);
405420
}
406421
export function DECIMAL(
@@ -532,6 +547,14 @@ export class DuckDBEnumType extends BaseDuckDBType<DuckDBTypeId.ENUM> {
532547
}
533548
return logicalType;
534549
}
550+
public override toJson(): Json {
551+
return {
552+
typeId: this.typeId,
553+
values: [...this.values],
554+
internalTypeId: this.internalTypeId,
555+
...(this.alias ? { alias: this.alias } : {}),
556+
};
557+
}
535558
}
536559
export function ENUM8(
537560
values: readonly string[],
@@ -586,6 +609,13 @@ export class DuckDBListType extends BaseDuckDBType<DuckDBTypeId.LIST> {
586609
}
587610
return logicalType;
588611
}
612+
public override toJson(): Json {
613+
return {
614+
typeId: this.typeId,
615+
valueType: this.valueType.toJson(),
616+
...(this.alias ? { alias: this.alias } : {}),
617+
};
618+
}
589619
}
590620
export function LIST(valueType: DuckDBType, alias?: string): DuckDBListType {
591621
return new DuckDBListType(valueType, alias);
@@ -641,6 +671,14 @@ export class DuckDBStructType extends BaseDuckDBType<DuckDBTypeId.STRUCT> {
641671
}
642672
return logicalType;
643673
}
674+
public override toJson(): Json {
675+
return {
676+
typeId: this.typeId,
677+
entryNames: [...this.entryNames],
678+
entryTypes: this.entryTypes.map(t => t.toJson()),
679+
...(this.alias ? { alias: this.alias } : {}),
680+
};
681+
}
644682
}
645683
export function STRUCT(
646684
entries: Record<string, DuckDBType>,
@@ -676,6 +714,14 @@ export class DuckDBMapType extends BaseDuckDBType<DuckDBTypeId.MAP> {
676714
}
677715
return logicalType;
678716
}
717+
public override toJson(): Json {
718+
return {
719+
typeId: this.typeId,
720+
keyType: this.keyType.toJson(),
721+
valueType: this.valueType.toJson(),
722+
...(this.alias ? { alias: this.alias } : {}),
723+
};
724+
}
679725
}
680726
export function MAP(
681727
keyType: DuckDBType,
@@ -706,6 +752,14 @@ export class DuckDBArrayType extends BaseDuckDBType<DuckDBTypeId.ARRAY> {
706752
}
707753
return logicalType;
708754
}
755+
public override toJson(): Json {
756+
return {
757+
typeId: this.typeId,
758+
valueType: this.valueType.toJson(),
759+
length: this.length,
760+
...(this.alias ? { alias: this.alias } : {}),
761+
};
762+
}
709763
}
710764
export function ARRAY(
711765
valueType: DuckDBType,
@@ -782,6 +836,14 @@ export class DuckDBUnionType extends BaseDuckDBType<DuckDBTypeId.UNION> {
782836
}
783837
return logicalType;
784838
}
839+
public override toJson(): Json {
840+
return {
841+
typeId: this.typeId,
842+
memberTags: [...this.memberTags],
843+
memberTypes: this.memberTypes.map(t => t.toJson()),
844+
...(this.alias ? { alias: this.alias } : {}),
845+
};
846+
}
785847
}
786848
export function UNION(
787849
members: Record<string, DuckDBType>,

api/src/DuckDBValueToJsonConverter.ts

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { DuckDBType } from './DuckDBType';
22
import { DuckDBTypeId } from './DuckDBTypeId';
33
import { DuckDBValueConverter } from './DuckDBValueConverter';
4+
import { Json } from './Json';
45
import {
56
DuckDBArrayValue,
67
DuckDBIntervalValue,
@@ -11,14 +12,6 @@ import {
1112
DuckDBValue,
1213
} from './values';
1314

14-
export type Json =
15-
| null
16-
| boolean
17-
| number
18-
| string
19-
| Json[]
20-
| { [key: string]: Json };
21-
2215
export class DuckDBValueToJsonConverter implements DuckDBValueConverter<Json> {
2316
public static readonly default = new DuckDBValueToJsonConverter();
2417

api/src/Json.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
export type Json =
2+
| null
3+
| boolean
4+
| number
5+
| string
6+
| Json[]
7+
| { [key: string]: Json };

api/src/duckdb.ts

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
export {
2-
hugeint_to_double,
32
double_to_hugeint,
4-
uhugeint_to_double,
53
double_to_uhugeint,
4+
hugeint_to_double,
5+
uhugeint_to_double,
66
} from '@duckdb/node-bindings';
7+
export * from './configurationOptionDescriptions';
78
export * from './DuckDBAppender';
89
export * from './DuckDBConnection';
910
export * from './DuckDBDataChunk';
@@ -19,8 +20,8 @@ export * from './DuckDBTypeId';
1920
export * from './DuckDBValueConverter';
2021
export * from './DuckDBValueToJsonConverter';
2122
export * from './DuckDBVector';
22-
export * from './configurationOptionDescriptions';
2323
export * from './enums';
24+
export * from './Json';
2425
export * from './sql';
2526
export * from './values';
2627
export * from './version';

0 commit comments

Comments
 (0)