Skip to content

Commit

Permalink
change table definition
Browse files Browse the repository at this point in the history
  • Loading branch information
invisal committed Oct 16, 2024
1 parent 0673185 commit 8993ee3
Show file tree
Hide file tree
Showing 10 changed files with 169 additions and 111 deletions.
25 changes: 7 additions & 18 deletions src/client.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import { SqlConnection, QueryResult } from './connections';
import { Query } from './query';
import { QueryType } from './query-params';
import { AbstractDialect, ColumnDataType } from './query-builder';
import { TableColumnDefinition } from './models/database';

export enum QueryBuilderAction {
SELECT = 'select',
Expand Down Expand Up @@ -53,12 +54,9 @@ export interface QueryBuilderInternal {

// Used when column names and type are required, such as CREATE TABLE
columns: {
default?: string;
primaryKey?: boolean;
nullable?: boolean;
name?: string;
type?: ColumnDataType | string;
oldName?: string;
name: string;
definition?: TableColumnDefinition;
// When you want to rename a column
newName?: string;
}[];

Expand Down Expand Up @@ -304,17 +302,8 @@ class QueryBuilderCreateTable extends IQueryBuilder {
this.state.table = tableName;
}

column(
columnName: string,
type: string,
options?: { nullable?: boolean; default?: string; primaryKey?: boolean }
) {
this.state.columns.push({
name: columnName,
type,
nullable: true, // Most database when creating a table, the column is nullable by default
...options,
});
column(name: string, definition: TableColumnDefinition) {
this.state.columns.push({ name, definition });
return this;
}
}
Expand Down Expand Up @@ -350,7 +339,7 @@ class QueryBuilderAlterTable extends IQueryBuilder {
this.state.action = QueryBuilderAction.RENAME_COLUMNS;
this.state.columns = [
{
oldName: columnName,
name: columnName,
newName: newColumnName,
},
];
Expand Down
13 changes: 7 additions & 6 deletions src/connections/bigquery.ts
Original file line number Diff line number Diff line change
Expand Up @@ -122,13 +122,14 @@ export class BigQueryConnection extends SqlConnection {
(field: any, index: number): TableColumn => {
return {
name: field.name,
type: field.type,
position: index,
nullable: field.mode === 'NULLABLE',
default: null, // BigQuery does not support default values in the schema metadata
primary: false, // BigQuery does not have a concept of primary keys
unique: false, // BigQuery does not have a concept of unique constraints
references: [], // BigQuery does not support foreign keys
definition: {
type: field.type,
nullable: field.mode === 'NULLABLE',
default: null, // BigQuery does not support default values in the schema metadata
primaryKey: false, // BigQuery does not have a concept of primary keys
unique: false, // BigQuery does not have a concept of unique constraints
},
};
}
);
Expand Down
6 changes: 2 additions & 4 deletions src/connections/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -188,16 +188,14 @@ export abstract class SqlConnection extends Connection {
createTable(
schemaName: string | undefined,
tableName: string,
columns: Partial<TableColumn>[]
columns: TableColumn[]
): Promise<QueryResult> {
const qb = Outerbase(this).createTable(
schemaName ? `${schemaName}.${tableName}` : tableName
);

for (const column of columns) {
if (column.name && column.type) {
qb.column(column.name, column.type);
}
qb.column(column.name, column.definition);
}

return this.query(qb.toQuery());
Expand Down
13 changes: 7 additions & 6 deletions src/connections/mongodb.ts
Original file line number Diff line number Diff line change
Expand Up @@ -256,13 +256,14 @@ export class MongoDBConnection implements Connection {
)) {
const column: TableColumn = {
name: fieldName,
type: typeof value,
definition: {
type: typeof value,
nullable: true,
default: null,
primaryKey: fieldName === '_id',
unique: fieldName === '_id',
},
position: position++,
nullable: true,
default: null,
primary: fieldName === '_id',
unique: fieldName === '_id',
references: [],
};
columns.push(column);
}
Expand Down
19 changes: 10 additions & 9 deletions src/connections/mysql.ts
Original file line number Diff line number Diff line change
Expand Up @@ -98,13 +98,14 @@ export function buildMySQLDatabaseSchmea({

const columnObject = {
name: column.COLUMN_NAME,
type: column.COLUMN_TYPE,
position: column.ORDINAL_POSITION,
nullable: column.IS_NULLABLE === 'YES',
default: column.COLUMN_DEFAULT,
primary: column.COLUMN_KEY === 'PRI',
unique: column.EXTRA === 'UNI',
references: [],
definition: {
type: column.COLUMN_TYPE,
nullable: column.IS_NULLABLE === 'YES',
default: column.COLUMN_DEFAULT,
primary: column.COLUMN_KEY === 'PRI',
unique: column.EXTRA === 'UNI',
},
} as TableColumn;

columnLookup[
Expand Down Expand Up @@ -163,10 +164,10 @@ export function buildMySQLDatabaseSchmea({
constraintColumn.COLUMN_NAME
];
if (currentColumn && constraintColumn.REFERENCED_COLUMN_NAME) {
currentColumn.references.push({
currentColumn.definition.references = {
table: constraintColumn.REFERENCED_TABLE_NAME,
column: constraintColumn.REFERENCED_COLUMN_NAME,
});
column: [constraintColumn.REFERENCED_COLUMN_NAME],
};
}

constraint.columns.push({
Expand Down
28 changes: 14 additions & 14 deletions src/connections/sqlite/base.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { Database, Table } from 'src/models/database';
import { Database, Table, TableColumn } from 'src/models/database';
import { Connection, SqlConnection } from '..';
export abstract class SqliteBaseConnection extends SqlConnection {
public async fetchDatabaseSchema(): Promise<Database> {
Expand Down Expand Up @@ -47,22 +47,22 @@ FROM

tableLookup[column.tbl_name].columns.push({
name: column.name,
type: column.type,
position: column.cid,
nullable: column.notnull === 0,
default: column.dflt_value,
primary: column.pk === 1,
unique: false,
references:
column.ref_table_name && column.ref_column_name
? [
{
definition: {
type: column.type,
nullable: column.notnull === 0,
default: column.dflt_value,
primaryKey: column.pk === 1,
unique: false,
references:
column.ref_table_name && column.ref_column_name
? {
table: column.ref_table_name,
column: column.ref_column_name,
},
]
: [],
});
}
: undefined,
},
} as TableColumn);
}

// Sqlite default schema is "main", since we don't support
Expand Down
13 changes: 7 additions & 6 deletions src/connections/sqlite/cloudflare.ts
Original file line number Diff line number Diff line change
Expand Up @@ -255,13 +255,14 @@ export class CloudflareD1Connection extends SqliteBaseConnection {

const currentColumn: TableColumn = {
name: column.name,
type: column.type,
position: column.cid,
nullable: column.notnull === 0,
default: column.dflt_value,
primary: column.pk === 1,
unique: column.pk === 1,
references: [],
definition: {
type: column.type,
nullable: column.notnull === 0,
default: column.dflt_value,
primaryKey: column.pk === 1,
unique: column.pk === 1,
},
};

return currentColumn;
Expand Down
128 changes: 92 additions & 36 deletions src/models/database.ts
Original file line number Diff line number Diff line change
@@ -1,58 +1,114 @@
type SchemaName = string
export type Database = Record<SchemaName, Schema>
type SchemaName = string;
export type Database = Record<SchemaName, Schema>;

type TableName = string
export type Schema = Record<TableName, Table>
type TableName = string;
export type Schema = Record<TableName, Table>;

export type Table = {
name: string
columns: TableColumn[]
indexes: TableIndex[]
constraints: Constraint[]
}
name: string;
columns: TableColumn[];
indexes: TableIndex[];
constraints: Constraint[];
};

export type ConstraintColumn = {
columnName: string
}
columnName: string;
};

export type Constraint = {
name: string
schema: string
tableName: string
type: string
columns: ConstraintColumn[]
}
name: string;
schema: string;
tableName: string;
type: string;
columns: ConstraintColumn[];
};

export type TableColumn = {
name: string
type: string
position: number
nullable: boolean
default: string | null
primary: boolean
unique: boolean
references: TableReference[]
export interface TableColumn {
name: string;
position?: number;
definition: TableColumnDefinition;
}

export type TableReference = {
table: string
column: string
}
table: string;
column: string;
};

export type TableRecord = Record<string, any>
export type TableRecord = Record<string, any>;
export type TableCondition = {
column: string
value: any
column: string;
value: any;
// condition: 'eq' | 'neq' | 'gt' | 'lt' | 'gte' | 'lte' | 'like' | 'in' | 'nin'
}
};

export enum TableIndexType {
PRIMARY = 'primary',
UNIQUE = 'unique',
INDEX = 'index',
}
export type TableIndex = {
name: string
type: TableIndexType
columns: string[]
name: string;
type: TableIndexType;
columns: string[];
};

// This definition is trying to fit all database providers
// - MySQL: https://dev.mysql.com/doc/refman/8.4/en/create-table.html
// - Sqlite: https://www.sqlite.org/lang_createtable.html
// - PostgreSQL: https://www.postgresql.org/docs/current/sql-createtable.html
// - Motherduck: https://duckdb.org/docs/sql/statements/create_table.html
// - SQL Server: https://learn.microsoft.com/en-us/sql/t-sql/statements/create-table-transact-sql?view=sql-server-ver16
export interface TableColumnDefinition extends TableColumnConstraint {
type: string;

// An invisible column is normally hidden to queries,
// but can be accessed if explicitly referenced
// Supported: MySQL
invisible?: boolean;

// In MySQL: DISK, MEMORY
// In PostgreSQL: PLAIN, EXTERNAL, EXTENDED, MAIN, DEFAULT
storage?: boolean;

// PostgreSQL: pglz, lz4, default
compression?: string;

// Other
collate?: string;
comment?: string;
}

export interface TableColumnConstraint {
nullable?: boolean;
nullConflict?: string;

// Default value
default?: string | null;
defaultExpression?: string;
autoIncrement?: boolean;

// Column Constraints
constraintName?: string;

unique?: boolean;
uniqueConflict?: string;

primaryKey?: boolean;
primaryKeyConflict?: string;
primaryKeyOrder?: string;

references?: TableReferenceDefinition;
checkExpression?: string;

// Generative columns
generatedExpression?: string;
generatedType?: 'VIRTUAL' | 'STORED';
}

export interface TableReferenceDefinition {
table: string;
column: string[];
match?: string;
onDelete?: string;
onUpdate?: string;
}
Loading

0 comments on commit 8993ee3

Please sign in to comment.