-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathinsert.ts
More file actions
94 lines (79 loc) · 2.61 KB
/
insert.ts
File metadata and controls
94 lines (79 loc) · 2.61 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
import { toSnakeCase } from "../utils";
import { BaseQueryBuilder } from "./base";
export class InsertQueryBuilder<T> extends BaseQueryBuilder<T> {
private data: Partial<T> | Partial<T>[] = {};
private returningColumns: Array<keyof T> = ["*"] as any;
values(data: Partial<T> | Partial<T>[]): this {
this.data = data;
return this;
}
returning(columns?: Array<keyof T>): this {
if (columns && columns.length > 0) {
this.returningColumns = columns;
}
return this;
}
build(): { sql: string; values: any[] } {
if (Array.isArray(this.data)) {
// Handle bulk insert
return this.buildBulkInsert();
} else {
// Handle single insert
return this.buildSingleInsert();
}
}
private buildSingleInsert(): { sql: string; values: any[] } {
const data = this.data as Partial<T>;
const columns = Object.keys(data)
.map(toSnakeCase)
.map((c) => `"${c}"`)
.join(", ");
const placeholders = Object.keys(data)
.map((_, index) => `$${index + 1}`)
.join(", ");
const values = Object.values(data);
const returning = this.returningColumns
.map((col) => (typeof col === "string" ? col : "*"))
.join(", ");
const sql = `
INSERT INTO ${this.tableName} (${columns})
VALUES (${placeholders})
RETURNING ${returning};
`;
return { sql, values };
}
private buildBulkInsert(): { sql: string; values: any[] } {
const dataArray = this.data as Partial<T>[];
if (dataArray.length === 0) {
throw new Error("No data provided for bulk insert");
}
// Get all unique keys from all objects
const allKeys = new Set<string>();
dataArray.forEach((data) => {
Object.keys(data).forEach((key) => allKeys.add(key));
});
const columns = Array.from(allKeys).map(toSnakeCase);
const values: any[] = [];
// Build value placeholders for each row
const valuePlaceholders = dataArray
.map((data, rowIndex) => {
const rowPlaceholders = columns.map((column, colIndex) => {
const originalKey = Array.from(allKeys)[colIndex];
const value = (data as any)[originalKey];
values.push(value !== undefined ? value : null);
return `$${values.length}`;
});
return `(${rowPlaceholders.join(", ")})`;
})
.join(", ");
const returning = this.returningColumns
.map((col) => (typeof col === "string" ? col : "*"))
.join(", ");
const sql = `
INSERT INTO ${this.tableName} (${columns.join(", ")})
VALUES ${valuePlaceholders}
RETURNING ${returning};
`;
return { sql, values };
}
}