Skip to content

Commit

Permalink
Add support for inserting multiple rows to a table
Browse files Browse the repository at this point in the history
  • Loading branch information
luminamystere committed Mar 11, 2024
1 parent 1756670 commit 73ff3d5
Show file tree
Hide file tree
Showing 2 changed files with 21 additions and 11 deletions.
4 changes: 2 additions & 2 deletions src/Table.ts
Original file line number Diff line number Diff line change
Expand Up @@ -36,10 +36,10 @@ export default class Table<SCHEMA extends TableSchema> {
return initialiser?.(query) ?? query;
}

public insert (data: Partial<Schema.RowInput<SCHEMA>>): InsertIntoTable<SCHEMA>;
public insert (data: Partial<Schema.RowInput<SCHEMA>>, initialiser: Initialiser<InsertIntoTable<SCHEMA>>): InsertIntoTable<SCHEMA>;
public insert<COLUMNS extends Schema.Column<SCHEMA>[]> (...columns: COLUMNS): InsertIntoTableFactory<SCHEMA, COLUMNS>;
public insert<COLUMNS extends Schema.Column<SCHEMA>[], RETURN extends InsertIntoTableFactory<SCHEMA, COLUMNS> | InsertIntoTable<SCHEMA>> (...columnsAndInitialiser: [...COLUMNS, Initialiser<InsertIntoTableFactory<SCHEMA, COLUMNS>, RETURN>]): RETURN;
public insert (data: Partial<Schema.RowInput<SCHEMA>>): InsertIntoTable<SCHEMA>;
public insert (data: Partial<Schema.RowInput<SCHEMA>>, initialiser: Initialiser<InsertIntoTable<SCHEMA>>): InsertIntoTable<SCHEMA>;
public insert (...params: (boolean | Partial<Schema.RowInput<SCHEMA>> | Schema.Column<SCHEMA> | Initialiser<InsertIntoTableFactory<SCHEMA>> | Initialiser<InsertIntoTable<SCHEMA>>)[]): InsertIntoTableFactory<SCHEMA> | InsertIntoTable<SCHEMA> {
const isUpsert = params[0] === true;
if (typeof params[0] === "boolean")
Expand Down
28 changes: 19 additions & 9 deletions src/statements/Insert.ts
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ export default class InsertIntoTable<SCHEMA extends TableSchema, COLUMNS extends

return {
values: (...values: any[]) => {
const query = new InsertIntoTable<SCHEMA, COLUMNS>(tableName, schema, columns, values as never);
const query = new InsertIntoTable<SCHEMA, COLUMNS>(tableName, schema, columns, [values] as never);
if (isUpsert) {
query.onConflict(primaryKey!).doUpdate(update => {
for (let i = 0; i < columns.length; i++) {
Expand All @@ -37,10 +37,15 @@ export default class InsertIntoTable<SCHEMA extends TableSchema, COLUMNS extends
}

private vars: any[] = [];
public constructor (public readonly tableName: string, public readonly schema: SCHEMA, public readonly columns: Schema.Column<SCHEMA>[], public readonly values: Value<Schema.RowInput<SCHEMA>>[]) {
public constructor (public readonly tableName: string, public readonly schema: SCHEMA, public readonly columns: Schema.Column<SCHEMA>[], public readonly rows: Value<Schema.RowInput<SCHEMA>>[][]) {
super();
}

public values (...values: { [I in keyof COLUMNS]: InputTypeFromString<SCHEMA[COLUMNS[I]]> }): this {
this.rows.push(values);
return this;
}

private conflictTarget?: Schema.Column<SCHEMA>[];
private conflictAction?: null | UpdateTable<SCHEMA, any>;
public onConflict (...columns: Schema.Column<SCHEMA>[]): InsertIntoTableConflictActionFactory<SCHEMA, COLUMNS, RESULT> {
Expand All @@ -59,12 +64,17 @@ export default class InsertIntoTable<SCHEMA extends TableSchema, COLUMNS extends
}

public compile () {
const values = this.values.map((value: ValidType, i) => {
const column = this.columns[i];
if (Schema.isColumn(this.schema, column, "TIMESTAMP") && typeof value === "number")
value = new Date(value);
return Expression.stringifyValue(value, this.vars);
}).join(",");
const rows = this.rows
.map(row => row
.map((value: ValidType, i) => {
const column = this.columns[i];
if (Schema.isColumn(this.schema, column, "TIMESTAMP") && typeof value === "number")
value = new Date(value);
return Expression.stringifyValue(value, this.vars);
})
.join(","))
.map(columnValues => `(${columnValues})`)
.join(",");

const conflictTarget = this.conflictTarget?.length ? `(${this.conflictTarget.join(",")})` : "";
let conflictAction = this.conflictAction === undefined ? " "
Expand All @@ -76,7 +86,7 @@ export default class InsertIntoTable<SCHEMA extends TableSchema, COLUMNS extends
conflictAction = `ON CONFLICT ${conflictTarget} DO ${compiled.text}`;
}

return this.queryable(`INSERT INTO ${this.tableName} (${this.columns.join(",")}) VALUES (${values}) ${conflictAction!}`, undefined, this.vars);
return this.queryable(`INSERT INTO ${this.tableName} (${this.columns.join(",")}) VALUES ${rows} ${conflictAction!}`, undefined, this.vars);
}

protected override resolveQueryOutput (output: QueryResult<any>) {
Expand Down

0 comments on commit 73ff3d5

Please sign in to comment.