Skip to content

Commit

Permalink
Add type performance improvements
Browse files Browse the repository at this point in the history
  • Loading branch information
dankochetov committed Aug 6, 2023
1 parent 0ea6f8c commit 4768d12
Show file tree
Hide file tree
Showing 129 changed files with 2,529 additions and 2,799 deletions.
4 changes: 2 additions & 2 deletions drizzle-orm/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -146,8 +146,8 @@
"mysql2": "^3.3.3",
"pg": "^8.11.0",
"postgres": "^3.3.5",
"rollup": "^3.23.0",
"rollup-plugin-dts": "^5.3.0",
"rollup": "^3.27.2",
"rollup-plugin-dts": "^5.3.1",
"sql.js": "^1.8.0",
"sqlite3": "^5.1.2",
"tslib": "^2.5.2",
Expand Down
230 changes: 125 additions & 105 deletions drizzle-orm/src/column-builder.ts
Original file line number Diff line number Diff line change
@@ -1,56 +1,67 @@
import { entityKind } from '~/entity';
import type { AnyColumn, ColumnHKTBase, ColumnKind } from './column';
import type { Column } from './column';
import type { MySqlColumn } from './mysql-core';
import type { PgColumn } from './pg-core';
import type { SQL } from './sql';
import { type Assume, type SimplifyShallow, type Update } from './utils';

