add duckdb-ui-client & other ts pkgs (#10)
* add duckdb-ui-client & other ts pkgs * workflow fixes * fix working dir * no sparse checkout; specify package.json path * path to pnpm-lock.yaml * add check & build test * workflow step descriptions * use comments & names * one more naming tweak
This commit is contained in:
37
ts/pkgs/duckdb-data-types/package.json
Normal file
37
ts/pkgs/duckdb-data-types/package.json
Normal file
@@ -0,0 +1,37 @@
|
||||
{
|
||||
"name": "@duckdb/data-types",
|
||||
"version": "0.0.1",
|
||||
"description": "Utilities for representing DuckDB types",
|
||||
"type": "module",
|
||||
"main": "./out/index.js",
|
||||
"module": "./out/index.js",
|
||||
"types": "./out/index.d.ts",
|
||||
"scripts": {
|
||||
"preinstall": "pnpm build:src",
|
||||
"build": "tsc -b src test",
|
||||
"build:src": "tsc -b src",
|
||||
"build:test": "tsc -b test",
|
||||
"build:watch": "tsc -b src test --watch",
|
||||
"check": "pnpm format:check && pnpm lint",
|
||||
"clean": "rimraf out",
|
||||
"format:check": "prettier . --ignore-path $(find-up .prettierignore) --check",
|
||||
"format:write": "prettier . --ignore-path $(find-up .prettierignore) --write",
|
||||
"lint": "pnpm eslint src test",
|
||||
"test": "vitest run",
|
||||
"test:watch": "vitest"
|
||||
},
|
||||
"dependencies": {
|
||||
"@duckdb/data-values": "workspace:*"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@eslint/js": "^9.24.0",
|
||||
"eslint": "^9.24.0",
|
||||
"find-up-cli": "^6.0.0",
|
||||
"prettier": "^3.5.3",
|
||||
"rimraf": "^6.0.1",
|
||||
"typescript": "^5.8.3",
|
||||
"typescript-eslint": "^8.30.1",
|
||||
"vite": "^6.2.6",
|
||||
"vitest": "^3.1.1"
|
||||
}
|
||||
}
|
||||
989
ts/pkgs/duckdb-data-types/src/DuckDBType.ts
Normal file
989
ts/pkgs/duckdb-data-types/src/DuckDBType.ts
Normal file
@@ -0,0 +1,989 @@
|
||||
import { Json } from '@duckdb/data-values';
|
||||
import { DuckDBTypeId } from './DuckDBTypeId.js';
|
||||
import { quotedIdentifier, quotedString } from './sql.js';
|
||||
|
||||
export interface DuckDBTypeToStringOptions {
|
||||
short?: boolean;
|
||||
}
|
||||
export abstract class BaseDuckDBType<T extends DuckDBTypeId> {
|
||||
public readonly typeId: T;
|
||||
public readonly alias?: string;
|
||||
protected constructor(typeId: T, alias?: string) {
|
||||
this.typeId = typeId;
|
||||
this.alias = alias;
|
||||
}
|
||||
public toString(_options?: DuckDBTypeToStringOptions): string {
|
||||
return this.alias ?? DuckDBTypeId[this.typeId];
|
||||
}
|
||||
public toJson(): Json {
|
||||
return {
|
||||
typeId: this.typeId,
|
||||
...(this.alias ? { alias: this.alias } : {}),
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export class DuckDBBooleanType extends BaseDuckDBType<DuckDBTypeId.BOOLEAN> {
|
||||
public constructor(alias?: string) {
|
||||
super(DuckDBTypeId.BOOLEAN, alias);
|
||||
}
|
||||
public static readonly instance = new DuckDBBooleanType();
|
||||
public static create(alias?: string): DuckDBBooleanType {
|
||||
return alias ? new DuckDBBooleanType(alias) : DuckDBBooleanType.instance;
|
||||
}
|
||||
}
|
||||
export const BOOLEAN = DuckDBBooleanType.instance;
|
||||
|
||||
export class DuckDBTinyIntType extends BaseDuckDBType<DuckDBTypeId.TINYINT> {
|
||||
public constructor(alias?: string) {
|
||||
super(DuckDBTypeId.TINYINT, alias);
|
||||
}
|
||||
public static readonly instance = new DuckDBTinyIntType();
|
||||
public static create(alias?: string): DuckDBTinyIntType {
|
||||
return alias ? new DuckDBTinyIntType(alias) : DuckDBTinyIntType.instance;
|
||||
}
|
||||
public static readonly Max = 2 ** 7 - 1;
|
||||
public static readonly Min = -(2 ** 7);
|
||||
public get max() {
|
||||
return DuckDBTinyIntType.Max;
|
||||
}
|
||||
public get min() {
|
||||
return DuckDBTinyIntType.Min;
|
||||
}
|
||||
}
|
||||
export const TINYINT = DuckDBTinyIntType.instance;
|
||||
|
||||
export class DuckDBSmallIntType extends BaseDuckDBType<DuckDBTypeId.SMALLINT> {
|
||||
public constructor(alias?: string) {
|
||||
super(DuckDBTypeId.SMALLINT, alias);
|
||||
}
|
||||
public static readonly instance = new DuckDBSmallIntType();
|
||||
public static create(alias?: string): DuckDBSmallIntType {
|
||||
return alias ? new DuckDBSmallIntType(alias) : DuckDBSmallIntType.instance;
|
||||
}
|
||||
public static readonly Max = 2 ** 15 - 1;
|
||||
public static readonly Min = -(2 ** 15);
|
||||
public get max() {
|
||||
return DuckDBSmallIntType.Max;
|
||||
}
|
||||
public get min() {
|
||||
return DuckDBSmallIntType.Min;
|
||||
}
|
||||
}
|
||||
export const SMALLINT = DuckDBSmallIntType.instance;
|
||||
|
||||
export class DuckDBIntegerType extends BaseDuckDBType<DuckDBTypeId.INTEGER> {
|
||||
public constructor(alias?: string) {
|
||||
super(DuckDBTypeId.INTEGER, alias);
|
||||
}
|
||||
public static readonly instance = new DuckDBIntegerType();
|
||||
public static create(alias?: string): DuckDBIntegerType {
|
||||
return alias ? new DuckDBIntegerType(alias) : DuckDBIntegerType.instance;
|
||||
}
|
||||
public static readonly Max = 2 ** 31 - 1;
|
||||
public static readonly Min = -(2 ** 31);
|
||||
public get max() {
|
||||
return DuckDBIntegerType.Max;
|
||||
}
|
||||
public get min() {
|
||||
return DuckDBIntegerType.Min;
|
||||
}
|
||||
}
|
||||
export const INTEGER = DuckDBIntegerType.instance;
|
||||
|
||||
export class DuckDBBigIntType extends BaseDuckDBType<DuckDBTypeId.BIGINT> {
|
||||
public constructor(alias?: string) {
|
||||
super(DuckDBTypeId.BIGINT, alias);
|
||||
}
|
||||
public static readonly instance = new DuckDBBigIntType();
|
||||
public static create(alias?: string): DuckDBBigIntType {
|
||||
return alias ? new DuckDBBigIntType(alias) : DuckDBBigIntType.instance;
|
||||
}
|
||||
public static readonly Max: bigint = 2n ** 63n - 1n;
|
||||
public static readonly Min: bigint = -(2n ** 63n);
|
||||
public get max() {
|
||||
return DuckDBBigIntType.Max;
|
||||
}
|
||||
public get min() {
|
||||
return DuckDBBigIntType.Min;
|
||||
}
|
||||
}
|
||||
export const BIGINT = DuckDBBigIntType.instance;
|
||||
|
||||
export class DuckDBUTinyIntType extends BaseDuckDBType<DuckDBTypeId.UTINYINT> {
|
||||
public constructor(alias?: string) {
|
||||
super(DuckDBTypeId.UTINYINT, alias);
|
||||
}
|
||||
public static readonly instance = new DuckDBUTinyIntType();
|
||||
public static create(alias?: string): DuckDBUTinyIntType {
|
||||
return alias ? new DuckDBUTinyIntType(alias) : DuckDBUTinyIntType.instance;
|
||||
}
|
||||
public static readonly Max = 2 ** 8 - 1;
|
||||
public static readonly Min = 0;
|
||||
public get max() {
|
||||
return DuckDBUTinyIntType.Max;
|
||||
}
|
||||
public get min() {
|
||||
return DuckDBUTinyIntType.Min;
|
||||
}
|
||||
}
|
||||
export const UTINYINT = DuckDBUTinyIntType.instance;
|
||||
|
||||
export class DuckDBUSmallIntType extends BaseDuckDBType<DuckDBTypeId.USMALLINT> {
|
||||
public constructor(alias?: string) {
|
||||
super(DuckDBTypeId.USMALLINT, alias);
|
||||
}
|
||||
public static readonly instance = new DuckDBUSmallIntType();
|
||||
public static create(alias?: string): DuckDBUSmallIntType {
|
||||
return alias
|
||||
? new DuckDBUSmallIntType(alias)
|
||||
: DuckDBUSmallIntType.instance;
|
||||
}
|
||||
public static readonly Max = 2 ** 16 - 1;
|
||||
public static readonly Min = 0;
|
||||
public get max() {
|
||||
return DuckDBUSmallIntType.Max;
|
||||
}
|
||||
public get min() {
|
||||
return DuckDBUSmallIntType.Min;
|
||||
}
|
||||
}
|
||||
export const USMALLINT = DuckDBUSmallIntType.instance;
|
||||
|
||||
export class DuckDBUIntegerType extends BaseDuckDBType<DuckDBTypeId.UINTEGER> {
|
||||
public constructor(alias?: string) {
|
||||
super(DuckDBTypeId.UINTEGER, alias);
|
||||
}
|
||||
public static readonly instance = new DuckDBUIntegerType();
|
||||
public static create(alias?: string): DuckDBUIntegerType {
|
||||
return alias ? new DuckDBUIntegerType(alias) : DuckDBUIntegerType.instance;
|
||||
}
|
||||
public static readonly Max = 2 ** 32 - 1;
|
||||
public static readonly Min = 0;
|
||||
public get max() {
|
||||
return DuckDBUIntegerType.Max;
|
||||
}
|
||||
public get min() {
|
||||
return DuckDBUIntegerType.Min;
|
||||
}
|
||||
}
|
||||
export const UINTEGER = DuckDBUIntegerType.instance;
|
||||
|
||||
export class DuckDBUBigIntType extends BaseDuckDBType<DuckDBTypeId.UBIGINT> {
|
||||
public constructor(alias?: string) {
|
||||
super(DuckDBTypeId.UBIGINT, alias);
|
||||
}
|
||||
public static readonly instance = new DuckDBUBigIntType();
|
||||
public static create(alias?: string): DuckDBUBigIntType {
|
||||
return alias ? new DuckDBUBigIntType(alias) : DuckDBUBigIntType.instance;
|
||||
}
|
||||
public static readonly Max: bigint = 2n ** 64n - 1n;
|
||||
public static readonly Min: bigint = 0n;
|
||||
public get max() {
|
||||
return DuckDBUBigIntType.Max;
|
||||
}
|
||||
public get min() {
|
||||
return DuckDBUBigIntType.Min;
|
||||
}
|
||||
}
|
||||
export const UBIGINT = DuckDBUBigIntType.instance;
|
||||
|
||||
export class DuckDBFloatType extends BaseDuckDBType<DuckDBTypeId.FLOAT> {
|
||||
public constructor(alias?: string) {
|
||||
super(DuckDBTypeId.FLOAT, alias);
|
||||
}
|
||||
public static readonly instance = new DuckDBFloatType();
|
||||
public static create(alias?: string): DuckDBFloatType {
|
||||
return alias ? new DuckDBFloatType(alias) : DuckDBFloatType.instance;
|
||||
}
|
||||
public static readonly Max = Math.fround(3.4028235e38);
|
||||
public static readonly Min = Math.fround(-3.4028235e38);
|
||||
public get max() {
|
||||
return DuckDBFloatType.Max;
|
||||
}
|
||||
public get min() {
|
||||
return DuckDBFloatType.Min;
|
||||
}
|
||||
}
|
||||
export const FLOAT = DuckDBFloatType.instance;
|
||||
|
||||
export class DuckDBDoubleType extends BaseDuckDBType<DuckDBTypeId.DOUBLE> {
|
||||
public constructor(alias?: string) {
|
||||
super(DuckDBTypeId.DOUBLE, alias);
|
||||
}
|
||||
public static readonly instance = new DuckDBDoubleType();
|
||||
public static create(alias?: string): DuckDBDoubleType {
|
||||
return alias ? new DuckDBDoubleType(alias) : DuckDBDoubleType.instance;
|
||||
}
|
||||
public static readonly Max = Number.MAX_VALUE;
|
||||
public static readonly Min = -Number.MAX_VALUE;
|
||||
public get max() {
|
||||
return DuckDBDoubleType.Max;
|
||||
}
|
||||
public get min() {
|
||||
return DuckDBDoubleType.Min;
|
||||
}
|
||||
}
|
||||
export const DOUBLE = DuckDBDoubleType.instance;
|
||||
|
||||
export class DuckDBTimestampType extends BaseDuckDBType<DuckDBTypeId.TIMESTAMP> {
|
||||
public constructor(alias?: string) {
|
||||
super(DuckDBTypeId.TIMESTAMP, alias);
|
||||
}
|
||||
public static readonly instance = new DuckDBTimestampType();
|
||||
public static create(alias?: string): DuckDBTimestampType {
|
||||
return alias
|
||||
? new DuckDBTimestampType(alias)
|
||||
: DuckDBTimestampType.instance;
|
||||
}
|
||||
// TODO: common DuckDBValues on type objects
|
||||
// public get epoch() {
|
||||
// return DuckDBTimestampValue.Epoch;
|
||||
// }
|
||||
// public get max() {
|
||||
// return DuckDBTimestampValue.Max;
|
||||
// }
|
||||
// public get min() {
|
||||
// return DuckDBTimestampValue.Min;
|
||||
// }
|
||||
// public get posInf() {
|
||||
// return DuckDBTimestampValue.PosInf;
|
||||
// }
|
||||
// public get negInf() {
|
||||
// return DuckDBTimestampValue.NegInf;
|
||||
// }
|
||||
}
|
||||
export const TIMESTAMP = DuckDBTimestampType.instance;
|
||||
|
||||
export type DuckDBTimestampMicrosecondsType = DuckDBTimestampType;
|
||||
export const DuckDBTimestampMicrosecondsType = DuckDBTimestampType;
|
||||
|
||||
export class DuckDBDateType extends BaseDuckDBType<DuckDBTypeId.DATE> {
|
||||
public constructor(alias?: string) {
|
||||
super(DuckDBTypeId.DATE, alias);
|
||||
}
|
||||
public static readonly instance = new DuckDBDateType();
|
||||
public static create(alias?: string): DuckDBDateType {
|
||||
return alias ? new DuckDBDateType(alias) : DuckDBDateType.instance;
|
||||
}
|
||||
// TODO: common DuckDBValues on type objects
|
||||
// public get epoch() {
|
||||
// return DuckDBDateValue.Epoch;
|
||||
// }
|
||||
// public get max() {
|
||||
// return DuckDBDateValue.Max;
|
||||
// }
|
||||
// public get min() {
|
||||
// return DuckDBDateValue.Min;
|
||||
// }
|
||||
// public get posInf() {
|
||||
// return DuckDBDateValue.PosInf;
|
||||
// }
|
||||
// public get negInf() {
|
||||
// return DuckDBDateValue.NegInf;
|
||||
// }
|
||||
}
|
||||
export const DATE = DuckDBDateType.instance;
|
||||
|
||||
export class DuckDBTimeType extends BaseDuckDBType<DuckDBTypeId.TIME> {
|
||||
public constructor(alias?: string) {
|
||||
super(DuckDBTypeId.TIME, alias);
|
||||
}
|
||||
public static readonly instance = new DuckDBTimeType();
|
||||
public static create(alias?: string): DuckDBTimeType {
|
||||
return alias ? new DuckDBTimeType(alias) : DuckDBTimeType.instance;
|
||||
}
|
||||
// TODO: common DuckDBValues on type objects
|
||||
// public get max() {
|
||||
// return DuckDBTimeValue.Max;
|
||||
// }
|
||||
// public get min() {
|
||||
// return DuckDBTimeValue.Min;
|
||||
// }
|
||||
}
|
||||
export const TIME = DuckDBTimeType.instance;
|
||||
|
||||
export class DuckDBIntervalType extends BaseDuckDBType<DuckDBTypeId.INTERVAL> {
|
||||
public constructor(alias?: string) {
|
||||
super(DuckDBTypeId.INTERVAL, alias);
|
||||
}
|
||||
public static readonly instance = new DuckDBIntervalType();
|
||||
public static create(alias?: string): DuckDBIntervalType {
|
||||
return alias ? new DuckDBIntervalType(alias) : DuckDBIntervalType.instance;
|
||||
}
|
||||
}
|
||||
export const INTERVAL = DuckDBIntervalType.instance;
|
||||
|
||||
export class DuckDBHugeIntType extends BaseDuckDBType<DuckDBTypeId.HUGEINT> {
|
||||
public constructor(alias?: string) {
|
||||
super(DuckDBTypeId.HUGEINT, alias);
|
||||
}
|
||||
public static readonly instance = new DuckDBHugeIntType();
|
||||
public static create(alias?: string): DuckDBHugeIntType {
|
||||
return alias ? new DuckDBHugeIntType(alias) : DuckDBHugeIntType.instance;
|
||||
}
|
||||
public static readonly Max: bigint = 2n ** 127n - 1n;
|
||||
public static readonly Min: bigint = -(2n ** 127n);
|
||||
public get max() {
|
||||
return DuckDBHugeIntType.Max;
|
||||
}
|
||||
public get min() {
|
||||
return DuckDBHugeIntType.Min;
|
||||
}
|
||||
}
|
||||
export const HUGEINT = DuckDBHugeIntType.instance;
|
||||
|
||||
export class DuckDBUHugeIntType extends BaseDuckDBType<DuckDBTypeId.UHUGEINT> {
|
||||
public constructor(alias?: string) {
|
||||
super(DuckDBTypeId.UHUGEINT, alias);
|
||||
}
|
||||
public static readonly instance = new DuckDBUHugeIntType();
|
||||
public static create(alias?: string): DuckDBUHugeIntType {
|
||||
return alias ? new DuckDBUHugeIntType(alias) : DuckDBUHugeIntType.instance;
|
||||
}
|
||||
public static readonly Max: bigint = 2n ** 128n - 1n;
|
||||
public static readonly Min: bigint = 0n;
|
||||
public get max() {
|
||||
return DuckDBUHugeIntType.Max;
|
||||
}
|
||||
public get min() {
|
||||
return DuckDBUHugeIntType.Min;
|
||||
}
|
||||
}
|
||||
export const UHUGEINT = DuckDBUHugeIntType.instance;
|
||||
|
||||
export class DuckDBVarCharType extends BaseDuckDBType<DuckDBTypeId.VARCHAR> {
|
||||
public constructor(alias?: string) {
|
||||
super(DuckDBTypeId.VARCHAR, alias);
|
||||
}
|
||||
public static readonly instance = new DuckDBVarCharType();
|
||||
public static create(alias?: string): DuckDBVarCharType {
|
||||
return alias ? new DuckDBVarCharType(alias) : DuckDBVarCharType.instance;
|
||||
}
|
||||
}
|
||||
export const VARCHAR = DuckDBVarCharType.instance;
|
||||
|
||||
export class DuckDBBlobType extends BaseDuckDBType<DuckDBTypeId.BLOB> {
|
||||
public constructor(alias?: string) {
|
||||
super(DuckDBTypeId.BLOB, alias);
|
||||
}
|
||||
public static readonly instance = new DuckDBBlobType();
|
||||
public static create(alias?: string): DuckDBBlobType {
|
||||
return alias ? new DuckDBBlobType(alias) : DuckDBBlobType.instance;
|
||||
}
|
||||
}
|
||||
export const BLOB = DuckDBBlobType.instance;
|
||||
|
||||
export class DuckDBDecimalType extends BaseDuckDBType<DuckDBTypeId.DECIMAL> {
|
||||
public readonly width: number;
|
||||
public readonly scale: number;
|
||||
public constructor(width: number, scale: number, alias?: string) {
|
||||
super(DuckDBTypeId.DECIMAL, alias);
|
||||
this.width = width;
|
||||
this.scale = scale;
|
||||
}
|
||||
public toString(_options?: DuckDBTypeToStringOptions): string {
|
||||
return this.alias ?? `DECIMAL(${this.width},${this.scale})`;
|
||||
}
|
||||
public override toJson(): Json {
|
||||
return {
|
||||
typeId: this.typeId,
|
||||
width: this.width,
|
||||
scale: this.scale,
|
||||
...(this.alias ? { alias: this.alias } : {}),
|
||||
};
|
||||
}
|
||||
public static readonly default = new DuckDBDecimalType(18, 3);
|
||||
}
|
||||
export function DECIMAL(
|
||||
width?: number,
|
||||
scale?: number,
|
||||
alias?: string,
|
||||
): DuckDBDecimalType {
|
||||
if (width === undefined) {
|
||||
return DuckDBDecimalType.default;
|
||||
}
|
||||
if (scale === undefined) {
|
||||
return new DuckDBDecimalType(width, 0);
|
||||
}
|
||||
return new DuckDBDecimalType(width, scale, alias);
|
||||
}
|
||||
|
||||
export class DuckDBTimestampSecondsType extends BaseDuckDBType<DuckDBTypeId.TIMESTAMP_S> {
|
||||
public constructor(alias?: string) {
|
||||
super(DuckDBTypeId.TIMESTAMP_S, alias);
|
||||
}
|
||||
public static readonly instance = new DuckDBTimestampSecondsType();
|
||||
public static create(alias?: string): DuckDBTimestampSecondsType {
|
||||
return alias
|
||||
? new DuckDBTimestampSecondsType(alias)
|
||||
: DuckDBTimestampSecondsType.instance;
|
||||
}
|
||||
// TODO: common DuckDBValues on type objects
|
||||
// public get epoch() {
|
||||
// return DuckDBTimestampSecondsValue.Epoch;
|
||||
// }
|
||||
// public get max() {
|
||||
// return DuckDBTimestampSecondsValue.Max;
|
||||
// }
|
||||
// public get min() {
|
||||
// return DuckDBTimestampSecondsValue.Min;
|
||||
// }
|
||||
// public get posInf() {
|
||||
// return DuckDBTimestampSecondsValue.PosInf;
|
||||
// }
|
||||
// public get negInf() {
|
||||
// return DuckDBTimestampSecondsValue.NegInf;
|
||||
// }
|
||||
}
|
||||
export const TIMESTAMP_S = DuckDBTimestampSecondsType.instance;
|
||||
|
||||
export class DuckDBTimestampMillisecondsType extends BaseDuckDBType<DuckDBTypeId.TIMESTAMP_MS> {
|
||||
public constructor(alias?: string) {
|
||||
super(DuckDBTypeId.TIMESTAMP_MS, alias);
|
||||
}
|
||||
public static readonly instance = new DuckDBTimestampMillisecondsType();
|
||||
public static create(alias?: string): DuckDBTimestampMillisecondsType {
|
||||
return alias
|
||||
? new DuckDBTimestampMillisecondsType(alias)
|
||||
: DuckDBTimestampMillisecondsType.instance;
|
||||
}
|
||||
// TODO: common DuckDBValues on type objects
|
||||
// public get epoch() {
|
||||
// return DuckDBTimestampMillisecondsValue.Epoch;
|
||||
// }
|
||||
// public get max() {
|
||||
// return DuckDBTimestampMillisecondsValue.Max;
|
||||
// }
|
||||
// public get min() {
|
||||
// return DuckDBTimestampMillisecondsValue.Min;
|
||||
// }
|
||||
// public get posInf() {
|
||||
// return DuckDBTimestampMillisecondsValue.PosInf;
|
||||
// }
|
||||
// public get negInf() {
|
||||
// return DuckDBTimestampMillisecondsValue.NegInf;
|
||||
// }
|
||||
}
|
||||
export const TIMESTAMP_MS = DuckDBTimestampMillisecondsType.instance;
|
||||
|
||||
export class DuckDBTimestampNanosecondsType extends BaseDuckDBType<DuckDBTypeId.TIMESTAMP_NS> {
|
||||
public constructor(alias?: string) {
|
||||
super(DuckDBTypeId.TIMESTAMP_NS, alias);
|
||||
}
|
||||
public static readonly instance = new DuckDBTimestampNanosecondsType();
|
||||
public static create(alias?: string): DuckDBTimestampNanosecondsType {
|
||||
return alias
|
||||
? new DuckDBTimestampNanosecondsType(alias)
|
||||
: DuckDBTimestampNanosecondsType.instance;
|
||||
}
|
||||
// TODO: common DuckDBValues on type objects
|
||||
// public get epoch() {
|
||||
// return DuckDBTimestampNanosecondsValue.Epoch;
|
||||
// }
|
||||
// public get max() {
|
||||
// return DuckDBTimestampNanosecondsValue.Max;
|
||||
// }
|
||||
// public get min() {
|
||||
// return DuckDBTimestampNanosecondsValue.Min;
|
||||
// }
|
||||
// public get posInf() {
|
||||
// return DuckDBTimestampNanosecondsValue.PosInf;
|
||||
// }
|
||||
// public get negInf() {
|
||||
// return DuckDBTimestampNanosecondsValue.NegInf;
|
||||
// }
|
||||
}
|
||||
export const TIMESTAMP_NS = DuckDBTimestampNanosecondsType.instance;
|
||||
|
||||
export class DuckDBEnumType extends BaseDuckDBType<DuckDBTypeId.ENUM> {
|
||||
public readonly values: readonly string[];
|
||||
public readonly valueIndexes: Readonly<Record<string, number>>;
|
||||
public readonly internalTypeId: DuckDBTypeId;
|
||||
public constructor(
|
||||
values: readonly string[],
|
||||
internalTypeId: DuckDBTypeId,
|
||||
alias?: string,
|
||||
) {
|
||||
super(DuckDBTypeId.ENUM, alias);
|
||||
this.values = values;
|
||||
const valueIndexes: Record<string, number> = {};
|
||||
for (let i = 0; i < values.length; i++) {
|
||||
valueIndexes[values[i]] = i;
|
||||
}
|
||||
this.valueIndexes = valueIndexes;
|
||||
this.internalTypeId = internalTypeId;
|
||||
}
|
||||
public indexForValue(value: string): number {
|
||||
return this.valueIndexes[value];
|
||||
}
|
||||
public toString(options?: DuckDBTypeToStringOptions): string {
|
||||
if (this.alias) {
|
||||
return this.alias;
|
||||
}
|
||||
if (options?.short) {
|
||||
return `ENUM(…)`;
|
||||
}
|
||||
return `ENUM(${this.values.map(quotedString).join(', ')})`;
|
||||
}
|
||||
public override toJson(): Json {
|
||||
return {
|
||||
typeId: this.typeId,
|
||||
values: [...this.values],
|
||||
internalTypeId: this.internalTypeId,
|
||||
...(this.alias ? { alias: this.alias } : {}),
|
||||
};
|
||||
}
|
||||
}
|
||||
export function ENUM8(
|
||||
values: readonly string[],
|
||||
alias?: string,
|
||||
): DuckDBEnumType {
|
||||
return new DuckDBEnumType(values, DuckDBTypeId.UTINYINT, alias);
|
||||
}
|
||||
export function ENUM16(
|
||||
values: readonly string[],
|
||||
alias?: string,
|
||||
): DuckDBEnumType {
|
||||
return new DuckDBEnumType(values, DuckDBTypeId.USMALLINT, alias);
|
||||
}
|
||||
export function ENUM32(
|
||||
values: readonly string[],
|
||||
alias?: string,
|
||||
): DuckDBEnumType {
|
||||
return new DuckDBEnumType(values, DuckDBTypeId.UINTEGER, alias);
|
||||
}
|
||||
export function ENUM(
|
||||
values: readonly string[],
|
||||
alias?: string,
|
||||
): DuckDBEnumType {
|
||||
if (values.length < 256) {
|
||||
return ENUM8(values, alias);
|
||||
} else if (values.length < 65536) {
|
||||
return ENUM16(values, alias);
|
||||
} else if (values.length < 4294967296) {
|
||||
return ENUM32(values, alias);
|
||||
} else {
|
||||
throw new Error(
|
||||
`ENUM types cannot have more than 4294967295 values; received ${values.length}`,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export class DuckDBListType extends BaseDuckDBType<DuckDBTypeId.LIST> {
|
||||
public readonly valueType: DuckDBType;
|
||||
public constructor(valueType: DuckDBType, alias?: string) {
|
||||
super(DuckDBTypeId.LIST, alias);
|
||||
this.valueType = valueType;
|
||||
}
|
||||
public toString(options?: DuckDBTypeToStringOptions): string {
|
||||
return this.alias ?? `${this.valueType.toString(options)}[]`;
|
||||
}
|
||||
public override toJson(): Json {
|
||||
return {
|
||||
typeId: this.typeId,
|
||||
valueType: this.valueType.toJson(),
|
||||
...(this.alias ? { alias: this.alias } : {}),
|
||||
};
|
||||
}
|
||||
}
|
||||
export function LIST(valueType: DuckDBType, alias?: string): DuckDBListType {
|
||||
return new DuckDBListType(valueType, alias);
|
||||
}
|
||||
|
||||
export class DuckDBStructType extends BaseDuckDBType<DuckDBTypeId.STRUCT> {
|
||||
public readonly entryNames: readonly string[];
|
||||
public readonly entryTypes: readonly DuckDBType[];
|
||||
public readonly entryIndexes: Readonly<Record<string, number>>;
|
||||
public constructor(
|
||||
entryNames: readonly string[],
|
||||
entryTypes: readonly DuckDBType[],
|
||||
alias?: string,
|
||||
) {
|
||||
super(DuckDBTypeId.STRUCT, alias);
|
||||
if (entryNames.length !== entryTypes.length) {
|
||||
throw new Error(`Could not create DuckDBStructType: \
|
||||
entryNames length (${entryNames.length}) does not match entryTypes length (${entryTypes.length})`);
|
||||
}
|
||||
this.entryNames = entryNames;
|
||||
this.entryTypes = entryTypes;
|
||||
const entryIndexes: Record<string, number> = {};
|
||||
for (let i = 0; i < entryNames.length; i++) {
|
||||
entryIndexes[entryNames[i]] = i;
|
||||
}
|
||||
this.entryIndexes = entryIndexes;
|
||||
}
|
||||
public get entryCount() {
|
||||
return this.entryNames.length;
|
||||
}
|
||||
public indexForEntry(entryName: string): number {
|
||||
return this.entryIndexes[entryName];
|
||||
}
|
||||
public typeForEntry(entryName: string): DuckDBType {
|
||||
return this.entryTypes[this.entryIndexes[entryName]];
|
||||
}
|
||||
public toString(options?: DuckDBTypeToStringOptions): string {
|
||||
if (this.alias) {
|
||||
return this.alias;
|
||||
}
|
||||
if (options?.short) {
|
||||
return `STRUCT(…)`;
|
||||
}
|
||||
const parts: string[] = [];
|
||||
for (let i = 0; i < this.entryNames.length; i++) {
|
||||
parts.push(
|
||||
`${quotedIdentifier(this.entryNames[i])} ${this.entryTypes[i]}`,
|
||||
);
|
||||
}
|
||||
return `STRUCT(${parts.join(', ')})`;
|
||||
}
|
||||
public override toJson(): Json {
|
||||
return {
|
||||
typeId: this.typeId,
|
||||
entryNames: [...this.entryNames],
|
||||
entryTypes: this.entryTypes.map((t) => t.toJson()),
|
||||
...(this.alias ? { alias: this.alias } : {}),
|
||||
};
|
||||
}
|
||||
}
|
||||
export function STRUCT(
|
||||
entries: Record<string, DuckDBType>,
|
||||
alias?: string,
|
||||
): DuckDBStructType {
|
||||
const entryNames = Object.keys(entries);
|
||||
const entryTypes = Object.values(entries);
|
||||
return new DuckDBStructType(entryNames, entryTypes, alias);
|
||||
}
|
||||
|
||||
export class DuckDBMapType extends BaseDuckDBType<DuckDBTypeId.MAP> {
|
||||
public readonly keyType: DuckDBType;
|
||||
public readonly valueType: DuckDBType;
|
||||
public constructor(
|
||||
keyType: DuckDBType,
|
||||
valueType: DuckDBType,
|
||||
alias?: string,
|
||||
) {
|
||||
super(DuckDBTypeId.MAP, alias);
|
||||
this.keyType = keyType;
|
||||
this.valueType = valueType;
|
||||
}
|
||||
public toString(options?: DuckDBTypeToStringOptions): string {
|
||||
if (this.alias) {
|
||||
return this.alias;
|
||||
}
|
||||
if (options?.short) {
|
||||
return `MAP(…)`;
|
||||
}
|
||||
return `MAP(${this.keyType}, ${this.valueType})`;
|
||||
}
|
||||
public override toJson(): Json {
|
||||
return {
|
||||
typeId: this.typeId,
|
||||
keyType: this.keyType.toJson(),
|
||||
valueType: this.valueType.toJson(),
|
||||
...(this.alias ? { alias: this.alias } : {}),
|
||||
};
|
||||
}
|
||||
}
|
||||
export function MAP(
|
||||
keyType: DuckDBType,
|
||||
valueType: DuckDBType,
|
||||
alias?: string,
|
||||
): DuckDBMapType {
|
||||
return new DuckDBMapType(keyType, valueType, alias);
|
||||
}
|
||||
|
||||
export class DuckDBArrayType extends BaseDuckDBType<DuckDBTypeId.ARRAY> {
|
||||
public readonly valueType: DuckDBType;
|
||||
public readonly length: number;
|
||||
public constructor(valueType: DuckDBType, length: number, alias?: string) {
|
||||
super(DuckDBTypeId.ARRAY, alias);
|
||||
this.valueType = valueType;
|
||||
this.length = length;
|
||||
}
|
||||
public toString(options?: DuckDBTypeToStringOptions): string {
|
||||
return this.alias ?? `${this.valueType.toString(options)}[${this.length}]`;
|
||||
}
|
||||
public override toJson(): Json {
|
||||
return {
|
||||
typeId: this.typeId,
|
||||
valueType: this.valueType.toJson(),
|
||||
length: this.length,
|
||||
...(this.alias ? { alias: this.alias } : {}),
|
||||
};
|
||||
}
|
||||
}
|
||||
export function ARRAY(
|
||||
valueType: DuckDBType,
|
||||
length: number,
|
||||
alias?: string,
|
||||
): DuckDBArrayType {
|
||||
return new DuckDBArrayType(valueType, length, alias);
|
||||
}
|
||||
|
||||
export class DuckDBUUIDType extends BaseDuckDBType<DuckDBTypeId.UUID> {
|
||||
public constructor(alias?: string) {
|
||||
super(DuckDBTypeId.UUID, alias);
|
||||
}
|
||||
public static readonly instance = new DuckDBUUIDType();
|
||||
public static create(alias?: string): DuckDBUUIDType {
|
||||
return alias ? new DuckDBUUIDType(alias) : DuckDBUUIDType.instance;
|
||||
}
|
||||
// TODO: common DuckDBValues on type objects
|
||||
// public get max() {
|
||||
// return DuckDBUUIDValue.Max;
|
||||
// }
|
||||
// public get min() {
|
||||
// return DuckDBUUIDValue.Min;
|
||||
// }
|
||||
}
|
||||
export const UUID = DuckDBUUIDType.instance;
|
||||
|
||||
export class DuckDBUnionType extends BaseDuckDBType<DuckDBTypeId.UNION> {
|
||||
public readonly memberTags: readonly string[];
|
||||
public readonly tagMemberIndexes: Readonly<Record<string, number>>;
|
||||
public readonly memberTypes: readonly DuckDBType[];
|
||||
public constructor(
|
||||
memberTags: readonly string[],
|
||||
memberTypes: readonly DuckDBType[],
|
||||
alias?: string,
|
||||
) {
|
||||
super(DuckDBTypeId.UNION, alias);
|
||||
if (memberTags.length !== memberTypes.length) {
|
||||
throw new Error(`Could not create DuckDBUnionType: \
|
||||
tags length (${memberTags.length}) does not match valueTypes length (${memberTypes.length})`);
|
||||
}
|
||||
this.memberTags = memberTags;
|
||||
const tagMemberIndexes: Record<string, number> = {};
|
||||
for (let i = 0; i < memberTags.length; i++) {
|
||||
tagMemberIndexes[memberTags[i]] = i;
|
||||
}
|
||||
this.tagMemberIndexes = tagMemberIndexes;
|
||||
this.memberTypes = memberTypes;
|
||||
}
|
||||
public memberIndexForTag(tag: string): number {
|
||||
return this.tagMemberIndexes[tag];
|
||||
}
|
||||
public memberTypeForTag(tag: string): DuckDBType {
|
||||
return this.memberTypes[this.tagMemberIndexes[tag]];
|
||||
}
|
||||
public get memberCount() {
|
||||
return this.memberTags.length;
|
||||
}
|
||||
public toString(options?: DuckDBTypeToStringOptions): string {
|
||||
if (this.alias) {
|
||||
return this.alias;
|
||||
}
|
||||
if (options?.short) {
|
||||
return `UNION(…)`;
|
||||
}
|
||||
const parts: string[] = [];
|
||||
for (let i = 0; i < this.memberTags.length; i++) {
|
||||
parts.push(
|
||||
`${quotedIdentifier(this.memberTags[i])} ${this.memberTypes[i]}`,
|
||||
);
|
||||
}
|
||||
return `UNION(${parts.join(', ')})`;
|
||||
}
|
||||
public override toJson(): Json {
|
||||
return {
|
||||
typeId: this.typeId,
|
||||
memberTags: [...this.memberTags],
|
||||
memberTypes: this.memberTypes.map((t) => t.toJson()),
|
||||
...(this.alias ? { alias: this.alias } : {}),
|
||||
};
|
||||
}
|
||||
}
|
||||
export function UNION(
|
||||
members: Record<string, DuckDBType>,
|
||||
alias?: string,
|
||||
): DuckDBUnionType {
|
||||
const memberTags = Object.keys(members);
|
||||
const memberTypes = Object.values(members);
|
||||
return new DuckDBUnionType(memberTags, memberTypes, alias);
|
||||
}
|
||||
|
||||
export class DuckDBBitType extends BaseDuckDBType<DuckDBTypeId.BIT> {
|
||||
public constructor(alias?: string) {
|
||||
super(DuckDBTypeId.BIT, alias);
|
||||
}
|
||||
public static readonly instance = new DuckDBBitType();
|
||||
public static create(alias?: string): DuckDBBitType {
|
||||
return alias ? new DuckDBBitType(alias) : DuckDBBitType.instance;
|
||||
}
|
||||
}
|
||||
export const BIT = DuckDBBitType.instance;
|
||||
|
||||
export class DuckDBTimeTZType extends BaseDuckDBType<DuckDBTypeId.TIME_TZ> {
|
||||
public constructor(alias?: string) {
|
||||
super(DuckDBTypeId.TIME_TZ, alias);
|
||||
}
|
||||
public toString(options?: DuckDBTypeToStringOptions): string {
|
||||
if (this.alias) {
|
||||
return this.alias;
|
||||
}
|
||||
if (options?.short) {
|
||||
return 'TIMETZ';
|
||||
}
|
||||
return 'TIME WITH TIME ZONE';
|
||||
}
|
||||
public static readonly instance = new DuckDBTimeTZType();
|
||||
public static create(alias?: string): DuckDBTimeTZType {
|
||||
return alias ? new DuckDBTimeTZType(alias) : DuckDBTimeTZType.instance;
|
||||
}
|
||||
// TODO: common DuckDBValues on type objects
|
||||
// public get max() {
|
||||
// return DuckDBTimeTZValue.Max;
|
||||
// }
|
||||
// public get min() {
|
||||
// return DuckDBTimeTZValue.Min;
|
||||
// }
|
||||
}
|
||||
export const TIMETZ = DuckDBTimeTZType.instance;
|
||||
|
||||
export class DuckDBTimestampTZType extends BaseDuckDBType<DuckDBTypeId.TIMESTAMP_TZ> {
|
||||
public constructor(alias?: string) {
|
||||
super(DuckDBTypeId.TIMESTAMP_TZ, alias);
|
||||
}
|
||||
public toString(options?: DuckDBTypeToStringOptions): string {
|
||||
if (this.alias) {
|
||||
return this.alias;
|
||||
}
|
||||
if (options?.short) {
|
||||
return 'TIMESTAMPTZ';
|
||||
}
|
||||
return 'TIMESTAMP WITH TIME ZONE';
|
||||
}
|
||||
public static readonly instance = new DuckDBTimestampTZType();
|
||||
public static create(alias?: string): DuckDBTimestampTZType {
|
||||
return alias
|
||||
? new DuckDBTimestampTZType(alias)
|
||||
: DuckDBTimestampTZType.instance;
|
||||
}
|
||||
// TODO: common DuckDBValues on type objects
|
||||
// public get epoch() {
|
||||
// return DuckDBTimestampTZValue.Epoch;
|
||||
// }
|
||||
// public get max() {
|
||||
// return DuckDBTimestampTZValue.Max;
|
||||
// }
|
||||
// public get min() {
|
||||
// return DuckDBTimestampTZValue.Min;
|
||||
// }
|
||||
// public get posInf() {
|
||||
// return DuckDBTimestampTZValue.PosInf;
|
||||
// }
|
||||
// public get negInf() {
|
||||
// return DuckDBTimestampTZValue.NegInf;
|
||||
// }
|
||||
}
|
||||
export const TIMESTAMPTZ = DuckDBTimestampTZType.instance;
|
||||
|
||||
export class DuckDBAnyType extends BaseDuckDBType<DuckDBTypeId.ANY> {
|
||||
public constructor(alias?: string) {
|
||||
super(DuckDBTypeId.ANY, alias);
|
||||
}
|
||||
public static readonly instance = new DuckDBAnyType();
|
||||
public static create(alias?: string): DuckDBAnyType {
|
||||
return alias ? new DuckDBAnyType(alias) : DuckDBAnyType.instance;
|
||||
}
|
||||
}
|
||||
export const ANY = DuckDBAnyType.instance;
|
||||
|
||||
export class DuckDBVarIntType extends BaseDuckDBType<DuckDBTypeId.VARINT> {
|
||||
public constructor(alias?: string) {
|
||||
super(DuckDBTypeId.VARINT, alias);
|
||||
}
|
||||
public static readonly instance = new DuckDBVarIntType();
|
||||
public static create(alias?: string): DuckDBVarIntType {
|
||||
return alias ? new DuckDBVarIntType(alias) : DuckDBVarIntType.instance;
|
||||
}
|
||||
public static readonly Max: bigint =
|
||||
179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368n;
|
||||
public static readonly Min: bigint =
|
||||
-179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368n;
|
||||
public get max() {
|
||||
return DuckDBVarIntType.Max;
|
||||
}
|
||||
public get min() {
|
||||
return DuckDBVarIntType.Min;
|
||||
}
|
||||
}
|
||||
export const VARINT = DuckDBVarIntType.instance;
|
||||
|
||||
export class DuckDBSQLNullType extends BaseDuckDBType<DuckDBTypeId.SQLNULL> {
|
||||
public constructor(alias?: string) {
|
||||
super(DuckDBTypeId.SQLNULL, alias);
|
||||
}
|
||||
public static readonly instance = new DuckDBSQLNullType();
|
||||
public static create(alias?: string): DuckDBSQLNullType {
|
||||
return alias ? new DuckDBSQLNullType(alias) : DuckDBSQLNullType.instance;
|
||||
}
|
||||
}
|
||||
export const SQLNULL = DuckDBSQLNullType.instance;
|
||||
|
||||
export class DuckDBStringLiteralType extends BaseDuckDBType<DuckDBTypeId.STRING_LITERAL> {
|
||||
public constructor(alias?: string) {
|
||||
super(DuckDBTypeId.STRING_LITERAL, alias);
|
||||
}
|
||||
public static readonly instance = new DuckDBStringLiteralType();
|
||||
public static create(alias?: string): DuckDBStringLiteralType {
|
||||
return alias
|
||||
? new DuckDBStringLiteralType(alias)
|
||||
: DuckDBStringLiteralType.instance;
|
||||
}
|
||||
}
|
||||
export const STRING_LITERAL = DuckDBStringLiteralType.instance;
|
||||
|
||||
export class DuckDBIntegerLiteralType extends BaseDuckDBType<DuckDBTypeId.INTEGER_LITERAL> {
|
||||
public constructor(alias?: string) {
|
||||
super(DuckDBTypeId.INTEGER_LITERAL, alias);
|
||||
}
|
||||
public static readonly instance = new DuckDBIntegerLiteralType();
|
||||
public static create(alias?: string): DuckDBIntegerLiteralType {
|
||||
return alias
|
||||
? new DuckDBIntegerLiteralType(alias)
|
||||
: DuckDBIntegerLiteralType.instance;
|
||||
}
|
||||
}
|
||||
export const INTEGER_LITERAL = DuckDBIntegerLiteralType.instance;
|
||||
|
||||
export type DuckDBType =
|
||||
| DuckDBBooleanType
|
||||
| DuckDBTinyIntType
|
||||
| DuckDBSmallIntType
|
||||
| DuckDBIntegerType
|
||||
| DuckDBBigIntType
|
||||
| DuckDBUTinyIntType
|
||||
| DuckDBUSmallIntType
|
||||
| DuckDBUIntegerType
|
||||
| DuckDBUBigIntType
|
||||
| DuckDBFloatType
|
||||
| DuckDBDoubleType
|
||||
| DuckDBTimestampType
|
||||
| DuckDBDateType
|
||||
| DuckDBTimeType
|
||||
| DuckDBIntervalType
|
||||
| DuckDBHugeIntType
|
||||
| DuckDBUHugeIntType
|
||||
| DuckDBVarCharType
|
||||
| DuckDBBlobType
|
||||
| DuckDBDecimalType
|
||||
| DuckDBTimestampSecondsType
|
||||
| DuckDBTimestampMillisecondsType
|
||||
| DuckDBTimestampNanosecondsType
|
||||
| DuckDBEnumType
|
||||
| DuckDBListType
|
||||
| DuckDBStructType
|
||||
| DuckDBMapType
|
||||
| DuckDBArrayType
|
||||
| DuckDBUUIDType
|
||||
| DuckDBUnionType
|
||||
| DuckDBBitType
|
||||
| DuckDBTimeTZType
|
||||
| DuckDBTimestampTZType
|
||||
| DuckDBAnyType
|
||||
| DuckDBVarIntType
|
||||
| DuckDBSQLNullType
|
||||
| DuckDBStringLiteralType
|
||||
| DuckDBIntegerLiteralType;
|
||||
42
ts/pkgs/duckdb-data-types/src/DuckDBTypeId.ts
Normal file
42
ts/pkgs/duckdb-data-types/src/DuckDBTypeId.ts
Normal file
@@ -0,0 +1,42 @@
|
||||
// copy of DUCKDB_TYPE from the C API, with names shortened
|
||||
export enum DuckDBTypeId {
|
||||
INVALID = 0,
|
||||
BOOLEAN = 1,
|
||||
TINYINT = 2,
|
||||
SMALLINT = 3,
|
||||
INTEGER = 4,
|
||||
BIGINT = 5,
|
||||
UTINYINT = 6,
|
||||
USMALLINT = 7,
|
||||
UINTEGER = 8,
|
||||
UBIGINT = 9,
|
||||
FLOAT = 10,
|
||||
DOUBLE = 11,
|
||||
TIMESTAMP = 12,
|
||||
DATE = 13,
|
||||
TIME = 14,
|
||||
INTERVAL = 15,
|
||||
HUGEINT = 16,
|
||||
UHUGEINT = 32,
|
||||
VARCHAR = 17,
|
||||
BLOB = 18,
|
||||
DECIMAL = 19,
|
||||
TIMESTAMP_S = 20,
|
||||
TIMESTAMP_MS = 21,
|
||||
TIMESTAMP_NS = 22,
|
||||
ENUM = 23,
|
||||
LIST = 24,
|
||||
STRUCT = 25,
|
||||
MAP = 26,
|
||||
ARRAY = 33,
|
||||
UUID = 27,
|
||||
UNION = 28,
|
||||
BIT = 29,
|
||||
TIME_TZ = 30,
|
||||
TIMESTAMP_TZ = 31,
|
||||
ANY = 34,
|
||||
VARINT = 35,
|
||||
SQLNULL = 36,
|
||||
STRING_LITERAL = 37,
|
||||
INTEGER_LITERAL = 38,
|
||||
}
|
||||
46
ts/pkgs/duckdb-data-types/src/extensionTypes.ts
Normal file
46
ts/pkgs/duckdb-data-types/src/extensionTypes.ts
Normal file
@@ -0,0 +1,46 @@
|
||||
import {
|
||||
DOUBLE,
|
||||
DuckDBBlobType,
|
||||
DuckDBVarCharType,
|
||||
FLOAT,
|
||||
HUGEINT,
|
||||
LIST,
|
||||
STRUCT,
|
||||
USMALLINT,
|
||||
UTINYINT,
|
||||
} from './DuckDBType.js';
|
||||
|
||||
// see https://github.com/duckdb/duckdb-inet/blob/main/src/inet_extension.cpp
|
||||
export const INET = STRUCT(
|
||||
{ ip_type: UTINYINT, address: HUGEINT, mask: USMALLINT },
|
||||
'INET',
|
||||
);
|
||||
|
||||
// see LogicalType::JSON() in https://github.com/duckdb/duckdb/blob/main/src/common/types.cpp
|
||||
export const JSONType = DuckDBVarCharType.create('JSON');
|
||||
|
||||
// see https://github.com/duckdb/duckdb-spatial/blob/main/src/spatial/spatial_types.cpp
|
||||
export const BOX_2D = STRUCT(
|
||||
{ min_x: DOUBLE, min_y: DOUBLE, max_x: DOUBLE, max_y: DOUBLE },
|
||||
'BOX_2D',
|
||||
);
|
||||
export const BOX_2DF = STRUCT(
|
||||
{ min_x: FLOAT, min_y: FLOAT, max_x: FLOAT, max_y: FLOAT },
|
||||
'BOX_2DF',
|
||||
);
|
||||
export const GEOMETRY = DuckDBBlobType.create('GEOMETRY');
|
||||
export const LINESTRING_2D = LIST(
|
||||
STRUCT({ x: DOUBLE, y: DOUBLE }),
|
||||
'LINESTRING_2D',
|
||||
);
|
||||
export const POINT_2D = STRUCT({ x: DOUBLE, y: DOUBLE }, 'POINT_2D');
|
||||
export const POINT_3D = STRUCT({ x: DOUBLE, y: DOUBLE, z: DOUBLE }, 'POINT_3D');
|
||||
export const POINT_4D = STRUCT(
|
||||
{ x: DOUBLE, y: DOUBLE, z: DOUBLE, m: DOUBLE },
|
||||
'POINT_4D',
|
||||
);
|
||||
export const POLYGON_2D = LIST(
|
||||
LIST(STRUCT({ x: DOUBLE, y: DOUBLE })),
|
||||
'POLYGON_2D',
|
||||
);
|
||||
export const WKB_BLOB = DuckDBBlobType.create('WKB_BLOB');
|
||||
4
ts/pkgs/duckdb-data-types/src/index.ts
Normal file
4
ts/pkgs/duckdb-data-types/src/index.ts
Normal file
@@ -0,0 +1,4 @@
|
||||
export * from './DuckDBType.js';
|
||||
export * from './DuckDBTypeId.js';
|
||||
export * from './extensionTypes.js';
|
||||
export * from './parseLogicalTypeString.js';
|
||||
286
ts/pkgs/duckdb-data-types/src/parseLogicalTypeString.ts
Normal file
286
ts/pkgs/duckdb-data-types/src/parseLogicalTypeString.ts
Normal file
@@ -0,0 +1,286 @@
|
||||
import {
|
||||
ARRAY,
|
||||
BIGINT,
|
||||
BIT,
|
||||
BLOB,
|
||||
BOOLEAN,
|
||||
DATE,
|
||||
DECIMAL,
|
||||
DOUBLE,
|
||||
DuckDBMapType,
|
||||
DuckDBStructType,
|
||||
DuckDBType,
|
||||
DuckDBUnionType,
|
||||
ENUM,
|
||||
FLOAT,
|
||||
HUGEINT,
|
||||
INTEGER,
|
||||
INTERVAL,
|
||||
LIST,
|
||||
MAP,
|
||||
SMALLINT,
|
||||
SQLNULL,
|
||||
STRUCT,
|
||||
TIME,
|
||||
TIMESTAMP,
|
||||
TIMESTAMP_MS,
|
||||
TIMESTAMP_NS,
|
||||
TIMESTAMP_S,
|
||||
TIMESTAMPTZ,
|
||||
TIMETZ,
|
||||
TINYINT,
|
||||
UBIGINT,
|
||||
UHUGEINT,
|
||||
UINTEGER,
|
||||
UNION,
|
||||
USMALLINT,
|
||||
UTINYINT,
|
||||
UUID,
|
||||
VARCHAR,
|
||||
VARINT,
|
||||
} from './DuckDBType.js';
|
||||
import {
|
||||
BOX_2D,
|
||||
BOX_2DF,
|
||||
GEOMETRY,
|
||||
INET,
|
||||
JSONType,
|
||||
LINESTRING_2D,
|
||||
POINT_2D,
|
||||
POINT_3D,
|
||||
POINT_4D,
|
||||
POLYGON_2D,
|
||||
WKB_BLOB,
|
||||
} from './extensionTypes.js';
|
||||
|
||||
const simpleTypeMap: Record<string, DuckDBType> = {
|
||||
BIGINT: BIGINT,
|
||||
BIT: BIT,
|
||||
BOOLEAN: BOOLEAN,
|
||||
BLOB: BLOB,
|
||||
BOX_2D: BOX_2D,
|
||||
BOX_2DF: BOX_2DF,
|
||||
DATE: DATE,
|
||||
DOUBLE: DOUBLE,
|
||||
FLOAT: FLOAT,
|
||||
GEOMETRY: GEOMETRY,
|
||||
HUGEINT: HUGEINT,
|
||||
INET: INET,
|
||||
INTEGER: INTEGER,
|
||||
INTERVAL: INTERVAL,
|
||||
JSON: JSONType,
|
||||
LINESTRING_2D: LINESTRING_2D,
|
||||
POINT_2D: POINT_2D,
|
||||
POINT_3D: POINT_3D,
|
||||
POINT_4D: POINT_4D,
|
||||
POLYGON_2D: POLYGON_2D,
|
||||
SMALLINT: SMALLINT,
|
||||
SQLNULL: SQLNULL,
|
||||
TIME: TIME,
|
||||
'TIME WITH TIME ZONE': TIMETZ,
|
||||
TIMESTAMP: TIMESTAMP,
|
||||
'TIMESTAMP WITH TIME ZONE': TIMESTAMPTZ,
|
||||
TIMESTAMP_S: TIMESTAMP_S,
|
||||
TIMESTAMP_MS: TIMESTAMP_MS,
|
||||
TIMESTAMP_NS: TIMESTAMP_NS,
|
||||
TINYINT: TINYINT,
|
||||
UBIGINT: UBIGINT,
|
||||
UHUGEINT: UHUGEINT,
|
||||
UINTEGER: UINTEGER,
|
||||
USMALLINT: USMALLINT,
|
||||
UTINYINT: UTINYINT,
|
||||
UUID: UUID,
|
||||
VARCHAR: VARCHAR,
|
||||
VARINT: VARINT,
|
||||
WKB_BLOB: WKB_BLOB,
|
||||
};
|
||||
|
||||
function matchStructMapOrUnion(
|
||||
typeString: string,
|
||||
): DuckDBStructType | DuckDBMapType | DuckDBUnionType | undefined {
|
||||
typeString = typeString.trim();
|
||||
|
||||
const fields = parseStructLike(typeString);
|
||||
if (!fields) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
if (typeString.startsWith('STRUCT')) {
|
||||
const entries: Record<string, DuckDBType> = {};
|
||||
for (const field of fields) {
|
||||
if (field.key && field.type) {
|
||||
entries[field.key] = field.type;
|
||||
}
|
||||
}
|
||||
return STRUCT(entries);
|
||||
}
|
||||
if (typeString.startsWith('MAP')) {
|
||||
const keyType = fields[0]?.type;
|
||||
const valueType = fields[1]?.type;
|
||||
if (keyType && valueType) {
|
||||
return MAP(keyType, valueType);
|
||||
}
|
||||
}
|
||||
if (typeString.startsWith('UNION')) {
|
||||
const members: Record<string, DuckDBType> = {};
|
||||
for (const field of fields) {
|
||||
if (field.key && field.type) {
|
||||
members[field.key] = field.type;
|
||||
}
|
||||
}
|
||||
return UNION(members);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function parseStructLike(typeString: string): ParsedField[] | undefined {
|
||||
const structPattern = /^(STRUCT|MAP|UNION)\s*\((.*)\)$/;
|
||||
const match = structPattern.exec(typeString);
|
||||
if (!match) {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
const fieldsString = match[2];
|
||||
return parseFields(fieldsString);
|
||||
}
|
||||
|
||||
/** Parse the fields substring. We do this by counting parens and double quotes.
|
||||
* When checking for double-quotes, we only need to count an even number of them
|
||||
* to count brackets, since in cases where there escaped double quotes inside
|
||||
* a double-quoted string, the double quotes appear adjacent to each other,
|
||||
* always incrementing the count by 2 before there could theoretically be another
|
||||
* paren.
|
||||
*/
|
||||
function parseFields(fieldsString: string): ParsedField[] {
|
||||
const fields: ParsedField[] = [];
|
||||
let currentFieldStartIndex: number | null = null;
|
||||
let parenCount = 0;
|
||||
let quoteCount = 0;
|
||||
|
||||
for (let i = 0; i < fieldsString.length; i++) {
|
||||
const char = fieldsString[i];
|
||||
|
||||
if (
|
||||
currentFieldStartIndex === null &&
|
||||
char !== '(' &&
|
||||
char !== ')' &&
|
||||
char !== ','
|
||||
) {
|
||||
currentFieldStartIndex = i;
|
||||
}
|
||||
|
||||
if (char === '"') {
|
||||
quoteCount++;
|
||||
}
|
||||
|
||||
if (
|
||||
char === ',' &&
|
||||
parenCount === 0 &&
|
||||
quoteCount % 2 === 0 &&
|
||||
currentFieldStartIndex !== null
|
||||
) {
|
||||
const field = fieldsString.slice(currentFieldStartIndex, i);
|
||||
fields.push(parseField(field.trim()));
|
||||
currentFieldStartIndex = null;
|
||||
} else {
|
||||
if (char === '(' && quoteCount % 2 === 0) parenCount++;
|
||||
if (char === ')' && quoteCount % 2 === 0) parenCount--;
|
||||
}
|
||||
}
|
||||
|
||||
if (currentFieldStartIndex !== null) {
|
||||
const lastField = fieldsString.slice(currentFieldStartIndex);
|
||||
fields.push(parseField(lastField.trim()));
|
||||
}
|
||||
return fields;
|
||||
}
|
||||
|
||||
interface ParsedField {
|
||||
key?: string;
|
||||
type?: DuckDBType;
|
||||
}
|
||||
|
||||
function parseField(fieldString: string): ParsedField {
|
||||
const fieldPattern = /^(".*?"|\w+)\s+(.+)$/;
|
||||
const match = fieldPattern.exec(fieldString);
|
||||
if (match) {
|
||||
const key = match[1];
|
||||
const type = parseLogicalTypeString(match[2].trim());
|
||||
return { key, type };
|
||||
} else {
|
||||
const type = parseLogicalTypeString(fieldString);
|
||||
return { type };
|
||||
}
|
||||
}
|
||||
|
||||
function matchDecimal(typeString: string) {
|
||||
const match = typeString.match(/^DECIMAL\((\d+),(\d+)\)$/);
|
||||
if (match) {
|
||||
return DECIMAL(Number(match[1]), Number(match[2]));
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function matchEnum(typeString: string) {
|
||||
const match = /ENUM\(([^)]*)\)/i.exec(typeString);
|
||||
if (match) {
|
||||
const matches = match[1].matchAll(/'((?:[^']|'')*)'/g);
|
||||
const values: string[] = [];
|
||||
for (const match of matches) {
|
||||
values.push(match[1].replace(/''/, `'`));
|
||||
}
|
||||
return ENUM(values);
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function matchList(typeString: string) {
|
||||
if (typeString.endsWith('[]')) {
|
||||
const innerType = typeString.slice(0, -2);
|
||||
return LIST(parseLogicalTypeString(innerType));
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function matchArray(typeString: string) {
|
||||
const match = typeString.match(/\[(\d+)\]$/);
|
||||
if (match) {
|
||||
const innerType = typeString.slice(0, -match[0].length);
|
||||
const length = match[1];
|
||||
return ARRAY(parseLogicalTypeString(innerType), Number(length));
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
|
||||
export function parseLogicalTypeString(typeString: string): DuckDBType {
|
||||
if (typeString in simpleTypeMap) {
|
||||
return simpleTypeMap[typeString];
|
||||
}
|
||||
|
||||
const listType = matchList(typeString);
|
||||
if (listType) {
|
||||
return listType;
|
||||
}
|
||||
|
||||
const arrayType = matchArray(typeString);
|
||||
if (arrayType) {
|
||||
return arrayType;
|
||||
}
|
||||
|
||||
const decimalType = matchDecimal(typeString);
|
||||
if (decimalType) {
|
||||
return decimalType;
|
||||
}
|
||||
|
||||
const enumType = matchEnum(typeString);
|
||||
if (enumType) {
|
||||
return enumType;
|
||||
}
|
||||
|
||||
const structMapOrUnionType = matchStructMapOrUnion(typeString);
|
||||
if (structMapOrUnionType) {
|
||||
return structMapOrUnionType;
|
||||
}
|
||||
|
||||
throw Error(`unimplemented type match: ${typeString}`);
|
||||
}
|
||||
7
ts/pkgs/duckdb-data-types/src/sql.ts
Normal file
7
ts/pkgs/duckdb-data-types/src/sql.ts
Normal file
@@ -0,0 +1,7 @@
|
||||
export function quotedString(input: string): string {
|
||||
return `'${input.replace(`'`, `''`)}'`;
|
||||
}
|
||||
|
||||
export function quotedIdentifier(input: string): string {
|
||||
return `"${input.replace(`"`, `""`)}"`;
|
||||
}
|
||||
6
ts/pkgs/duckdb-data-types/src/tsconfig.json
Normal file
6
ts/pkgs/duckdb-data-types/src/tsconfig.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"extends": "../../../tsconfig.library.json",
|
||||
"compilerOptions": {
|
||||
"outDir": "../out"
|
||||
}
|
||||
}
|
||||
1025
ts/pkgs/duckdb-data-types/test/DuckDBType.test.ts
Normal file
1025
ts/pkgs/duckdb-data-types/test/DuckDBType.test.ts
Normal file
File diff suppressed because it is too large
Load Diff
326
ts/pkgs/duckdb-data-types/test/parseLogicalTypeString.test.ts
Normal file
326
ts/pkgs/duckdb-data-types/test/parseLogicalTypeString.test.ts
Normal file
@@ -0,0 +1,326 @@
|
||||
import { expect, suite, test } from 'vitest';
|
||||
import {
|
||||
ARRAY,
|
||||
BIGINT,
|
||||
BIT,
|
||||
BLOB,
|
||||
BOOLEAN,
|
||||
DATE,
|
||||
DECIMAL,
|
||||
DOUBLE,
|
||||
ENUM,
|
||||
FLOAT,
|
||||
HUGEINT,
|
||||
INTEGER,
|
||||
INTERVAL,
|
||||
LIST,
|
||||
MAP,
|
||||
SMALLINT,
|
||||
STRUCT,
|
||||
TIME,
|
||||
TIMESTAMP,
|
||||
TIMESTAMP_MS,
|
||||
TIMESTAMP_NS,
|
||||
TIMESTAMP_S,
|
||||
TIMESTAMPTZ,
|
||||
TIMETZ,
|
||||
TINYINT,
|
||||
UBIGINT,
|
||||
UHUGEINT,
|
||||
UINTEGER,
|
||||
UNION,
|
||||
USMALLINT,
|
||||
UTINYINT,
|
||||
UUID,
|
||||
VARCHAR,
|
||||
VARINT,
|
||||
} from '../src/DuckDBType';
|
||||
import {
|
||||
BOX_2D,
|
||||
BOX_2DF,
|
||||
GEOMETRY,
|
||||
INET,
|
||||
JSONType,
|
||||
LINESTRING_2D,
|
||||
POINT_2D,
|
||||
POINT_3D,
|
||||
POINT_4D,
|
||||
POLYGON_2D,
|
||||
WKB_BLOB,
|
||||
} from '../src/extensionTypes';
|
||||
import { parseLogicalTypeString } from '../src/parseLogicalTypeString';
|
||||
|
||||
suite('parseLogicalTypeString', () => {
|
||||
test('BOOLEAN', () => {
|
||||
expect(parseLogicalTypeString('BOOLEAN')).toStrictEqual(BOOLEAN);
|
||||
});
|
||||
test('TINYINT', () => {
|
||||
expect(parseLogicalTypeString('TINYINT')).toStrictEqual(TINYINT);
|
||||
});
|
||||
test('GEOMETRY', () => {
|
||||
expect(parseLogicalTypeString('GEOMETRY')).toStrictEqual(GEOMETRY);
|
||||
});
|
||||
test('LINESTRING_2D', () => {
|
||||
expect(parseLogicalTypeString('LINESTRING_2D')).toStrictEqual(
|
||||
LINESTRING_2D,
|
||||
);
|
||||
});
|
||||
test('BOX_2D', () => {
|
||||
expect(parseLogicalTypeString('BOX_2D')).toStrictEqual(BOX_2D);
|
||||
});
|
||||
test('BOX_2DF', () => {
|
||||
expect(parseLogicalTypeString('BOX_2DF')).toStrictEqual(BOX_2DF);
|
||||
});
|
||||
test('POINT_2D', () => {
|
||||
expect(parseLogicalTypeString('POINT_2D')).toStrictEqual(POINT_2D);
|
||||
});
|
||||
test('POINT_3D', () => {
|
||||
expect(parseLogicalTypeString('POINT_3D')).toStrictEqual(POINT_3D);
|
||||
});
|
||||
test('POINT_4D', () => {
|
||||
expect(parseLogicalTypeString('POINT_4D')).toStrictEqual(POINT_4D);
|
||||
});
|
||||
test('POLYGON_2D', () => {
|
||||
expect(parseLogicalTypeString('POLYGON_2D')).toStrictEqual(POLYGON_2D);
|
||||
});
|
||||
test('INET', () => {
|
||||
expect(parseLogicalTypeString('INET')).toStrictEqual(INET);
|
||||
});
|
||||
test('JSON', () => {
|
||||
expect(parseLogicalTypeString('JSON')).toStrictEqual(JSONType);
|
||||
});
|
||||
test('WKB_BLOB', () => {
|
||||
expect(parseLogicalTypeString('WKB_BLOB')).toStrictEqual(WKB_BLOB);
|
||||
});
|
||||
test('SMALLINT', () => {
|
||||
expect(parseLogicalTypeString('SMALLINT')).toStrictEqual(SMALLINT);
|
||||
});
|
||||
test('INTEGER', () => {
|
||||
expect(parseLogicalTypeString('INTEGER')).toStrictEqual(INTEGER);
|
||||
});
|
||||
test('BIGINT', () => {
|
||||
expect(parseLogicalTypeString('BIGINT')).toStrictEqual(BIGINT);
|
||||
});
|
||||
test('HUGEINT', () => {
|
||||
expect(parseLogicalTypeString('HUGEINT')).toStrictEqual(HUGEINT);
|
||||
});
|
||||
test('UTINYINT', () => {
|
||||
expect(parseLogicalTypeString('UTINYINT')).toStrictEqual(UTINYINT);
|
||||
});
|
||||
test('UHUGEINT', () => {
|
||||
expect(parseLogicalTypeString('UHUGEINT')).toStrictEqual(UHUGEINT);
|
||||
});
|
||||
test('USMALLINT', () => {
|
||||
expect(parseLogicalTypeString('USMALLINT')).toStrictEqual(USMALLINT);
|
||||
});
|
||||
test('UINTEGER', () => {
|
||||
expect(parseLogicalTypeString('UINTEGER')).toStrictEqual(UINTEGER);
|
||||
});
|
||||
test('UBIGINT', () => {
|
||||
expect(parseLogicalTypeString('UBIGINT')).toStrictEqual(UBIGINT);
|
||||
});
|
||||
test('DATE', () => {
|
||||
expect(parseLogicalTypeString('DATE')).toStrictEqual(DATE);
|
||||
});
|
||||
test('TIME', () => {
|
||||
expect(parseLogicalTypeString('TIME')).toStrictEqual(TIME);
|
||||
});
|
||||
test('TIMESTAMP', () => {
|
||||
expect(parseLogicalTypeString('TIMESTAMP')).toStrictEqual(TIMESTAMP);
|
||||
});
|
||||
test('TIMESTAMP_S', () => {
|
||||
expect(parseLogicalTypeString('TIMESTAMP_S')).toStrictEqual(TIMESTAMP_S);
|
||||
});
|
||||
test('TIMESTAMP_MS', () => {
|
||||
expect(parseLogicalTypeString('TIMESTAMP_MS')).toStrictEqual(TIMESTAMP_MS);
|
||||
});
|
||||
test('TIMESTAMP_NS', () => {
|
||||
expect(parseLogicalTypeString('TIMESTAMP_NS')).toStrictEqual(TIMESTAMP_NS);
|
||||
});
|
||||
test('TIME WITH TIME ZONE', () => {
|
||||
expect(parseLogicalTypeString('TIME WITH TIME ZONE')).toStrictEqual(TIMETZ);
|
||||
});
|
||||
test('TIMESTAMP WITH TIME ZONE', () => {
|
||||
expect(parseLogicalTypeString('TIMESTAMP WITH TIME ZONE')).toStrictEqual(
|
||||
TIMESTAMPTZ,
|
||||
);
|
||||
});
|
||||
test('FLOAT', () => {
|
||||
expect(parseLogicalTypeString('FLOAT')).toStrictEqual(FLOAT);
|
||||
});
|
||||
test('DOUBLE', () => {
|
||||
expect(parseLogicalTypeString('DOUBLE')).toStrictEqual(DOUBLE);
|
||||
});
|
||||
|
||||
test('DECIMAL(18,6)', () => {
|
||||
expect(parseLogicalTypeString('DECIMAL(18,6)')).toStrictEqual(
|
||||
DECIMAL(18, 6),
|
||||
);
|
||||
});
|
||||
|
||||
test(`ENUM('DUCK_DUCK_ENUM', 'GOOSE')`, () => {
|
||||
expect(
|
||||
parseLogicalTypeString(`ENUM('DUCK_DUCK_ENUM', 'GOOSE')`),
|
||||
).toStrictEqual(ENUM(['DUCK_DUCK_ENUM', 'GOOSE']));
|
||||
});
|
||||
|
||||
test('DOUBLE[]', () => {
|
||||
expect(parseLogicalTypeString('DOUBLE[]')).toStrictEqual(LIST(DOUBLE));
|
||||
});
|
||||
|
||||
test('STRUCT(a INTEGER, b VARCHAR)', () => {
|
||||
expect(
|
||||
parseLogicalTypeString('STRUCT(a INTEGER, b VARCHAR)'),
|
||||
).toStrictEqual(
|
||||
STRUCT({
|
||||
a: INTEGER,
|
||||
b: VARCHAR,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
test('STRUCT(a INTEGER[], b VARCHAR[])', () => {
|
||||
expect(
|
||||
parseLogicalTypeString('STRUCT(a INTEGER[], b VARCHAR[])'),
|
||||
).toStrictEqual(
|
||||
STRUCT({
|
||||
a: LIST(INTEGER),
|
||||
b: LIST(VARCHAR),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
test('STRUCT(a INTEGER, b VARCHAR)[]', () => {
|
||||
expect(
|
||||
parseLogicalTypeString('STRUCT(a INTEGER, b VARCHAR)[]'),
|
||||
).toStrictEqual(
|
||||
LIST(
|
||||
STRUCT({
|
||||
a: INTEGER,
|
||||
b: VARCHAR,
|
||||
}),
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
// addition: nested struct
|
||||
test('STRUCT(a STRUCT(b INTEGER), b VARCHAR)', () => {
|
||||
expect(
|
||||
parseLogicalTypeString('STRUCT(a STRUCT(b INTEGER), b VARCHAR)'),
|
||||
).toStrictEqual(
|
||||
STRUCT({
|
||||
a: STRUCT({ b: INTEGER }),
|
||||
b: VARCHAR,
|
||||
}),
|
||||
);
|
||||
});
|
||||
test('STRUCT("my weird ""key" INTEGER, b VARCHAR)', () => {
|
||||
expect(
|
||||
parseLogicalTypeString('STRUCT("my weird ""key" INTEGER, b VARCHAR)'),
|
||||
).toStrictEqual(
|
||||
STRUCT({
|
||||
'"my weird ""key"': INTEGER,
|
||||
b: VARCHAR,
|
||||
}),
|
||||
);
|
||||
});
|
||||
test('STRUCT("my weird ""key" STRUCT("my other ""weird key" INTEGER), b VARCHAR)', () => {
|
||||
expect(
|
||||
parseLogicalTypeString(
|
||||
'STRUCT("my weird ""key" STRUCT("my other ""weird key" INTEGER), b VARCHAR)',
|
||||
),
|
||||
).toStrictEqual(
|
||||
STRUCT({
|
||||
'"my weird ""key"': STRUCT({
|
||||
'"my other ""weird key"': INTEGER,
|
||||
}),
|
||||
b: VARCHAR,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
test('MAP(INTEGER, VARCHAR)', () => {
|
||||
expect(parseLogicalTypeString('MAP(INTEGER, VARCHAR)')).toStrictEqual(
|
||||
MAP(INTEGER, VARCHAR),
|
||||
);
|
||||
});
|
||||
|
||||
test('MAP(VARCHAR, STRUCT(b INTEGER))', () => {
|
||||
expect(
|
||||
parseLogicalTypeString('MAP(VARCHAR, STRUCT(b INTEGER))'),
|
||||
).toStrictEqual(MAP(VARCHAR, STRUCT({ b: INTEGER })));
|
||||
});
|
||||
|
||||
test('UNION("name" VARCHAR, age SMALLINT)', () => {
|
||||
expect(
|
||||
parseLogicalTypeString('UNION("name" VARCHAR, age SMALLINT)'),
|
||||
).toStrictEqual(
|
||||
UNION({
|
||||
'"name"': VARCHAR,
|
||||
age: SMALLINT,
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
test('INTEGER[3]', () => {
|
||||
expect(parseLogicalTypeString('INTEGER[3]')).toStrictEqual(
|
||||
ARRAY(INTEGER, 3),
|
||||
);
|
||||
});
|
||||
|
||||
test('STRUCT(a INTEGER, b VARCHAR)[3]', () => {
|
||||
expect(
|
||||
parseLogicalTypeString('STRUCT(a INTEGER, b VARCHAR)[3]'),
|
||||
).toStrictEqual(
|
||||
ARRAY(
|
||||
STRUCT({
|
||||
a: INTEGER,
|
||||
b: VARCHAR,
|
||||
}),
|
||||
3,
|
||||
),
|
||||
);
|
||||
});
|
||||
|
||||
test('STRUCT(a INTEGER[3], b VARCHAR[3])', () => {
|
||||
expect(
|
||||
parseLogicalTypeString('STRUCT(a INTEGER[3], b VARCHAR[3])'),
|
||||
).toStrictEqual(
|
||||
STRUCT({
|
||||
a: ARRAY(INTEGER, 3),
|
||||
b: ARRAY(VARCHAR, 3),
|
||||
}),
|
||||
);
|
||||
});
|
||||
|
||||
test('INTEGER[][3]', () => {
|
||||
expect(parseLogicalTypeString('INTEGER[][3]')).toStrictEqual(
|
||||
ARRAY(LIST(INTEGER), 3),
|
||||
);
|
||||
});
|
||||
|
||||
test('INTEGER[3][]', () => {
|
||||
expect(parseLogicalTypeString('INTEGER[3][]')).toStrictEqual(
|
||||
LIST(ARRAY(INTEGER, 3)),
|
||||
);
|
||||
});
|
||||
|
||||
test('UUID', () => {
|
||||
expect(parseLogicalTypeString('UUID')).toStrictEqual(UUID);
|
||||
});
|
||||
test('INTERVAL', () => {
|
||||
expect(parseLogicalTypeString('INTERVAL')).toStrictEqual(INTERVAL);
|
||||
});
|
||||
test('VARCHAR', () => {
|
||||
expect(parseLogicalTypeString('VARCHAR')).toStrictEqual(VARCHAR);
|
||||
});
|
||||
test('VARINT', () => {
|
||||
expect(parseLogicalTypeString('VARINT')).toStrictEqual(VARINT);
|
||||
});
|
||||
test('BLOB', () => {
|
||||
expect(parseLogicalTypeString('BLOB')).toStrictEqual(BLOB);
|
||||
});
|
||||
test('BIT', () => {
|
||||
expect(parseLogicalTypeString('BIT')).toStrictEqual(BIT);
|
||||
});
|
||||
});
|
||||
6
ts/pkgs/duckdb-data-types/test/tsconfig.json
Normal file
6
ts/pkgs/duckdb-data-types/test/tsconfig.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"extends": "../../../tsconfig.test.json",
|
||||
"references": [
|
||||
{ "path": "../src" }
|
||||
]
|
||||
}
|
||||
Reference in New Issue
Block a user