Skip to content

Commit

Permalink
Try another approach for table type related typecheck
Browse files Browse the repository at this point in the history
  • Loading branch information
tiagoacastro committed Jul 25, 2024
1 parent 10aec33 commit fba59c0
Show file tree
Hide file tree
Showing 3 changed files with 120 additions and 40 deletions.
34 changes: 22 additions & 12 deletions drizzle-orm/src/singlestore-core/indexes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ import type { SQL } from '~/sql/sql.ts';
import type { AnySingleStoreColumn, SingleStoreColumn } from './columns/index.ts';
import type { SingleStoreTable } from './table.ts';

interface IndexConfig {
interface IndexCommonConfig {
name: string;

columns: IndexColumn[];
Expand All @@ -13,11 +13,6 @@ interface IndexConfig {
*/
unique?: boolean;

/**
* If set, the index will be created as `create index ... using { 'btree' | 'hash' }`.
*/
using?: 'btree' | 'hash';

/**
* If set, the index will be created as `create index ... algorythm { 'default' | 'inplace' | 'copy' }`.
*/
Expand All @@ -29,6 +24,21 @@ interface IndexConfig {
lock?: 'default' | 'none' | 'shared' | 'exclusive';
}

export type IndexColumnstoreConfig = IndexCommonConfig & {
/**
* If set, the index will be created as `create index ... using { 'hash' }`.
*/
using?: 'hash';
};
export type IndexRowstoreConfig = IndexCommonConfig & {
/**
* If set, the index will be created as `create index ... using { 'btree' | 'hash' }`.
*/
using?: 'btree' | 'hash';
};

type IndexConfig = IndexColumnstoreConfig | IndexRowstoreConfig;

export type IndexColumn = SingleStoreColumn | SQL;

export class IndexBuilderOn {
Expand All @@ -48,31 +58,31 @@ export interface AnyIndexBuilder {
// eslint-disable-next-line @typescript-eslint/no-empty-interface
export interface IndexBuilder extends AnyIndexBuilder {}

export class IndexBuilder implements AnyIndexBuilder {
export class IndexBuilder<TConfig extends IndexConfig = IndexConfig> implements AnyIndexBuilder {
static readonly [entityKind]: string = 'SingleStoreIndexBuilder';

/** @internal */
config: IndexConfig;
config: TConfig;

constructor(name: string, columns: IndexColumn[], unique: boolean) {
this.config = {
name,
columns,
unique,
};
} as TConfig;
}

using(using: IndexConfig['using']): this {
using(using: TConfig['using']): this {
this.config.using = using;
return this;
}

algorythm(algorythm: IndexConfig['algorythm']): this {
algorythm(algorythm: TConfig['algorythm']): this {
this.config.algorythm = algorythm;
return this;
}

lock(lock: IndexConfig['lock']): this {
lock(lock: TConfig['lock']): this {
this.config.lock = lock;
return this;
}
Expand Down
4 changes: 2 additions & 2 deletions drizzle-orm/src/singlestore-core/schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@ export class SingleStoreSchema<TName extends string = string> {
public readonly schemaName: TName,
) {}

table: SingleStoreTableFn<TName> = (name, columns, extraConfig) => {
return singlestoreTableWithSchema(name, columns, extraConfig, this.schemaName);
table: SingleStoreTableFn<'columnstore', TName> = (name, columns, extraConfig) => {
return singlestoreTableWithSchema('columnstore', name, columns, extraConfig, this.schemaName);
};

view = ((name, columns) => {
Expand Down
122 changes: 96 additions & 26 deletions drizzle-orm/src/singlestore-core/table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,20 +2,40 @@ import type { BuildColumns, BuildExtraConfigColumns } from '~/column-builder.ts'
import { entityKind } from '~/entity.ts';
import { Table, type TableConfig as TableConfigBase, type UpdateTableConfig } from '~/table.ts';
import type { SingleStoreColumn, SingleStoreColumnBuilder, SingleStoreColumnBuilderBase } from './columns/common.ts';
import type { AnyIndexBuilder } from './indexes.ts';
import type { IndexBuilder, IndexColumnstoreConfig, IndexRowstoreConfig } from './indexes.ts';
import type { PrimaryKeyBuilder } from './primary-keys.ts';
import type { UniqueConstraintBuilder } from './unique-constraint.ts';

export type SingleStoreTableExtraConfig = Record<
type SinglestoreTableTypeTypes = {
columnstore: {
extraconfig: SingleStoreColumnstoreTableExtraConfig;
};
rowstore: {
extraconfig: SingleStoreRowstoreTableExtraConfig;
};
};
type SinglestoreTableTypes = 'columnstore' | 'rowstore';

export type SingleStoreColumnstoreTableExtraConfig = Record<
string,
| AnyIndexBuilder
| IndexBuilder<IndexColumnstoreConfig>
| PrimaryKeyBuilder
| UniqueConstraintBuilder
>;

export type SingleStoreRowstoreTableExtraConfig = Record<
string,
| IndexBuilder<IndexRowstoreConfig>
| PrimaryKeyBuilder
| UniqueConstraintBuilder
>;

export type TableConfig = TableConfigBase<SingleStoreColumn>;

export class SingleStoreTable<T extends TableConfig = TableConfig> extends Table<T> {
export abstract class SingleStoreTable<
TTableType extends SinglestoreTableTypes = SinglestoreTableTypes,
T extends TableConfig = TableConfig,
> extends Table<T> {
static readonly [entityKind]: string = 'SingleStoreTable';

declare protected $columns: T['columns'];
Expand All @@ -28,44 +48,76 @@ export class SingleStoreTable<T extends TableConfig = TableConfig> extends Table

/** @internal */
override [Table.Symbol.ExtraConfigBuilder]:
| ((self: Record<string, SingleStoreColumn>) => SingleStoreTableExtraConfig)
| ((self: Record<string, SingleStoreColumn>) => SinglestoreTableTypeTypes[TTableType]['extraconfig'])
| undefined = undefined;
}

export type AnySingleStoreTable<TPartial extends Partial<TableConfig> = {}> = SingleStoreTable<
UpdateTableConfig<TableConfig, TPartial>
>;
export class SingleStoreColumnstoreTable<T extends TableConfig = TableConfig>
extends SingleStoreTable<'columnstore', T>
{
static readonly [entityKind]: string = 'SingleStoreColumnstoreTable';
}

export type SingleStoreTableWithColumns<T extends TableConfig> =
& SingleStoreTable<T>
export class SingleStoreRowstoreTable<T extends TableConfig = TableConfig> extends SingleStoreTable<'rowstore', T> {
static readonly [entityKind]: string = 'SingleStoreRowstoreTable';
}

export type AnySingleStoreTable<TPartial extends Partial<TableConfig> = {}> =
| SingleStoreColumnstoreTable<UpdateTableConfig<TableConfig, TPartial>>
| SingleStoreRowstoreTable<UpdateTableConfig<TableConfig, TPartial>>;

export type SingleStoreTableWithColumns<TTableType extends SinglestoreTableTypes, T extends TableConfig> =
& (SingleStoreTable<TTableType, T>)
& {
[Key in keyof T['columns']]: T['columns'][Key];
};

export function singlestoreTableWithSchema<
TTableType extends SinglestoreTableTypes,
TTableName extends string,
TSchemaName extends string | undefined,
TColumnsMap extends Record<string, SingleStoreColumnBuilderBase>,
>(
tableType: TTableType,
name: TTableName,
columns: TColumnsMap,
extraConfig:
| ((self: BuildColumns<TTableName, TColumnsMap, 'singlestore'>) => SingleStoreTableExtraConfig)
| ((
self: BuildColumns<TTableName, TColumnsMap, 'singlestore'>,
) => SinglestoreTableTypeTypes[TTableType]['extraconfig'])
| undefined,
schema: TSchemaName,
baseName = name,
): SingleStoreTableWithColumns<{
): SingleStoreTableWithColumns<TTableType, {
name: TTableName;
schema: TSchemaName;
columns: BuildColumns<TTableName, TColumnsMap, 'singlestore'>;
dialect: 'singlestore';
}> {
const rawTable = new SingleStoreTable<{
name: TTableName;
schema: TSchemaName;
columns: BuildColumns<TTableName, TColumnsMap, 'singlestore'>;
dialect: 'singlestore';
}>(name, schema, baseName);
let rawTable;
switch (tableType) {
case 'columnstore': {
rawTable = new SingleStoreColumnstoreTable<{
name: TTableName;
schema: TSchemaName;
columns: BuildColumns<TTableName, TColumnsMap, 'singlestore'>;
dialect: 'singlestore';
}>(name, schema, baseName);
break;
}
case 'rowstore': {
rawTable = new SingleStoreRowstoreTable<{
name: TTableName;
schema: TSchemaName;
columns: BuildColumns<TTableName, TColumnsMap, 'singlestore'>;
dialect: 'singlestore';
}>(name, schema, baseName);
break;
}
default: {
throw new Error('Invalid table type');
}
}

const builtColumns = Object.fromEntries(
Object.entries(columns).map(([name, colBuilderBase]) => {
Expand All @@ -87,34 +139,52 @@ export function singlestoreTableWithSchema<
if (extraConfig) {
table[SingleStoreTable.Symbol.ExtraConfigBuilder] = extraConfig as unknown as (
self: Record<string, SingleStoreColumn>,
) => SingleStoreTableExtraConfig;
) => SinglestoreTableTypeTypes[TTableType]['extraconfig'];
}

return table;
}

export interface SingleStoreTableFn<TSchemaName extends string | undefined = undefined> {
export interface SingleStoreTableFn<
TTableType extends SinglestoreTableTypes,
TSchemaName extends string | undefined = undefined,
> {
<
TTableName extends string,
TColumnsMap extends Record<string, SingleStoreColumnBuilderBase>,
>(
name: TTableName,
columns: TColumnsMap,
extraConfig?: (self: BuildColumns<TTableName, TColumnsMap, 'singlestore'>) => SingleStoreTableExtraConfig,
): SingleStoreTableWithColumns<{
extraConfig?: (
self: BuildColumns<TTableName, TColumnsMap, 'singlestore'>,
) => SinglestoreTableTypeTypes[TTableType]['extraconfig'],
): SingleStoreTableWithColumns<TTableType, {
name: TTableName;
schema: TSchemaName;
columns: BuildColumns<TTableName, TColumnsMap, 'singlestore'>;
dialect: 'singlestore';
}>;
}

export const singlestoreTable: SingleStoreTableFn = (name, columns, extraConfig) => {
return singlestoreTableWithSchema(name, columns, extraConfig, undefined, name);
export const singlestoreTable: SingleStoreTableFn<'columnstore'> = (name, columns, extraConfig) => {
return singlestoreTableWithSchema('columnstore', name, columns, extraConfig, undefined, name);
};

export const singlestoreRowstoreTable: SingleStoreTableFn<'rowstore'> = (name, columns, extraConfig) => {
return singlestoreTableWithSchema('rowstore', name, columns, extraConfig, undefined, name);
};

export function singlestoreTableCreator(customizeTableName: (name: string) => string): SingleStoreTableFn {
export function singlestoreTableCreator(
customizeTableName: (name: string) => string,
): SingleStoreTableFn<'columnstore'> {
return (name, columns, extraConfig) => {
return singlestoreTableWithSchema(customizeTableName(name) as typeof name, columns, extraConfig, undefined, name);
return singlestoreTableWithSchema(
'columnstore',
customizeTableName(name) as typeof name,
columns,
extraConfig,
undefined,
name,
);
};
}

0 comments on commit fba59c0

Please sign in to comment.