Skip to content

Commit

Permalink
data type toString
Browse files Browse the repository at this point in the history
  • Loading branch information
jraymakers committed Oct 27, 2024
1 parent d59bc93 commit c908c5d
Show file tree
Hide file tree
Showing 5 changed files with 104 additions and 3 deletions.
6 changes: 6 additions & 0 deletions api/pkgs/@duckdb/node-api/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -191,6 +191,12 @@ function typeToString(dataType) {
}
```

While the example above demonstrates how to access the properties of data type objects, there is a much simpler way to convert them to strings:

```ts
const dataTypeString = dataType.toString();
```

### Inspect Data Values

```ts
Expand Down
35 changes: 35 additions & 0 deletions api/src/DuckDBType.ts
Original file line number Diff line number Diff line change
@@ -1,10 +1,14 @@
import { DuckDBTypeId } from './DuckDBTypeId';
import { quotedIdentifier, quotedString } from './sql';

export abstract class BaseDuckDBType {
public readonly typeId: DuckDBTypeId;
protected constructor(typeId: DuckDBTypeId) {
this.typeId = typeId;
}
public toString(): string {
return DuckDBTypeId[this.typeId];
}
}

export class DuckDBBooleanType extends BaseDuckDBType {
Expand Down Expand Up @@ -150,6 +154,9 @@ export class DuckDBDecimalType extends BaseDuckDBType {
this.width = width;
this.scale = scale;
}
public toString(): string {
return `DECIMAL(${this.width},${this.scale})`;
}
public static readonly default = new DuckDBDecimalType(18, 3);
}

Expand Down Expand Up @@ -182,6 +189,9 @@ export class DuckDBEnumType extends BaseDuckDBType {
this.values = values;
this.internalTypeId = internalTypeId;
}
public toString(): string {
return `ENUM(${this.values.map(quotedString).join(', ')})`;
}
}

export class DuckDBListType extends BaseDuckDBType {
Expand All @@ -190,6 +200,9 @@ export class DuckDBListType extends BaseDuckDBType {
super(DuckDBTypeId.LIST);
this.valueType = valueType;
}
public toString(): string {
return `${this.valueType}[]`;
}
}

export interface DuckDBStructEntryType {
Expand All @@ -203,6 +216,11 @@ export class DuckDBStructType extends BaseDuckDBType {
super(DuckDBTypeId.STRUCT);
this.entries = entries;
}
public toString(): string {
return `STRUCT(${this.entries.map(
entry => `${quotedIdentifier(entry.name)} ${entry.valueType}`
).join(', ')})`;
}
}

export class DuckDBMapType extends BaseDuckDBType {
Expand All @@ -213,6 +231,9 @@ export class DuckDBMapType extends BaseDuckDBType {
this.keyType = keyType;
this.valueType = valueType;
}
public toString(): string {
return `MAP(${this.keyType}, ${this.valueType})`;
}
}

export class DuckDBArrayType extends BaseDuckDBType {
Expand All @@ -223,6 +244,9 @@ export class DuckDBArrayType extends BaseDuckDBType {
this.valueType = valueType;
this.length = length;
}
public toString(): string {
return `${this.valueType}[${this.length}]`;
}
}

export class DuckDBUUIDType extends BaseDuckDBType {
Expand All @@ -243,6 +267,11 @@ export class DuckDBUnionType extends BaseDuckDBType {
super(DuckDBTypeId.UNION);
this.alternatives = alternatives;
}
public toString(): string {
return `UNION(${this.alternatives.map(
entry => `${quotedIdentifier(entry.tag)} ${entry.valueType}`
).join(', ')})`;
}
}