export interface ColumnBuilderBaseConfig {
import type { SQLiteColumn } from './sqlite-core';

export type ColumnDataType =
| 'string'
| 'number'
| 'boolean'
| 'array'
| 'json'
| 'date'
| 'bigint'
| 'custom'
| 'buffer';

export type Dialect = 'pg' | 'mysql' | 'sqlite' | 'common';

export interface ColumnBuilderBaseConfig<TDataType extends ColumnDataType, TColumnType extends string> {
name: string;
dataType: TDataType;
columnType: TColumnType;
data: unknown;
driverParam: unknown;
notNull: boolean;
hasDefault: boolean;
enumValues: string[] | undefined;
}

export type ColumnBuilderConfig<
TInitial extends Partial<ColumnBuilderBaseConfig> = {},
TDefaults extends Partial<ColumnBuilderBaseConfig> = {},
> = SimplifyShallow<
Required<
Update<
ColumnBuilderBaseConfig & {
notNull: false;
hasDefault: false;
},
& { [K in keyof TInitial]: TInitial[K] }
& {
[K in Exclude<keyof TDefaults, keyof TInitial> & string]: TDefaults[K];
}
>
>
>;

export type MakeColumnConfig<T extends ColumnBuilderBaseConfig, TTableName extends string> = SimplifyShallow<
Pick<T, keyof ColumnBuilderBaseConfig> & { tableName: TTableName }
>;

export interface ColumnBuilderHKTBase {
config: unknown;
_type: unknown;
_columnHKT: unknown;
}

export type ColumnBuilderKind<
THKT extends ColumnBuilderHKTBase,
TConfig extends ColumnBuilderBaseConfig,
> = (THKT & {
config: TConfig;
})['_type'];

export interface ColumnBuilderHKT extends ColumnBuilderHKTBase {
_type: ColumnBuilder<ColumnBuilderHKT, Assume<this['config'], ColumnBuilderBaseConfig>>;
}
export type MakeColumnConfig<
T extends ColumnBuilderBaseConfig<ColumnDataType, string>,
TTableName extends string,
> = {
name: T['name'];
tableName: TTableName;
dataType: T['dataType'];
columnType: T['columnType'];
data: T extends { $type: infer U } ? U : T['data'];
driverParam: T['driverParam'];
notNull: T extends { notNull: true } ? true : false;
hasDefault: T extends { hasDefault: true } ? true : false;
enumValues: T['enumValues'];
baseColumn: T extends { baseBuilder: infer U extends ColumnBuilder } ? BuildColumn<TTableName, U, 'common'>
: never;
} & {};

export type ColumnBuilderTypeConfig<
T extends ColumnBuilderBaseConfig<ColumnDataType, string>,
TTypeConfig extends object = object,
> =
& {
brand: 'ColumnBuilder';
name: T['name'];
dataType: T['dataType'];
columnType: T['columnType'];
data: T['data'];
driverParam: T['driverParam'];
notNull: T extends { notNull: infer U } ? U : boolean;
hasDefault: T extends { hasDefault: infer U } ? U : boolean;
enumValues: T['enumValues'];
}
& TTypeConfig;

export interface ColumnBuilderRuntimeConfig<TData> {
export type ColumnBuilderRuntimeConfig<TData, TRuntimeConfig extends object = object> = {
name: string;
notNull: boolean;
default: TData | SQL | undefined;
Expand All @@ -59,95 +70,104 @@ export interface ColumnBuilderRuntimeConfig<TData> {
isUnique: boolean;
uniqueName: string | undefined;
uniqueType: string | undefined;
dataType: string;
columnType: string;
} & TRuntimeConfig;

export interface ColumnBuilderExtraConfig {
primaryKeyHasDefault?: boolean;
}

export type NotNull<T extends ColumnBuilder> = T & {
_: {
notNull: true;
};
};

export type HasDefault<T extends ColumnBuilder> = T & {
_: {
hasDefault: true;
};
};

export type $Type<T extends ColumnBuilder, TType> = T & {
_: {
$type: TType;
};
};

// To understand how to use `ColumnBuilder` and `AnyColumnBuilder`, see `Column` and `AnyColumn` documentation.
export abstract class ColumnBuilder<
THKT extends ColumnBuilderHKTBase,
T extends ColumnBuilderBaseConfig,
TRuntimeConfig extends object = {},
TTypeConfig extends object = {},
T extends ColumnBuilderBaseConfig<ColumnDataType, string> = ColumnBuilderBaseConfig<ColumnDataType, string>,
TRuntimeConfig extends object = object,
TTypeConfig extends object = object,
TExtraConfig extends ColumnBuilderExtraConfig = ColumnBuilderExtraConfig,
> {
static readonly [entityKind]: string = 'ColumnBuilder';

declare _: {
brand: 'ColumnBuilder';
config: T;
hkt: THKT;
columnHKT: THKT['_columnHKT'];
name: T['name'];
data: T['data'];
driverParam: T['driverParam'];
notNull: T['notNull'];
hasDefault: T['hasDefault'];
} & TTypeConfig;
declare _: ColumnBuilderTypeConfig<T, TTypeConfig>;

protected config: ColumnBuilderRuntimeConfig<T['data']> & TRuntimeConfig;
protected config: ColumnBuilderRuntimeConfig<T['data'], TRuntimeConfig>;

constructor(name: T['name']) {
constructor(name: T['name'], dataType: T['dataType'], columnType: T['columnType']) {
this.config = {
name,
notNull: false,
default: undefined,
hasDefault: false,
primaryKey: false,
} as ColumnBuilder<THKT, T, TRuntimeConfig>['config'];
isUnique: false,
uniqueName: undefined,
uniqueType: undefined,
dataType,
columnType,
} as ColumnBuilderRuntimeConfig<T['data'], TRuntimeConfig>;
}

$type<TType extends T['data']>(): ColumnBuilderKind<THKT, Update<T, { data: TType }>> {
return this as ColumnBuilderKind<THKT, Update<T, { data: TType }>>;
$type<TType>(): $Type<this, TType> {
return this as $Type<this, TType>;
}

notNull(): ColumnBuilderKind<THKT, UpdateCBConfig<T, { notNull: true }>> {
notNull(): NotNull<this> {
this.config.notNull = true;
return this as ReturnType<this['notNull']>;
return this as NotNull<this>;
}

default(
value: T['data'] | SQL,
): ColumnBuilderKind<THKT, UpdateCBConfig<T, { hasDefault: true }>> {
default(value: (this['_'] extends { $type: infer U } ? U : T['data']) | SQL): HasDefault<this> {
this.config.default = value;
this.config.hasDefault = true;
return this as ReturnType<this['default']>;
return this as HasDefault<this>;
}

primaryKey(): ColumnBuilderKind<THKT, UpdateCBConfig<T, { notNull: true }>> {
primaryKey(): TExtraConfig['primaryKeyHasDefault'] extends true ? HasDefault<NotNull<this>> : NotNull<this> {
this.config.primaryKey = true;
this.config.notNull = true;
return this as ReturnType<this['primaryKey']>;
return this as TExtraConfig['primaryKeyHasDefault'] extends true ? HasDefault<NotNull<this>> : NotNull<this>;
}
}

export type AnyColumnBuilder = ColumnBuilder<ColumnBuilderHKT, ColumnBuilderBaseConfig>;

export type UpdateCBConfig<
T extends ColumnBuilderBaseConfig,
TUpdate extends Partial<ColumnBuilderBaseConfig>,
> = Update<T, TUpdate>;

export type BuildColumn<
TTableName extends string,
TBuilder extends AnyColumnBuilder,
> = Assume<
ColumnKind<
Assume<TBuilder['_']['columnHKT'], ColumnHKTBase>,
SimplifyShallow<{ tableName: TTableName } & TBuilder['_']['config']>
>,
AnyColumn
>;

export type BuildColumns<TTableName extends string, TConfigMap extends Record<string, AnyColumnBuilder>> =
SimplifyShallow<
{
[Key in keyof TConfigMap]: BuildColumn<TTableName, TConfigMap[Key]>;
}
>;

// export type ChangeColumnTableName<TColumn extends AnyColumn, TAlias extends string> = ColumnKind<
// TColumn['_']['hkt'],
// SimplifyShallow<Update<TColumn['_']['config'], { tableName: TAlias }>>
// >;

export type ChangeColumnTableName<TColumn extends AnyColumn, TAlias extends string> = ColumnKind<
TColumn['_']['hkt'],
SimplifyShallow<Update<TColumn['_']['config'], { tableName: TAlias }>>
>;
TBuilder extends ColumnBuilder,
TDialect extends Dialect,
> = TDialect extends 'pg' ? PgColumn<MakeColumnConfig<TBuilder['_'], TTableName>>
: TDialect extends 'mysql' ? MySqlColumn<MakeColumnConfig<TBuilder['_'], TTableName>>
: TDialect extends 'sqlite' ? SQLiteColumn<MakeColumnConfig<TBuilder['_'], TTableName>>
: TDialect extends 'common' ? Column<MakeColumnConfig<TBuilder['_'], TTableName>>
: never;

export type BuildColumns<
TTableName extends string,
TConfigMap extends Record<string, ColumnBuilder>,
TDialect extends Dialect,
> =
& {
[Key in keyof TConfigMap]: BuildColumn<TTableName, TConfigMap[Key], TDialect>;
}
& {};

export type ChangeColumnTableName<TColumn extends Column, TAlias extends string, TDialect extends Dialect> =
TDialect extends 'pg' ? PgColumn<MakeColumnConfig<TColumn['_'], TAlias>>
: TDialect extends 'mysql' ? MySqlColumn<MakeColumnConfig<TColumn['_'], TAlias>>
: TDialect extends 'sqlite' ? SQLiteColumn<MakeColumnConfig<TColumn['_'], TAlias>>
: never;
Loading

0 comments on commit 4768d12

Please sign in to comment.