@bunnykit/orm 0.1.14 → 0.1.16
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/src/connection/Connection.d.ts +2 -2
- package/dist/src/connection/Connection.js +5 -6
- package/dist/src/connection/ConnectionManager.d.ts +13 -0
- package/dist/src/connection/ConnectionManager.js +81 -0
- package/dist/src/query/Builder.d.ts +4 -1
- package/dist/src/query/Builder.js +102 -32
- package/dist/src/query/grammars/Grammar.d.ts +1 -0
- package/dist/src/query/grammars/MySqlGrammar.d.ts +1 -0
- package/dist/src/query/grammars/MySqlGrammar.js +3 -0
- package/dist/src/query/grammars/PostgresGrammar.d.ts +1 -0
- package/dist/src/query/grammars/PostgresGrammar.js +3 -0
- package/dist/src/query/grammars/SQLiteGrammar.d.ts +1 -0
- package/dist/src/query/grammars/SQLiteGrammar.js +3 -0
- package/dist/src/types/index.d.ts +4 -1
- package/package.json +1 -1
|
@@ -20,8 +20,8 @@ export declare class Connection {
|
|
|
20
20
|
withoutSchema(): Connection;
|
|
21
21
|
qualifyTable(table: string): string;
|
|
22
22
|
private quoteIdentifier;
|
|
23
|
-
query(sqlString: string): Promise<any[]>;
|
|
24
|
-
run(sqlString: string): Promise<any>;
|
|
23
|
+
query(sqlString: string, bindings?: any[]): Promise<any[]>;
|
|
24
|
+
run(sqlString: string, bindings?: any[]): Promise<any>;
|
|
25
25
|
beginTransaction(): Promise<void>;
|
|
26
26
|
commit(): Promise<void>;
|
|
27
27
|
rollback(): Promise<void>;
|
|
@@ -75,12 +75,11 @@ export class Connection {
|
|
|
75
75
|
quoteIdentifier(value) {
|
|
76
76
|
return `"${value.replace(/"/g, '""')}"`;
|
|
77
77
|
}
|
|
78
|
-
async query(sqlString) {
|
|
79
|
-
|
|
80
|
-
return (await this.driver.unsafe(sqlString));
|
|
78
|
+
async query(sqlString, bindings) {
|
|
79
|
+
return (await this.driver.unsafe(sqlString, bindings));
|
|
81
80
|
}
|
|
82
|
-
async run(sqlString) {
|
|
83
|
-
return await this.driver.unsafe(sqlString);
|
|
81
|
+
async run(sqlString, bindings) {
|
|
82
|
+
return await this.driver.unsafe(sqlString, bindings);
|
|
84
83
|
}
|
|
85
84
|
async beginTransaction() {
|
|
86
85
|
await this.driver.unsafe("BEGIN");
|
|
@@ -106,7 +105,7 @@ export class Connection {
|
|
|
106
105
|
return await this.transaction(callback);
|
|
107
106
|
}
|
|
108
107
|
return await this.transaction(async (connection) => {
|
|
109
|
-
await connection.run(`SET LOCAL ${setting} = ${connection.getGrammar().
|
|
108
|
+
await connection.run(`SET LOCAL ${setting} = ${connection.getGrammar().placeholder(1)}`, [tenantId]);
|
|
110
109
|
return await callback(connection);
|
|
111
110
|
});
|
|
112
111
|
}
|
|
@@ -21,15 +21,28 @@ export type TenantResolution = {
|
|
|
21
21
|
setting?: string;
|
|
22
22
|
};
|
|
23
23
|
export type TenantResolver = (tenantId: string) => TenantResolution | Promise<TenantResolution>;
|
|
24
|
+
export interface PoolConfig {
|
|
25
|
+
maxConnections?: number;
|
|
26
|
+
minConnections?: number;
|
|
27
|
+
idleTimeout?: number;
|
|
28
|
+
}
|
|
24
29
|
export declare class ConnectionManager {
|
|
25
30
|
private static defaultConnection?;
|
|
26
31
|
private static connections;
|
|
32
|
+
private static pools;
|
|
33
|
+
private static poolConfigs;
|
|
27
34
|
private static tenantResolver?;
|
|
28
35
|
private static tenantCache;
|
|
29
36
|
static setDefault(connection: Connection): void;
|
|
30
37
|
static getDefault(): Connection | undefined;
|
|
38
|
+
static setPoolConfig(name: string, config: PoolConfig): void;
|
|
39
|
+
static getPoolConfig(name: string): PoolConfig | undefined;
|
|
40
|
+
private static getPooledConnection;
|
|
41
|
+
private static releasePooledConnection;
|
|
31
42
|
static add(name: string, connection: Connection | ConnectionConfig): Connection;
|
|
32
43
|
static get(name: string): Connection | undefined;
|
|
44
|
+
static getPooled(name: string, config?: ConnectionConfig): Promise<Connection>;
|
|
45
|
+
static release(name: string, connection: Connection): void;
|
|
33
46
|
static require(name: string): Connection;
|
|
34
47
|
static setTenantResolver(resolver: TenantResolver): void;
|
|
35
48
|
static resolveTenant(tenantId: string): Promise<ActiveTenantContext>;
|
|
@@ -2,6 +2,8 @@ import { Connection } from "./Connection.js";
|
|
|
2
2
|
export class ConnectionManager {
|
|
3
3
|
static defaultConnection;
|
|
4
4
|
static connections = new Map();
|
|
5
|
+
static pools = new Map();
|
|
6
|
+
static poolConfigs = new Map();
|
|
5
7
|
static tenantResolver;
|
|
6
8
|
static tenantCache = new Map();
|
|
7
9
|
static setDefault(connection) {
|
|
@@ -10,6 +12,67 @@ export class ConnectionManager {
|
|
|
10
12
|
static getDefault() {
|
|
11
13
|
return this.defaultConnection;
|
|
12
14
|
}
|
|
15
|
+
static setPoolConfig(name, config) {
|
|
16
|
+
this.poolConfigs.set(name, { maxConnections: 10, minConnections: 1, idleTimeout: 30000, ...config });
|
|
17
|
+
}
|
|
18
|
+
static getPoolConfig(name) {
|
|
19
|
+
return this.poolConfigs.get(name);
|
|
20
|
+
}
|
|
21
|
+
static async getPooledConnection(name, config) {
|
|
22
|
+
const poolConfig = this.poolConfigs.get(name) || { maxConnections: 10, minConnections: 1, idleTimeout: 30000 };
|
|
23
|
+
let pool = this.pools.get(name);
|
|
24
|
+
if (!pool) {
|
|
25
|
+
pool = [];
|
|
26
|
+
this.pools.set(name, pool);
|
|
27
|
+
}
|
|
28
|
+
const now = Date.now();
|
|
29
|
+
const idleTimeout = poolConfig.idleTimeout || 30000;
|
|
30
|
+
while (pool.length > 0) {
|
|
31
|
+
const idx = pool.findIndex((c) => !c.inUse && (now - c.lastUsed) < idleTimeout);
|
|
32
|
+
if (idx === -1)
|
|
33
|
+
break;
|
|
34
|
+
const pooled = pool[idx];
|
|
35
|
+
pool.splice(idx, 1);
|
|
36
|
+
try {
|
|
37
|
+
pooled.connection.query("SELECT 1").catch(() => null);
|
|
38
|
+
pooled.inUse = true;
|
|
39
|
+
return pooled.connection;
|
|
40
|
+
}
|
|
41
|
+
catch {
|
|
42
|
+
await pooled.connection.close().catch(() => null);
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
if (pool.length < (poolConfig.maxConnections || 10)) {
|
|
46
|
+
const connection = new Connection(config);
|
|
47
|
+
pool.push({ connection, lastUsed: Date.now(), inUse: true });
|
|
48
|
+
return connection;
|
|
49
|
+
}
|
|
50
|
+
return new Promise((resolve, reject) => {
|
|
51
|
+
const checkInterval = setInterval(() => {
|
|
52
|
+
const available = pool.find((c) => !c.inUse);
|
|
53
|
+
if (available) {
|
|
54
|
+
clearInterval(checkInterval);
|
|
55
|
+
available.inUse = true;
|
|
56
|
+
available.lastUsed = Date.now();
|
|
57
|
+
resolve(available.connection);
|
|
58
|
+
}
|
|
59
|
+
}, 50);
|
|
60
|
+
setTimeout(() => {
|
|
61
|
+
clearInterval(checkInterval);
|
|
62
|
+
reject(new Error(`Connection pool exhausted for "${name}"`));
|
|
63
|
+
}, 30000);
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
static releasePooledConnection(name, connection) {
|
|
67
|
+
const pool = this.pools.get(name);
|
|
68
|
+
if (!pool)
|
|
69
|
+
return;
|
|
70
|
+
const pooled = pool.find((p) => p.connection === connection);
|
|
71
|
+
if (pooled) {
|
|
72
|
+
pooled.inUse = false;
|
|
73
|
+
pooled.lastUsed = Date.now();
|
|
74
|
+
}
|
|
75
|
+
}
|
|
13
76
|
static add(name, connection) {
|
|
14
77
|
const resolved = connection instanceof Connection ? connection : new Connection(connection);
|
|
15
78
|
this.connections.set(name, resolved);
|
|
@@ -18,6 +81,18 @@ export class ConnectionManager {
|
|
|
18
81
|
static get(name) {
|
|
19
82
|
return this.connections.get(name);
|
|
20
83
|
}
|
|
84
|
+
static async getPooled(name, config) {
|
|
85
|
+
if (config) {
|
|
86
|
+
return this.getPooledConnection(name, config);
|
|
87
|
+
}
|
|
88
|
+
const existing = this.connections.get(name);
|
|
89
|
+
if (existing)
|
|
90
|
+
return existing;
|
|
91
|
+
throw new Error(`No connection registered for "${name}". Use add() first or provide config.`);
|
|
92
|
+
}
|
|
93
|
+
static release(name, connection) {
|
|
94
|
+
this.releasePooledConnection(name, connection);
|
|
95
|
+
}
|
|
21
96
|
static require(name) {
|
|
22
97
|
const connection = this.get(name);
|
|
23
98
|
if (!connection) {
|
|
@@ -93,9 +168,15 @@ export class ConnectionManager {
|
|
|
93
168
|
}
|
|
94
169
|
static async closeAll() {
|
|
95
170
|
const connections = new Set(this.connections.values());
|
|
171
|
+
for (const pool of this.pools.values()) {
|
|
172
|
+
for (const { connection } of pool) {
|
|
173
|
+
connections.add(connection);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
96
176
|
if (this.defaultConnection)
|
|
97
177
|
connections.add(this.defaultConnection);
|
|
98
178
|
this.connections.clear();
|
|
179
|
+
this.pools.clear();
|
|
99
180
|
this.tenantCache.clear();
|
|
100
181
|
for (const connection of connections) {
|
|
101
182
|
await connection.close();
|
|
@@ -30,6 +30,8 @@ export declare class Builder<T = Record<string, any>> {
|
|
|
30
30
|
unions: UnionClause[];
|
|
31
31
|
fromRaw?: string;
|
|
32
32
|
updateJoins: string[];
|
|
33
|
+
bindings: any[];
|
|
34
|
+
private parameterize;
|
|
33
35
|
constructor(connection: Connection, table: string);
|
|
34
36
|
private get grammar();
|
|
35
37
|
setModel(model: ModelConstructor): this;
|
|
@@ -129,6 +131,7 @@ export declare class Builder<T = Record<string, any>> {
|
|
|
129
131
|
clone(): Builder<T>;
|
|
130
132
|
wrapColumn(value: string): string;
|
|
131
133
|
escapeValue(value: any): string;
|
|
134
|
+
private addBinding;
|
|
132
135
|
private compileWhereClause;
|
|
133
136
|
private compileWheres;
|
|
134
137
|
private compileNestedWheres;
|
|
@@ -157,7 +160,7 @@ export declare class Builder<T = Record<string, any>> {
|
|
|
157
160
|
paginate(perPage?: number, page?: number): Promise<Paginator<T>>;
|
|
158
161
|
chunk(count: number, callback: (items: T[]) => void | Promise<void>): Promise<void>;
|
|
159
162
|
each(count: number, callback: (item: T) => void | Promise<void>): Promise<void>;
|
|
160
|
-
cursor(): AsyncGenerator<T>;
|
|
163
|
+
cursor(keyset?: Record<string, any>): AsyncGenerator<T>;
|
|
161
164
|
lazy(count?: number): AsyncGenerator<T>;
|
|
162
165
|
insert(data: ModelAttributeInput<T> | ModelAttributeInput<T>[]): Promise<any>;
|
|
163
166
|
insertGetId(data: ModelAttributeInput<T>, idColumn?: ModelColumn<T>): Promise<any>;
|
|
@@ -18,6 +18,8 @@ export class Builder {
|
|
|
18
18
|
unions = [];
|
|
19
19
|
fromRaw;
|
|
20
20
|
updateJoins = [];
|
|
21
|
+
bindings = [];
|
|
22
|
+
parameterize = false;
|
|
21
23
|
constructor(connection, table) {
|
|
22
24
|
this.connection = connection;
|
|
23
25
|
this.tableName = table;
|
|
@@ -257,11 +259,11 @@ export class Builder {
|
|
|
257
259
|
return this;
|
|
258
260
|
}
|
|
259
261
|
having(column, operator, value) {
|
|
260
|
-
this.havings.push({
|
|
262
|
+
this.havings.push({ column, operator, value, boolean: "and" });
|
|
261
263
|
return this;
|
|
262
264
|
}
|
|
263
265
|
orHaving(column, operator, value) {
|
|
264
|
-
this.havings.push({
|
|
266
|
+
this.havings.push({ column, operator, value, boolean: "or" });
|
|
265
267
|
return this;
|
|
266
268
|
}
|
|
267
269
|
havingRaw(sql, boolean = "and") {
|
|
@@ -455,6 +457,7 @@ export class Builder {
|
|
|
455
457
|
cloned.unions = [...this.unions];
|
|
456
458
|
cloned.fromRaw = this.fromRaw;
|
|
457
459
|
cloned.updateJoins = [...this.updateJoins];
|
|
460
|
+
cloned.bindings = [...this.bindings];
|
|
458
461
|
return cloned;
|
|
459
462
|
}
|
|
460
463
|
wrapColumn(value) {
|
|
@@ -463,13 +466,21 @@ export class Builder {
|
|
|
463
466
|
escapeValue(value) {
|
|
464
467
|
return this.grammar.escape(value);
|
|
465
468
|
}
|
|
469
|
+
addBinding(value) {
|
|
470
|
+
this.bindings.push(value);
|
|
471
|
+
return this.grammar.placeholder(this.bindings.length);
|
|
472
|
+
}
|
|
466
473
|
compileWhereClause(where, prefix) {
|
|
467
474
|
if (where.type === "basic") {
|
|
468
|
-
|
|
475
|
+
const value = this.parameterize ? this.addBinding(where.value) : this.grammar.escape(where.value);
|
|
476
|
+
return `${prefix} ${this.grammar.wrap(where.column)} ${where.operator} ${value}`;
|
|
469
477
|
}
|
|
470
478
|
else if (where.type === "in") {
|
|
471
479
|
const op = where.operator === "NOT IN" ? "NOT IN" : "IN";
|
|
472
|
-
|
|
480
|
+
const values = this.parameterize
|
|
481
|
+
? where.value.map((v) => this.addBinding(v)).join(", ")
|
|
482
|
+
: where.value.map((v) => this.grammar.escape(v)).join(", ");
|
|
483
|
+
return `${prefix} ${this.grammar.wrap(where.column)} ${op} (${values})`;
|
|
473
484
|
}
|
|
474
485
|
else if (where.type === "null") {
|
|
475
486
|
const op = where.operator === "NOT NULL" ? "IS NOT NULL" : "IS NULL";
|
|
@@ -477,7 +488,9 @@ export class Builder {
|
|
|
477
488
|
}
|
|
478
489
|
else if (where.type === "between") {
|
|
479
490
|
const op = where.operator === "NOT BETWEEN" ? "NOT BETWEEN" : "BETWEEN";
|
|
480
|
-
|
|
491
|
+
const low = this.parameterize ? this.addBinding(where.value[0]) : this.grammar.escape(where.value[0]);
|
|
492
|
+
const high = this.parameterize ? this.addBinding(where.value[1]) : this.grammar.escape(where.value[1]);
|
|
493
|
+
return `${prefix} ${this.grammar.wrap(where.column)} ${op} ${low} AND ${high}`;
|
|
481
494
|
}
|
|
482
495
|
else if (where.type === "raw") {
|
|
483
496
|
return `${prefix} ${where.column}`;
|
|
@@ -526,7 +539,11 @@ export class Builder {
|
|
|
526
539
|
return "";
|
|
527
540
|
const clauses = this.havings.map((h, index) => {
|
|
528
541
|
const prefix = index === 0 ? "" : h.boolean.toUpperCase() + " ";
|
|
529
|
-
|
|
542
|
+
if (h.sql) {
|
|
543
|
+
return prefix + h.sql;
|
|
544
|
+
}
|
|
545
|
+
const value = this.parameterize ? this.addBinding(h.value) : this.grammar.escape(h.value);
|
|
546
|
+
return prefix + `${this.grammar.wrap(h.column)} ${h.operator} ${value}`;
|
|
530
547
|
});
|
|
531
548
|
return `HAVING ${clauses.join(" ")}`;
|
|
532
549
|
}
|
|
@@ -565,7 +582,11 @@ export class Builder {
|
|
|
565
582
|
return sql.replace(/\s+/g, " ").trim();
|
|
566
583
|
}
|
|
567
584
|
async get() {
|
|
568
|
-
|
|
585
|
+
this.bindings = [];
|
|
586
|
+
this.parameterize = true;
|
|
587
|
+
const sql = this.toSql();
|
|
588
|
+
this.parameterize = false;
|
|
589
|
+
const results = await this.connection.query(sql, this.bindings);
|
|
569
590
|
const rows = Array.from(results);
|
|
570
591
|
if (this.model) {
|
|
571
592
|
const models = rows.map((row) => {
|
|
@@ -697,14 +718,34 @@ export class Builder {
|
|
|
697
718
|
}
|
|
698
719
|
});
|
|
699
720
|
}
|
|
700
|
-
async *cursor() {
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
|
|
706
|
-
|
|
707
|
-
|
|
721
|
+
async *cursor(keyset) {
|
|
722
|
+
const model = this.model;
|
|
723
|
+
const primaryKey = model ? model.primaryKey || "id" : "id";
|
|
724
|
+
const orderColumn = this.orders[0]?.column || primaryKey;
|
|
725
|
+
const orderDirection = this.orders[0]?.direction || "asc";
|
|
726
|
+
const builder = this.clone();
|
|
727
|
+
builder.orders = [{ column: orderColumn, direction: orderDirection }];
|
|
728
|
+
builder.offsetValue = undefined;
|
|
729
|
+
if (keyset) {
|
|
730
|
+
const op = orderDirection === "asc" ? ">" : "<";
|
|
731
|
+
builder.wheres.push({
|
|
732
|
+
type: "basic",
|
|
733
|
+
column: orderColumn,
|
|
734
|
+
operator: op,
|
|
735
|
+
value: keyset[orderColumn],
|
|
736
|
+
boolean: "and",
|
|
737
|
+
scope: undefined,
|
|
738
|
+
});
|
|
739
|
+
}
|
|
740
|
+
const items = await builder.limit(1).get();
|
|
741
|
+
if (items.length === 0)
|
|
742
|
+
return;
|
|
743
|
+
yield items[0];
|
|
744
|
+
const nextKeyset = items[0] && typeof items[0] === "object"
|
|
745
|
+
? { [orderColumn]: items[0][orderColumn] }
|
|
746
|
+
: undefined;
|
|
747
|
+
if (nextKeyset) {
|
|
748
|
+
yield* this.cursor(nextKeyset);
|
|
708
749
|
}
|
|
709
750
|
}
|
|
710
751
|
async *lazy(count = 1000) {
|
|
@@ -726,11 +767,15 @@ export class Builder {
|
|
|
726
767
|
if (records.length === 0)
|
|
727
768
|
return;
|
|
728
769
|
const columns = Object.keys(records[0]);
|
|
770
|
+
const bindings = [];
|
|
729
771
|
const values = records.map((record) => {
|
|
730
|
-
return `(${columns.map((col) =>
|
|
772
|
+
return `(${columns.map((col) => {
|
|
773
|
+
bindings.push(record[col]);
|
|
774
|
+
return this.grammar.placeholder(bindings.length);
|
|
775
|
+
}).join(", ")})`;
|
|
731
776
|
});
|
|
732
777
|
const sql = `INSERT INTO ${this.grammar.wrap(this.tableName)} (${columns.map((c) => this.grammar.wrap(c)).join(", ")}) VALUES ${values.join(", ")}`;
|
|
733
|
-
return await this.connection.run(sql);
|
|
778
|
+
return await this.connection.run(sql, bindings);
|
|
734
779
|
}
|
|
735
780
|
async insertGetId(data, idColumn = "id") {
|
|
736
781
|
const result = await this.insert(data);
|
|
@@ -741,43 +786,65 @@ export class Builder {
|
|
|
741
786
|
if (records.length === 0)
|
|
742
787
|
return;
|
|
743
788
|
const columns = Object.keys(records[0]);
|
|
789
|
+
const bindings = [];
|
|
744
790
|
const values = records.map((record) => {
|
|
745
|
-
return `(${columns.map((col) =>
|
|
791
|
+
return `(${columns.map((col) => {
|
|
792
|
+
bindings.push(record[col]);
|
|
793
|
+
return this.grammar.placeholder(bindings.length);
|
|
794
|
+
}).join(", ")})`;
|
|
746
795
|
});
|
|
747
796
|
const sql = this.grammar.compileInsertOrIgnore(this.grammar.wrap(this.tableName), columns, values);
|
|
748
|
-
return await this.connection.run(sql);
|
|
797
|
+
return await this.connection.run(sql, bindings);
|
|
749
798
|
}
|
|
750
799
|
async upsert(data, uniqueBy, updateColumns) {
|
|
751
800
|
const records = Array.isArray(data) ? data : [data];
|
|
752
801
|
if (records.length === 0)
|
|
753
802
|
return;
|
|
754
803
|
const columns = Object.keys(records[0]);
|
|
804
|
+
const bindings = [];
|
|
755
805
|
const values = records.map((record) => {
|
|
756
|
-
return `(${columns.map((col) =>
|
|
806
|
+
return `(${columns.map((col) => {
|
|
807
|
+
bindings.push(record[col]);
|
|
808
|
+
return this.grammar.placeholder(bindings.length);
|
|
809
|
+
}).join(", ")})`;
|
|
757
810
|
});
|
|
758
811
|
const uniqueCols = Array.isArray(uniqueBy) ? uniqueBy : [uniqueBy];
|
|
759
812
|
const updateCols = updateColumns ?? columns.filter((c) => !uniqueCols.includes(c));
|
|
760
813
|
const sql = this.grammar.compileUpsert(this.grammar.wrap(this.tableName), columns, values, uniqueCols, updateCols);
|
|
761
|
-
return await this.connection.run(sql);
|
|
814
|
+
return await this.connection.run(sql, bindings);
|
|
762
815
|
}
|
|
763
816
|
async update(data) {
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
|
|
767
|
-
|
|
768
|
-
|
|
817
|
+
this.bindings = [];
|
|
818
|
+
this.parameterize = true;
|
|
819
|
+
const sets = Object.entries(data).map(([key, value]) => {
|
|
820
|
+
this.bindings.push(value);
|
|
821
|
+
return `${this.grammar.wrap(key)} = ${this.grammar.placeholder(this.bindings.length)}`;
|
|
822
|
+
});
|
|
823
|
+
const whereSql = this.compileWheres();
|
|
824
|
+
this.parameterize = false;
|
|
825
|
+
const sql = this.grammar.compileUpdate(this.grammar.wrap(this.tableName), sets, whereSql, this.updateJoins);
|
|
826
|
+
return await this.connection.run(sql, this.bindings);
|
|
769
827
|
}
|
|
770
828
|
async delete() {
|
|
771
|
-
|
|
772
|
-
|
|
829
|
+
this.bindings = [];
|
|
830
|
+
this.parameterize = true;
|
|
831
|
+
const whereSql = this.compileWheres();
|
|
832
|
+
this.parameterize = false;
|
|
833
|
+
const sql = this.grammar.compileDelete(this.grammar.wrap(this.tableName), whereSql, this.updateJoins, this.limitValue);
|
|
834
|
+
return await this.connection.run(sql, this.bindings);
|
|
773
835
|
}
|
|
774
836
|
async increment(column, amount = 1, extra = {}) {
|
|
837
|
+
this.bindings = [];
|
|
838
|
+
this.parameterize = true;
|
|
775
839
|
const sets = [`${this.grammar.wrap(column)} = ${this.grammar.wrap(column)} + ${amount}`];
|
|
776
840
|
for (const [key, value] of Object.entries(extra)) {
|
|
777
|
-
|
|
841
|
+
this.bindings.push(value);
|
|
842
|
+
sets.push(`${this.grammar.wrap(key)} = ${this.grammar.placeholder(this.bindings.length)}`);
|
|
778
843
|
}
|
|
779
|
-
const
|
|
780
|
-
|
|
844
|
+
const whereSql = this.compileWheres();
|
|
845
|
+
this.parameterize = false;
|
|
846
|
+
const sql = `UPDATE ${this.grammar.wrap(this.tableName)} SET ${sets.join(", ")} ${whereSql}`;
|
|
847
|
+
return await this.connection.run(sql.trim(), this.bindings);
|
|
781
848
|
}
|
|
782
849
|
async decrement(column, amount = 1, extra = {}) {
|
|
783
850
|
return this.increment(column, -amount, extra);
|
|
@@ -819,8 +886,11 @@ export class Builder {
|
|
|
819
886
|
throw new Error("dd() called — execution halted.");
|
|
820
887
|
}
|
|
821
888
|
async explain() {
|
|
889
|
+
this.bindings = [];
|
|
890
|
+
this.parameterize = true;
|
|
822
891
|
const sql = this.grammar.compileExplain(this.toSql());
|
|
823
|
-
|
|
892
|
+
this.parameterize = false;
|
|
893
|
+
const results = await this.connection.query(sql, this.bindings);
|
|
824
894
|
return Array.from(results);
|
|
825
895
|
}
|
|
826
896
|
take(count) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
export declare abstract class Grammar {
|
|
2
2
|
abstract wrap(value: string): string;
|
|
3
3
|
wrapArray(values: string[]): string[];
|
|
4
|
+
abstract placeholder(index: number): string;
|
|
4
5
|
escape(value: any): string;
|
|
5
6
|
abstract compileRandomOrder(): string;
|
|
6
7
|
compileOffset(offset: number, _limit?: number): string;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Grammar } from "./Grammar.js";
|
|
2
2
|
export declare class MySqlGrammar extends Grammar {
|
|
3
3
|
wrap(value: string): string;
|
|
4
|
+
placeholder(_index: number): string;
|
|
4
5
|
compileRandomOrder(): string;
|
|
5
6
|
compileDateWhere(type: string, column: string, operator: string, value: any): string;
|
|
6
7
|
compileInsertOrIgnore(table: string, columns: string[], values: string[]): string;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Grammar } from "./Grammar.js";
|
|
2
2
|
export declare class PostgresGrammar extends Grammar {
|
|
3
3
|
wrap(value: string): string;
|
|
4
|
+
placeholder(index: number): string;
|
|
4
5
|
compileRandomOrder(): string;
|
|
5
6
|
compileDateWhere(type: string, column: string, operator: string, value: any): string;
|
|
6
7
|
compileInsertOrIgnore(table: string, columns: string[], values: string[]): string;
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { Grammar } from "./Grammar.js";
|
|
2
2
|
export declare class SQLiteGrammar extends Grammar {
|
|
3
3
|
wrap(value: string): string;
|
|
4
|
+
placeholder(_index: number): string;
|
|
4
5
|
compileRandomOrder(): string;
|
|
5
6
|
compileOffset(offset: number, limit?: number): string;
|
|
6
7
|
compileDateWhere(type: string, column: string, operator: string, value: any): string;
|
|
@@ -41,7 +41,10 @@ export interface OrderClause {
|
|
|
41
41
|
direction: "asc" | "desc";
|
|
42
42
|
}
|
|
43
43
|
export interface HavingClause {
|
|
44
|
-
|
|
44
|
+
column?: string;
|
|
45
|
+
operator?: string;
|
|
46
|
+
value?: any;
|
|
47
|
+
sql?: string;
|
|
45
48
|
boolean: "and" | "or";
|
|
46
49
|
}
|
|
47
50
|
export interface UnionClause {
|
package/package.json
CHANGED