export class DuckDBBitType extends BaseDuckDBType {
Expand All @@ -256,13 +285,19 @@ export class DuckDBTimeTZType extends BaseDuckDBType {
private constructor() {
super(DuckDBTypeId.TIME_TZ);
}
public toString(): string {
return "TIME WITH TIME ZONE";
}
public static readonly instance = new DuckDBTimeTZType();
}

export class DuckDBTimestampTZType extends BaseDuckDBType {
private constructor() {
super(DuckDBTypeId.TIMESTAMP_TZ);
}
public toString(): string {
return "TIMESTAMP WITH TIME ZONE";
}
public static readonly instance = new DuckDBTimestampTZType();
}

Expand Down
1 change: 1 addition & 0 deletions api/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,4 +13,5 @@ export * from './DuckDBTypeId';
export * from './DuckDBValue';
export * from './DuckDBVector';
export * from './enums';
export * from './sql';
export * from './version';
7 changes: 7 additions & 0 deletions api/src/sql.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
export function quotedString(input: string): string {
return `'${input.replace(`'`, `''`)}'`;
}

export function quotedIdentifier(input: string): string {
return `"${input.replace(`"`, `""`)}"`;
}
58 changes: 55 additions & 3 deletions api/test/api.test.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { assert, describe, test } from 'vitest';
import {
DuckDBAnyType,
DuckDBArrayType,
DuckDBArrayVector,
DuckDBBigIntType,
Expand Down Expand Up @@ -44,6 +45,7 @@ import {
DuckDBMapVector,
DuckDBPendingResultState,
DuckDBResult,
DuckDBSQLNullType,
DuckDBSmallDecimal,
DuckDBSmallIntType,
DuckDBSmallIntVector,
Expand Down Expand Up @@ -283,6 +285,10 @@ describe('api', () => {
const ver = version();
assert.ok(ver.startsWith('v'), `version starts with 'v'`);
});
test('should expose configuration option descriptions', () => {
const descriptions = configurationOptionDescriptions();
assert.ok(descriptions['memory_limit'], `descriptions has 'memory_limit'`);
});
test('ReturnResultType enum', () => {
assert.equal(ResultReturnType.INVALID, 0);
assert.equal(ResultReturnType.CHANGED_ROWS, 1);
Expand Down Expand Up @@ -353,9 +359,55 @@ describe('api', () => {
assert.equal(StatementType[StatementType.DETACH], 'DETACH');
assert.equal(StatementType[StatementType.MULTI], 'MULTI');
});
test('should expose configuration option descriptions', () => {
const descriptions = configurationOptionDescriptions();
assert.ok(descriptions['memory_limit'], `descriptions has 'memory_limit'`);
test('DuckDBType toString', () => {
assert.equal(DuckDBBooleanType.instance.toString(), 'BOOLEAN');
assert.equal(DuckDBTinyIntType.instance.toString(), 'TINYINT');
assert.equal(DuckDBSmallIntType.instance.toString(), 'SMALLINT');
assert.equal(DuckDBIntegerType.instance.toString(), 'INTEGER');
assert.equal(DuckDBBigIntType.instance.toString(), 'BIGINT');
assert.equal(DuckDBUTinyIntType.instance.toString(), 'UTINYINT');
assert.equal(DuckDBUSmallIntType.instance.toString(), 'USMALLINT');
assert.equal(DuckDBUIntegerType.instance.toString(), 'UINTEGER');
assert.equal(DuckDBUBigIntType.instance.toString(), 'UBIGINT');
assert.equal(DuckDBFloatType.instance.toString(), 'FLOAT');
assert.equal(DuckDBDoubleType.instance.toString(), 'DOUBLE');
assert.equal(DuckDBTimestampType.instance.toString(), 'TIMESTAMP');
assert.equal(DuckDBDateType.instance.toString(), 'DATE');
assert.equal(DuckDBTimeType.instance.toString(), 'TIME');
assert.equal(DuckDBIntervalType.instance.toString(), 'INTERVAL');
assert.equal(DuckDBHugeIntType.instance.toString(), 'HUGEINT');
assert.equal(DuckDBUHugeIntType.instance.toString(), 'UHUGEINT');
assert.equal(DuckDBVarCharType.instance.toString(), 'VARCHAR');
assert.equal(DuckDBBlobType.instance.toString(), 'BLOB');
assert.equal((new DuckDBDecimalType(17, 5)).toString(), 'DECIMAL(17,5)');
assert.equal(DuckDBTimestampSecondsType.instance.toString(), 'TIMESTAMP_S');
assert.equal(DuckDBTimestampMillisecondsType.instance.toString(), 'TIMESTAMP_MS');
assert.equal(DuckDBTimestampNanosecondsType.instance.toString(), 'TIMESTAMP_NS');
assert.equal(
(new DuckDBEnumType(['fly', 'swim', 'walk'], DuckDBTypeId.UTINYINT)).toString(),
`ENUM('fly', 'swim', 'walk')`
);
assert.equal((new DuckDBListType(DuckDBIntegerType.instance)).toString(), 'INTEGER[]');
assert.equal((new DuckDBStructType([
{ name: 'id', valueType: DuckDBVarCharType.instance },
{ name: 'ts', valueType: DuckDBTimestampType.instance },
])).toString(), 'STRUCT("id" VARCHAR, "ts" TIMESTAMP)');
assert.equal(
(new DuckDBMapType(DuckDBIntegerType.instance, DuckDBVarCharType.instance)).toString(),
'MAP(INTEGER, VARCHAR)'
);
assert.equal((new DuckDBArrayType(DuckDBIntegerType.instance, 3)).toString(), 'INTEGER[3]');
assert.equal(DuckDBUUIDType.instance.toString(), 'UUID');
assert.equal((new DuckDBUnionType([
{ tag: 'str', valueType: DuckDBVarCharType.instance },
{ tag: 'num', valueType: DuckDBIntegerType.instance },
])).toString(), 'UNION("str" VARCHAR, "num" INTEGER)');
assert.equal(DuckDBBitType.instance.toString(), 'BIT');
assert.equal(DuckDBTimeTZType.instance.toString(), 'TIME WITH TIME ZONE');
assert.equal(DuckDBTimestampTZType.instance.toString(), 'TIMESTAMP WITH TIME ZONE');
assert.equal(DuckDBAnyType.instance.toString(), 'ANY');
assert.equal(DuckDBVarIntType.instance.toString(), 'VARINT');
assert.equal(DuckDBSQLNullType.instance.toString(), 'SQLNULL');
});
test('should support creating, connecting, running a basic query, and reading results', async () => {
const instance = await DuckDBInstance.create();
Expand Down

0 comments on commit c908c5d

Please sign in to comment.