node-mybatis-plus 0.1.0
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/README.md +426 -0
- package/dist/index.d.mts +302 -0
- package/dist/index.d.ts +302 -0
- package/dist/index.js +1051 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +1006 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +72 -0
package/dist/index.mjs
ADDED
|
@@ -0,0 +1,1006 @@
|
|
|
1
|
+
var __require = /* @__PURE__ */ ((x) => typeof require !== "undefined" ? require : typeof Proxy !== "undefined" ? new Proxy(x, {
|
|
2
|
+
get: (a, b) => (typeof require !== "undefined" ? require : a)[b]
|
|
3
|
+
}) : x)(function(x) {
|
|
4
|
+
if (typeof require !== "undefined") return require.apply(this, arguments);
|
|
5
|
+
throw Error('Dynamic require of "' + x + '" is not supported');
|
|
6
|
+
});
|
|
7
|
+
|
|
8
|
+
// src/index.ts
|
|
9
|
+
import "reflect-metadata";
|
|
10
|
+
|
|
11
|
+
// src/decorator/index.ts
|
|
12
|
+
import "reflect-metadata";
|
|
13
|
+
var metadataCache = /* @__PURE__ */ new Map();
|
|
14
|
+
function Table(tableName) {
|
|
15
|
+
return (target) => {
|
|
16
|
+
const existing = getOrCreateMeta(target);
|
|
17
|
+
existing.tableName = tableName;
|
|
18
|
+
metadataCache.set(target, existing);
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
function Id(options) {
|
|
22
|
+
return (target, propertyKey) => {
|
|
23
|
+
const meta = getOrCreateMeta(target.constructor);
|
|
24
|
+
const col = ensureColumn(meta, propertyKey);
|
|
25
|
+
col.isPrimary = true;
|
|
26
|
+
col.idType = options?.type ?? "auto";
|
|
27
|
+
meta.idColumn = col;
|
|
28
|
+
};
|
|
29
|
+
}
|
|
30
|
+
function Column(nameOrOptions) {
|
|
31
|
+
return (target, propertyKey) => {
|
|
32
|
+
const meta = getOrCreateMeta(target.constructor);
|
|
33
|
+
const col = ensureColumn(meta, propertyKey);
|
|
34
|
+
if (typeof nameOrOptions === "string") {
|
|
35
|
+
col.columnName = nameOrOptions;
|
|
36
|
+
} else if (nameOrOptions) {
|
|
37
|
+
if (nameOrOptions.name) col.columnName = nameOrOptions.name;
|
|
38
|
+
if (nameOrOptions.exist === false) col.exist = false;
|
|
39
|
+
}
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
function getOrCreateMeta(target) {
|
|
43
|
+
let meta = metadataCache.get(target);
|
|
44
|
+
if (!meta) {
|
|
45
|
+
meta = { tableName: "", columns: [], idColumn: null, target };
|
|
46
|
+
metadataCache.set(target, meta);
|
|
47
|
+
}
|
|
48
|
+
return meta;
|
|
49
|
+
}
|
|
50
|
+
function ensureColumn(meta, propertyName) {
|
|
51
|
+
let col = meta.columns.find((c) => c.propertyName === propertyName);
|
|
52
|
+
if (!col) {
|
|
53
|
+
col = {
|
|
54
|
+
propertyName,
|
|
55
|
+
columnName: camelToSnake(propertyName),
|
|
56
|
+
isPrimary: false,
|
|
57
|
+
exist: true
|
|
58
|
+
};
|
|
59
|
+
meta.columns.push(col);
|
|
60
|
+
}
|
|
61
|
+
return col;
|
|
62
|
+
}
|
|
63
|
+
function getEntityMeta(target) {
|
|
64
|
+
const meta = metadataCache.get(target);
|
|
65
|
+
if (!meta) throw new Error(`No entity metadata found for ${target.name}. Did you forget @Table?`);
|
|
66
|
+
return meta;
|
|
67
|
+
}
|
|
68
|
+
function camelToSnake(str) {
|
|
69
|
+
return str.replace(/[A-Z]/g, (letter) => `_${letter.toLowerCase()}`);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// src/dialect/index.ts
|
|
73
|
+
var MysqlDialect = class {
|
|
74
|
+
placeholder(_index) {
|
|
75
|
+
return "?";
|
|
76
|
+
}
|
|
77
|
+
quote(identifier) {
|
|
78
|
+
return `\`${identifier}\``;
|
|
79
|
+
}
|
|
80
|
+
paginate(sql, offset, limit) {
|
|
81
|
+
return `${sql} LIMIT ${limit} OFFSET ${offset}`;
|
|
82
|
+
}
|
|
83
|
+
insertReturningId() {
|
|
84
|
+
return null;
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
var PostgresDialect = class {
|
|
88
|
+
placeholder(index) {
|
|
89
|
+
return `$${index}`;
|
|
90
|
+
}
|
|
91
|
+
quote(identifier) {
|
|
92
|
+
return `"${identifier}"`;
|
|
93
|
+
}
|
|
94
|
+
paginate(sql, offset, limit) {
|
|
95
|
+
return `${sql} LIMIT ${limit} OFFSET ${offset}`;
|
|
96
|
+
}
|
|
97
|
+
insertReturningId(_table, _columns, idColumn) {
|
|
98
|
+
return `RETURNING "${idColumn}"`;
|
|
99
|
+
}
|
|
100
|
+
};
|
|
101
|
+
var SqliteDialect = class {
|
|
102
|
+
placeholder(_index) {
|
|
103
|
+
return "?";
|
|
104
|
+
}
|
|
105
|
+
quote(identifier) {
|
|
106
|
+
return `"${identifier}"`;
|
|
107
|
+
}
|
|
108
|
+
paginate(sql, offset, limit) {
|
|
109
|
+
return `${sql} LIMIT ${limit} OFFSET ${offset}`;
|
|
110
|
+
}
|
|
111
|
+
insertReturningId() {
|
|
112
|
+
return null;
|
|
113
|
+
}
|
|
114
|
+
};
|
|
115
|
+
function createDialect(type) {
|
|
116
|
+
switch (type) {
|
|
117
|
+
case "mysql":
|
|
118
|
+
return new MysqlDialect();
|
|
119
|
+
case "postgres":
|
|
120
|
+
return new PostgresDialect();
|
|
121
|
+
case "sqlite":
|
|
122
|
+
return new SqliteDialect();
|
|
123
|
+
default:
|
|
124
|
+
throw new Error(`Unsupported dialect: ${type}`);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
|
|
128
|
+
// src/core/transaction.ts
|
|
129
|
+
import { AsyncLocalStorage } from "async_hooks";
|
|
130
|
+
var txStore = new AsyncLocalStorage();
|
|
131
|
+
function getCurrentTxConnection() {
|
|
132
|
+
return txStore.getStore();
|
|
133
|
+
}
|
|
134
|
+
async function withTransaction(ds, fn) {
|
|
135
|
+
const existing = txStore.getStore();
|
|
136
|
+
if (existing && existing.datasource === ds) {
|
|
137
|
+
return fn();
|
|
138
|
+
}
|
|
139
|
+
const conn = await ds.getConnection();
|
|
140
|
+
await conn.query("BEGIN", []);
|
|
141
|
+
const ctx = { connection: conn, datasource: ds };
|
|
142
|
+
try {
|
|
143
|
+
const result = await txStore.run(ctx, fn);
|
|
144
|
+
await conn.query("COMMIT", []);
|
|
145
|
+
return result;
|
|
146
|
+
} catch (e) {
|
|
147
|
+
await conn.query("ROLLBACK", []);
|
|
148
|
+
throw e;
|
|
149
|
+
} finally {
|
|
150
|
+
conn.release();
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
var defaultDataSource = null;
|
|
154
|
+
function setDefaultDataSource(ds) {
|
|
155
|
+
defaultDataSource = ds;
|
|
156
|
+
}
|
|
157
|
+
function getDefaultDataSource() {
|
|
158
|
+
if (!defaultDataSource) throw new Error("No default DataSource set. Call setDefaultDataSource() first.");
|
|
159
|
+
return defaultDataSource;
|
|
160
|
+
}
|
|
161
|
+
function Transactional(options) {
|
|
162
|
+
return (_target, _propertyKey, descriptor) => {
|
|
163
|
+
const original = descriptor.value;
|
|
164
|
+
descriptor.value = async function(...args) {
|
|
165
|
+
const ds = options?.datasource ?? defaultDataSource;
|
|
166
|
+
if (!ds) throw new Error("No DataSource available for @Transactional. Set default or pass in options.");
|
|
167
|
+
return withTransaction(ds, () => original.apply(this, args));
|
|
168
|
+
};
|
|
169
|
+
return descriptor;
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
// src/core/datasource.ts
|
|
174
|
+
async function txAwareExecute(ds, sql, params) {
|
|
175
|
+
const txCtx = getCurrentTxConnection();
|
|
176
|
+
if (txCtx && txCtx.datasource === ds) {
|
|
177
|
+
return txCtx.connection.query(sql, params);
|
|
178
|
+
}
|
|
179
|
+
return null;
|
|
180
|
+
}
|
|
181
|
+
var MysqlConnection = class {
|
|
182
|
+
constructor(conn) {
|
|
183
|
+
this.conn = conn;
|
|
184
|
+
}
|
|
185
|
+
async query(sql, params) {
|
|
186
|
+
const cmd = sql.trimStart().toUpperCase();
|
|
187
|
+
if (cmd.startsWith("BEGIN") || cmd.startsWith("COMMIT") || cmd.startsWith("ROLLBACK") || cmd.startsWith("START")) {
|
|
188
|
+
const [rows2] = await this.conn.query(sql, params);
|
|
189
|
+
return rows2;
|
|
190
|
+
}
|
|
191
|
+
const [rows] = await this.conn.execute(sql, params);
|
|
192
|
+
return rows;
|
|
193
|
+
}
|
|
194
|
+
release() {
|
|
195
|
+
this.conn.release();
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
var MysqlDataSource = class {
|
|
199
|
+
constructor(config) {
|
|
200
|
+
this.config = config;
|
|
201
|
+
this.dialect = createDialect("mysql");
|
|
202
|
+
this.plugins = config.plugins ?? [];
|
|
203
|
+
}
|
|
204
|
+
dialect;
|
|
205
|
+
plugins;
|
|
206
|
+
pool;
|
|
207
|
+
async getPool() {
|
|
208
|
+
if (!this.pool) {
|
|
209
|
+
const mysql2 = await import("mysql2/promise");
|
|
210
|
+
this.pool = mysql2.createPool({
|
|
211
|
+
host: this.config.host ?? "localhost",
|
|
212
|
+
port: this.config.port ?? 3306,
|
|
213
|
+
database: this.config.database,
|
|
214
|
+
user: this.config.username,
|
|
215
|
+
password: this.config.password,
|
|
216
|
+
waitForConnections: true,
|
|
217
|
+
connectionLimit: this.config.pool?.max ?? 10
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
return this.pool;
|
|
221
|
+
}
|
|
222
|
+
async getConnection() {
|
|
223
|
+
const pool = await this.getPool();
|
|
224
|
+
const conn = await pool.getConnection();
|
|
225
|
+
return new MysqlConnection(conn);
|
|
226
|
+
}
|
|
227
|
+
async execute(sql, params) {
|
|
228
|
+
const txResult = await txAwareExecute(this, sql, params);
|
|
229
|
+
if (txResult !== null) return txResult;
|
|
230
|
+
const pool = await this.getPool();
|
|
231
|
+
const [rows] = await pool.execute(sql, params);
|
|
232
|
+
return rows;
|
|
233
|
+
}
|
|
234
|
+
async transaction(fn) {
|
|
235
|
+
const pool = await this.getPool();
|
|
236
|
+
const conn = await pool.getConnection();
|
|
237
|
+
await conn.beginTransaction();
|
|
238
|
+
const tx = {
|
|
239
|
+
connection: new MysqlConnection(conn),
|
|
240
|
+
async commit() {
|
|
241
|
+
await conn.commit();
|
|
242
|
+
},
|
|
243
|
+
async rollback() {
|
|
244
|
+
await conn.rollback();
|
|
245
|
+
}
|
|
246
|
+
};
|
|
247
|
+
try {
|
|
248
|
+
const result = await fn(tx);
|
|
249
|
+
await conn.commit();
|
|
250
|
+
return result;
|
|
251
|
+
} catch (e) {
|
|
252
|
+
await conn.rollback();
|
|
253
|
+
throw e;
|
|
254
|
+
} finally {
|
|
255
|
+
conn.release();
|
|
256
|
+
}
|
|
257
|
+
}
|
|
258
|
+
async close() {
|
|
259
|
+
if (this.pool) await this.pool.end();
|
|
260
|
+
}
|
|
261
|
+
};
|
|
262
|
+
var PgConnection = class {
|
|
263
|
+
constructor(client) {
|
|
264
|
+
this.client = client;
|
|
265
|
+
}
|
|
266
|
+
async query(sql, params) {
|
|
267
|
+
const result = await this.client.query(sql, params);
|
|
268
|
+
return result.rows;
|
|
269
|
+
}
|
|
270
|
+
release() {
|
|
271
|
+
this.client.release();
|
|
272
|
+
}
|
|
273
|
+
};
|
|
274
|
+
var PostgresDataSource = class {
|
|
275
|
+
constructor(config) {
|
|
276
|
+
this.config = config;
|
|
277
|
+
this.dialect = createDialect("postgres");
|
|
278
|
+
this.plugins = config.plugins ?? [];
|
|
279
|
+
}
|
|
280
|
+
dialect;
|
|
281
|
+
plugins;
|
|
282
|
+
pool;
|
|
283
|
+
async getPool() {
|
|
284
|
+
if (!this.pool) {
|
|
285
|
+
const { Pool } = await import("pg");
|
|
286
|
+
this.pool = new Pool({
|
|
287
|
+
host: this.config.host ?? "localhost",
|
|
288
|
+
port: this.config.port ?? 5432,
|
|
289
|
+
database: this.config.database,
|
|
290
|
+
user: this.config.username,
|
|
291
|
+
password: this.config.password,
|
|
292
|
+
min: this.config.pool?.min ?? 2,
|
|
293
|
+
max: this.config.pool?.max ?? 10,
|
|
294
|
+
idleTimeoutMillis: this.config.pool?.idleTimeout ?? 3e4
|
|
295
|
+
});
|
|
296
|
+
}
|
|
297
|
+
return this.pool;
|
|
298
|
+
}
|
|
299
|
+
async getConnection() {
|
|
300
|
+
const pool = await this.getPool();
|
|
301
|
+
const client = await pool.connect();
|
|
302
|
+
return new PgConnection(client);
|
|
303
|
+
}
|
|
304
|
+
async execute(sql, params) {
|
|
305
|
+
const txResult = await txAwareExecute(this, sql, params);
|
|
306
|
+
if (txResult !== null) return txResult;
|
|
307
|
+
const pool = await this.getPool();
|
|
308
|
+
const result = await pool.query(sql, params);
|
|
309
|
+
return result.rows;
|
|
310
|
+
}
|
|
311
|
+
async transaction(fn) {
|
|
312
|
+
const pool = await this.getPool();
|
|
313
|
+
const client = await pool.connect();
|
|
314
|
+
await client.query("BEGIN");
|
|
315
|
+
const tx = {
|
|
316
|
+
connection: new PgConnection(client),
|
|
317
|
+
async commit() {
|
|
318
|
+
await client.query("COMMIT");
|
|
319
|
+
},
|
|
320
|
+
async rollback() {
|
|
321
|
+
await client.query("ROLLBACK");
|
|
322
|
+
}
|
|
323
|
+
};
|
|
324
|
+
try {
|
|
325
|
+
const result = await fn(tx);
|
|
326
|
+
await client.query("COMMIT");
|
|
327
|
+
return result;
|
|
328
|
+
} catch (e) {
|
|
329
|
+
await client.query("ROLLBACK");
|
|
330
|
+
throw e;
|
|
331
|
+
} finally {
|
|
332
|
+
client.release();
|
|
333
|
+
}
|
|
334
|
+
}
|
|
335
|
+
async close() {
|
|
336
|
+
if (this.pool) await this.pool.end();
|
|
337
|
+
}
|
|
338
|
+
};
|
|
339
|
+
var SqliteConnection = class {
|
|
340
|
+
constructor(db) {
|
|
341
|
+
this.db = db;
|
|
342
|
+
}
|
|
343
|
+
async query(sql, params) {
|
|
344
|
+
const trimmed = sql.trimStart().toUpperCase();
|
|
345
|
+
if (trimmed.startsWith("SELECT") || trimmed.startsWith("WITH")) {
|
|
346
|
+
return this.db.prepare(sql).all(...params);
|
|
347
|
+
}
|
|
348
|
+
return this.db.prepare(sql).run(...params);
|
|
349
|
+
}
|
|
350
|
+
release() {
|
|
351
|
+
}
|
|
352
|
+
};
|
|
353
|
+
var SqliteDataSource = class {
|
|
354
|
+
constructor(config) {
|
|
355
|
+
this.config = config;
|
|
356
|
+
this.dialect = createDialect("sqlite");
|
|
357
|
+
this.plugins = config.plugins ?? [];
|
|
358
|
+
}
|
|
359
|
+
dialect;
|
|
360
|
+
plugins;
|
|
361
|
+
db;
|
|
362
|
+
getDb() {
|
|
363
|
+
if (!this.db) {
|
|
364
|
+
const Database = __require("better-sqlite3");
|
|
365
|
+
this.db = new Database(this.config.database);
|
|
366
|
+
this.db.pragma("journal_mode = WAL");
|
|
367
|
+
}
|
|
368
|
+
return this.db;
|
|
369
|
+
}
|
|
370
|
+
async getConnection() {
|
|
371
|
+
return new SqliteConnection(this.getDb());
|
|
372
|
+
}
|
|
373
|
+
async execute(sql, params) {
|
|
374
|
+
const txResult = await txAwareExecute(this, sql, params);
|
|
375
|
+
if (txResult !== null) return txResult;
|
|
376
|
+
const conn = await this.getConnection();
|
|
377
|
+
return conn.query(sql, params);
|
|
378
|
+
}
|
|
379
|
+
async transaction(fn) {
|
|
380
|
+
const db = this.getDb();
|
|
381
|
+
const conn = new SqliteConnection(db);
|
|
382
|
+
db.prepare("BEGIN").run();
|
|
383
|
+
const tx = {
|
|
384
|
+
connection: conn,
|
|
385
|
+
async commit() {
|
|
386
|
+
db.prepare("COMMIT").run();
|
|
387
|
+
},
|
|
388
|
+
async rollback() {
|
|
389
|
+
db.prepare("ROLLBACK").run();
|
|
390
|
+
}
|
|
391
|
+
};
|
|
392
|
+
try {
|
|
393
|
+
const result = await fn(tx);
|
|
394
|
+
db.prepare("COMMIT").run();
|
|
395
|
+
return result;
|
|
396
|
+
} catch (e) {
|
|
397
|
+
db.prepare("ROLLBACK").run();
|
|
398
|
+
throw e;
|
|
399
|
+
}
|
|
400
|
+
}
|
|
401
|
+
async close() {
|
|
402
|
+
if (this.db) this.db.close();
|
|
403
|
+
}
|
|
404
|
+
};
|
|
405
|
+
function createDataSource(config) {
|
|
406
|
+
switch (config.type) {
|
|
407
|
+
case "mysql":
|
|
408
|
+
return new MysqlDataSource(config);
|
|
409
|
+
case "postgres":
|
|
410
|
+
return new PostgresDataSource(config);
|
|
411
|
+
case "sqlite":
|
|
412
|
+
return new SqliteDataSource(config);
|
|
413
|
+
default:
|
|
414
|
+
throw new Error(`Unsupported database type: ${config.type}`);
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
// src/wrapper/abstract-wrapper.ts
|
|
419
|
+
var AbstractWrapper = class {
|
|
420
|
+
constructor(entityMeta) {
|
|
421
|
+
this.entityMeta = entityMeta;
|
|
422
|
+
}
|
|
423
|
+
conditionGroup = { logic: "AND", items: [] };
|
|
424
|
+
_orderBy = [];
|
|
425
|
+
_groupBy = [];
|
|
426
|
+
_having = null;
|
|
427
|
+
eq(...args) {
|
|
428
|
+
return this.addCondition("=", args);
|
|
429
|
+
}
|
|
430
|
+
ne(...args) {
|
|
431
|
+
return this.addCondition("!=", args);
|
|
432
|
+
}
|
|
433
|
+
gt(...args) {
|
|
434
|
+
return this.addCondition(">", args);
|
|
435
|
+
}
|
|
436
|
+
ge(...args) {
|
|
437
|
+
return this.addCondition(">=", args);
|
|
438
|
+
}
|
|
439
|
+
lt(...args) {
|
|
440
|
+
return this.addCondition("<", args);
|
|
441
|
+
}
|
|
442
|
+
le(...args) {
|
|
443
|
+
return this.addCondition("<=", args);
|
|
444
|
+
}
|
|
445
|
+
like(...args) {
|
|
446
|
+
return this.addCondition("LIKE", args, (v) => `%${v}%`);
|
|
447
|
+
}
|
|
448
|
+
likeLeft(...args) {
|
|
449
|
+
return this.addCondition("LIKE", args, (v) => `%${v}`);
|
|
450
|
+
}
|
|
451
|
+
likeRight(...args) {
|
|
452
|
+
return this.addCondition("LIKE", args, (v) => `${v}%`);
|
|
453
|
+
}
|
|
454
|
+
between(...args) {
|
|
455
|
+
const { active, column, values } = this.parseArgs(args, 2);
|
|
456
|
+
if (active) {
|
|
457
|
+
this.conditionGroup.items.push({
|
|
458
|
+
column: this.resolveColumn(column),
|
|
459
|
+
op: "BETWEEN",
|
|
460
|
+
value: values[0],
|
|
461
|
+
value2: values[1]
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
return this;
|
|
465
|
+
}
|
|
466
|
+
in(...args) {
|
|
467
|
+
return this.addCondition("IN", args);
|
|
468
|
+
}
|
|
469
|
+
notIn(...args) {
|
|
470
|
+
return this.addCondition("NOT IN", args);
|
|
471
|
+
}
|
|
472
|
+
isNull(...args) {
|
|
473
|
+
const hasCondition = typeof args[0] === "boolean";
|
|
474
|
+
const active = hasCondition ? args[0] : true;
|
|
475
|
+
const column = hasCondition ? args[1] : args[0];
|
|
476
|
+
if (active) {
|
|
477
|
+
this.conditionGroup.items.push({ column: this.resolveColumn(column), op: "IS NULL" });
|
|
478
|
+
}
|
|
479
|
+
return this;
|
|
480
|
+
}
|
|
481
|
+
isNotNull(...args) {
|
|
482
|
+
const hasCondition = typeof args[0] === "boolean";
|
|
483
|
+
const active = hasCondition ? args[0] : true;
|
|
484
|
+
const column = hasCondition ? args[1] : args[0];
|
|
485
|
+
if (active) {
|
|
486
|
+
this.conditionGroup.items.push({ column: this.resolveColumn(column), op: "IS NOT NULL" });
|
|
487
|
+
}
|
|
488
|
+
return this;
|
|
489
|
+
}
|
|
490
|
+
or(fn) {
|
|
491
|
+
const sub = this.createNested("OR");
|
|
492
|
+
fn(sub);
|
|
493
|
+
const nested = sub.conditionGroup;
|
|
494
|
+
if (nested.items.length) this.conditionGroup.items.push(nested);
|
|
495
|
+
return this;
|
|
496
|
+
}
|
|
497
|
+
and(fn) {
|
|
498
|
+
const sub = this.createNested("AND");
|
|
499
|
+
fn(sub);
|
|
500
|
+
const nested = sub.conditionGroup;
|
|
501
|
+
if (nested.items.length) this.conditionGroup.items.push(nested);
|
|
502
|
+
return this;
|
|
503
|
+
}
|
|
504
|
+
// ---- 排序 & 分组 ----
|
|
505
|
+
orderByAsc(...columns) {
|
|
506
|
+
for (const c of columns) this._orderBy.push({ column: this.resolveColumn(c), direction: "ASC" });
|
|
507
|
+
return this;
|
|
508
|
+
}
|
|
509
|
+
orderByDesc(...columns) {
|
|
510
|
+
for (const c of columns) this._orderBy.push({ column: this.resolveColumn(c), direction: "DESC" });
|
|
511
|
+
return this;
|
|
512
|
+
}
|
|
513
|
+
groupBy(...columns) {
|
|
514
|
+
this._groupBy.push(...columns.map((c) => this.resolveColumn(c)));
|
|
515
|
+
return this;
|
|
516
|
+
}
|
|
517
|
+
// ---- 内部方法 ----
|
|
518
|
+
resolveColumn(propertyName) {
|
|
519
|
+
const col = this.entityMeta.columns.find((c) => c.propertyName === propertyName);
|
|
520
|
+
return col ? col.columnName : propertyName;
|
|
521
|
+
}
|
|
522
|
+
getConditionGroup() {
|
|
523
|
+
return this.conditionGroup;
|
|
524
|
+
}
|
|
525
|
+
getOrderBy() {
|
|
526
|
+
return this._orderBy;
|
|
527
|
+
}
|
|
528
|
+
getGroupBy() {
|
|
529
|
+
return this._groupBy;
|
|
530
|
+
}
|
|
531
|
+
getHaving() {
|
|
532
|
+
return this._having;
|
|
533
|
+
}
|
|
534
|
+
addCondition(op, args, transform) {
|
|
535
|
+
const { active, column, values } = this.parseArgs(args, 1);
|
|
536
|
+
if (active) {
|
|
537
|
+
const value = transform ? transform(values[0]) : values[0];
|
|
538
|
+
this.conditionGroup.items.push({ column: this.resolveColumn(column), op, value });
|
|
539
|
+
}
|
|
540
|
+
return this;
|
|
541
|
+
}
|
|
542
|
+
parseArgs(args, valueCount) {
|
|
543
|
+
const hasCondition = typeof args[0] === "boolean";
|
|
544
|
+
const offset = hasCondition ? 1 : 0;
|
|
545
|
+
return {
|
|
546
|
+
active: hasCondition ? args[0] : true,
|
|
547
|
+
column: args[offset],
|
|
548
|
+
values: args.slice(offset + 1, offset + 1 + valueCount)
|
|
549
|
+
};
|
|
550
|
+
}
|
|
551
|
+
createNested(logic) {
|
|
552
|
+
const Ctor = this.constructor;
|
|
553
|
+
const nested = new Ctor(this.entityMeta);
|
|
554
|
+
nested.conditionGroup = { logic, items: [] };
|
|
555
|
+
return nested;
|
|
556
|
+
}
|
|
557
|
+
};
|
|
558
|
+
|
|
559
|
+
// src/builder/sql-builder.ts
|
|
560
|
+
var SqlBuilder = class {
|
|
561
|
+
constructor(dialect) {
|
|
562
|
+
this.dialect = dialect;
|
|
563
|
+
}
|
|
564
|
+
params = [];
|
|
565
|
+
paramIndex = 0;
|
|
566
|
+
build(node) {
|
|
567
|
+
this.params = [];
|
|
568
|
+
this.paramIndex = 0;
|
|
569
|
+
let sql;
|
|
570
|
+
switch (node.type) {
|
|
571
|
+
case "select":
|
|
572
|
+
sql = this.buildSelect(node);
|
|
573
|
+
break;
|
|
574
|
+
case "insert":
|
|
575
|
+
sql = this.buildInsert(node);
|
|
576
|
+
break;
|
|
577
|
+
case "update":
|
|
578
|
+
sql = this.buildUpdate(node);
|
|
579
|
+
break;
|
|
580
|
+
case "delete":
|
|
581
|
+
sql = this.buildDelete(node);
|
|
582
|
+
break;
|
|
583
|
+
}
|
|
584
|
+
return { sql, params: this.params };
|
|
585
|
+
}
|
|
586
|
+
buildSelect(node) {
|
|
587
|
+
const cols = node.columns.length ? node.columns.map((c) => this.q(c)).join(", ") : "*";
|
|
588
|
+
let sql = `SELECT ${cols} FROM ${this.q(node.table)}`;
|
|
589
|
+
if (node.where) {
|
|
590
|
+
const w = this.buildConditionGroup(node.where);
|
|
591
|
+
if (w) sql += ` WHERE ${w}`;
|
|
592
|
+
}
|
|
593
|
+
if (node.groupBy.length) {
|
|
594
|
+
sql += ` GROUP BY ${node.groupBy.map((c) => this.q(c)).join(", ")}`;
|
|
595
|
+
}
|
|
596
|
+
if (node.having) {
|
|
597
|
+
const h = this.buildConditionGroup(node.having);
|
|
598
|
+
if (h) sql += ` HAVING ${h}`;
|
|
599
|
+
}
|
|
600
|
+
if (node.orderBy.length) {
|
|
601
|
+
sql += ` ORDER BY ${node.orderBy.map((o) => `${this.q(o.column)} ${o.direction}`).join(", ")}`;
|
|
602
|
+
}
|
|
603
|
+
if (node.limit) {
|
|
604
|
+
sql = this.dialect.paginate(sql, node.limit.offset, node.limit.count);
|
|
605
|
+
}
|
|
606
|
+
return sql;
|
|
607
|
+
}
|
|
608
|
+
buildInsert(node) {
|
|
609
|
+
const cols = node.columns.map((c) => this.q(c)).join(", ");
|
|
610
|
+
const rows = node.values.map((row) => {
|
|
611
|
+
const placeholders = row.map((v) => this.addParam(v));
|
|
612
|
+
return `(${placeholders.join(", ")})`;
|
|
613
|
+
}).join(", ");
|
|
614
|
+
return `INSERT INTO ${this.q(node.table)} (${cols}) VALUES ${rows}`;
|
|
615
|
+
}
|
|
616
|
+
buildUpdate(node) {
|
|
617
|
+
const sets = node.sets.map((s) => `${this.q(s.column)} = ${this.addParam(s.value)}`).join(", ");
|
|
618
|
+
let sql = `UPDATE ${this.q(node.table)} SET ${sets}`;
|
|
619
|
+
if (node.where) {
|
|
620
|
+
const w = this.buildConditionGroup(node.where);
|
|
621
|
+
if (w) sql += ` WHERE ${w}`;
|
|
622
|
+
}
|
|
623
|
+
return sql;
|
|
624
|
+
}
|
|
625
|
+
buildDelete(node) {
|
|
626
|
+
let sql = `DELETE FROM ${this.q(node.table)}`;
|
|
627
|
+
if (node.where) {
|
|
628
|
+
const w = this.buildConditionGroup(node.where);
|
|
629
|
+
if (w) sql += ` WHERE ${w}`;
|
|
630
|
+
}
|
|
631
|
+
return sql;
|
|
632
|
+
}
|
|
633
|
+
buildConditionGroup(group) {
|
|
634
|
+
const parts = [];
|
|
635
|
+
for (const item of group.items) {
|
|
636
|
+
if ("logic" in item) {
|
|
637
|
+
const sub = this.buildConditionGroup(item);
|
|
638
|
+
if (sub) parts.push(`(${sub})`);
|
|
639
|
+
} else {
|
|
640
|
+
parts.push(this.buildCondition(item));
|
|
641
|
+
}
|
|
642
|
+
}
|
|
643
|
+
return parts.join(` ${group.logic} `);
|
|
644
|
+
}
|
|
645
|
+
buildCondition(cond) {
|
|
646
|
+
const col = this.q(cond.column);
|
|
647
|
+
switch (cond.op) {
|
|
648
|
+
case "IS NULL":
|
|
649
|
+
return `${col} IS NULL`;
|
|
650
|
+
case "IS NOT NULL":
|
|
651
|
+
return `${col} IS NOT NULL`;
|
|
652
|
+
case "BETWEEN":
|
|
653
|
+
return `${col} BETWEEN ${this.addParam(cond.value)} AND ${this.addParam(cond.value2)}`;
|
|
654
|
+
case "IN":
|
|
655
|
+
case "NOT IN": {
|
|
656
|
+
const list = cond.value.map((v) => this.addParam(v)).join(", ");
|
|
657
|
+
return `${col} ${cond.op} (${list})`;
|
|
658
|
+
}
|
|
659
|
+
default:
|
|
660
|
+
return `${col} ${cond.op} ${this.addParam(cond.value)}`;
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
addParam(value) {
|
|
664
|
+
this.params.push(value);
|
|
665
|
+
return this.dialect.placeholder(++this.paramIndex);
|
|
666
|
+
}
|
|
667
|
+
q(identifier) {
|
|
668
|
+
return this.dialect.quote(identifier);
|
|
669
|
+
}
|
|
670
|
+
};
|
|
671
|
+
|
|
672
|
+
// src/plugin/runner.ts
|
|
673
|
+
async function runPlugins(ds, node, sql, params, entityMeta) {
|
|
674
|
+
const plugins = [...ds.plugins].sort((a, b) => a.order - b.order);
|
|
675
|
+
const ctx = { node, sql, params, entityMeta };
|
|
676
|
+
for (const p of plugins) {
|
|
677
|
+
if (p.beforeExecute) {
|
|
678
|
+
await p.beforeExecute(ctx);
|
|
679
|
+
}
|
|
680
|
+
}
|
|
681
|
+
let result = await ds.execute(ctx.sql, ctx.params);
|
|
682
|
+
for (const p of plugins) {
|
|
683
|
+
if (p.afterExecute) {
|
|
684
|
+
const r = await p.afterExecute(ctx, result);
|
|
685
|
+
if (r !== void 0) result = r;
|
|
686
|
+
}
|
|
687
|
+
}
|
|
688
|
+
return result;
|
|
689
|
+
}
|
|
690
|
+
|
|
691
|
+
// src/wrapper/query-wrapper.ts
|
|
692
|
+
var LambdaQueryWrapper = class extends AbstractWrapper {
|
|
693
|
+
_columns = [];
|
|
694
|
+
_limit = null;
|
|
695
|
+
_datasource = null;
|
|
696
|
+
constructor(entityMeta) {
|
|
697
|
+
super(entityMeta);
|
|
698
|
+
}
|
|
699
|
+
/** 绑定数据源(由 BaseMapper 调用) */
|
|
700
|
+
bindDataSource(ds) {
|
|
701
|
+
this._datasource = ds;
|
|
702
|
+
return this;
|
|
703
|
+
}
|
|
704
|
+
select(...columns) {
|
|
705
|
+
this._columns = columns.map((c) => this.resolveColumn(c));
|
|
706
|
+
return this;
|
|
707
|
+
}
|
|
708
|
+
page(page, size) {
|
|
709
|
+
this._limit = { offset: (page - 1) * size, count: size };
|
|
710
|
+
return this;
|
|
711
|
+
}
|
|
712
|
+
/** 构建 SelectNode AST */
|
|
713
|
+
buildSelectNode() {
|
|
714
|
+
return {
|
|
715
|
+
type: "select",
|
|
716
|
+
table: this.entityMeta.tableName,
|
|
717
|
+
columns: this._columns,
|
|
718
|
+
where: this.conditionGroup.items.length ? this.conditionGroup : null,
|
|
719
|
+
orderBy: this._orderBy,
|
|
720
|
+
groupBy: this._groupBy,
|
|
721
|
+
having: this._having,
|
|
722
|
+
limit: this._limit
|
|
723
|
+
};
|
|
724
|
+
}
|
|
725
|
+
/** 终结操作:执行查询返回列表 */
|
|
726
|
+
async list() {
|
|
727
|
+
const ds = this.requireDs();
|
|
728
|
+
const node = this.buildSelectNode();
|
|
729
|
+
const builder = new SqlBuilder(ds.dialect);
|
|
730
|
+
const { sql, params } = builder.build(node);
|
|
731
|
+
if (ds.plugins.length) {
|
|
732
|
+
return runPlugins(ds, node, sql, params, this.entityMeta);
|
|
733
|
+
}
|
|
734
|
+
return ds.execute(sql, params);
|
|
735
|
+
}
|
|
736
|
+
/** 终结操作:查询单条 */
|
|
737
|
+
async one() {
|
|
738
|
+
this._limit = { offset: 0, count: 1 };
|
|
739
|
+
const list = await this.list();
|
|
740
|
+
return list[0] ?? null;
|
|
741
|
+
}
|
|
742
|
+
/** 终结操作:查询数量 */
|
|
743
|
+
async count() {
|
|
744
|
+
const ds = this.requireDs();
|
|
745
|
+
const node = {
|
|
746
|
+
...this.buildSelectNode(),
|
|
747
|
+
columns: [],
|
|
748
|
+
orderBy: [],
|
|
749
|
+
limit: null
|
|
750
|
+
};
|
|
751
|
+
const builder = new SqlBuilder(ds.dialect);
|
|
752
|
+
const { sql, params } = builder.build(node);
|
|
753
|
+
const countSql = sql.replace(/^SELECT \* FROM/, "SELECT COUNT(*) AS total FROM");
|
|
754
|
+
let rows;
|
|
755
|
+
if (ds.plugins.length) {
|
|
756
|
+
rows = await runPlugins(ds, node, countSql, params, this.entityMeta);
|
|
757
|
+
} else {
|
|
758
|
+
rows = await ds.execute(countSql, params);
|
|
759
|
+
}
|
|
760
|
+
return Number(rows[0]?.total ?? rows[0]?.count ?? 0);
|
|
761
|
+
}
|
|
762
|
+
/** 终结操作:分页查询 */
|
|
763
|
+
async pageResult(page, size) {
|
|
764
|
+
this._limit = { offset: (page - 1) * size, count: size };
|
|
765
|
+
const [records, total] = await Promise.all([
|
|
766
|
+
this.list(),
|
|
767
|
+
this.count()
|
|
768
|
+
]);
|
|
769
|
+
return {
|
|
770
|
+
records,
|
|
771
|
+
total,
|
|
772
|
+
page,
|
|
773
|
+
size,
|
|
774
|
+
pages: Math.ceil(total / size)
|
|
775
|
+
};
|
|
776
|
+
}
|
|
777
|
+
requireDs() {
|
|
778
|
+
if (!this._datasource) throw new Error("DataSource not bound. Use BaseMapper to create wrapper.");
|
|
779
|
+
return this._datasource;
|
|
780
|
+
}
|
|
781
|
+
};
|
|
782
|
+
|
|
783
|
+
// src/wrapper/update-wrapper.ts
|
|
784
|
+
var LambdaUpdateWrapper = class extends AbstractWrapper {
|
|
785
|
+
_sets = [];
|
|
786
|
+
_datasource = null;
|
|
787
|
+
constructor(entityMeta) {
|
|
788
|
+
super(entityMeta);
|
|
789
|
+
}
|
|
790
|
+
bindDataSource(ds) {
|
|
791
|
+
this._datasource = ds;
|
|
792
|
+
return this;
|
|
793
|
+
}
|
|
794
|
+
set(...args) {
|
|
795
|
+
const hasCondition = typeof args[0] === "boolean";
|
|
796
|
+
const active = hasCondition ? args[0] : true;
|
|
797
|
+
const column = hasCondition ? args[1] : args[0];
|
|
798
|
+
const value = hasCondition ? args[2] : args[1];
|
|
799
|
+
if (active) {
|
|
800
|
+
this._sets.push({ column: this.resolveColumn(column), value });
|
|
801
|
+
}
|
|
802
|
+
return this;
|
|
803
|
+
}
|
|
804
|
+
buildUpdateNode() {
|
|
805
|
+
return {
|
|
806
|
+
type: "update",
|
|
807
|
+
table: this.entityMeta.tableName,
|
|
808
|
+
sets: this._sets,
|
|
809
|
+
where: this.conditionGroup.items.length ? this.conditionGroup : null
|
|
810
|
+
};
|
|
811
|
+
}
|
|
812
|
+
async execute() {
|
|
813
|
+
if (!this._datasource) throw new Error("DataSource not bound.");
|
|
814
|
+
if (!this._sets.length) throw new Error("No SET clause specified.");
|
|
815
|
+
const node = this.buildUpdateNode();
|
|
816
|
+
const builder = new SqlBuilder(this._datasource.dialect);
|
|
817
|
+
const { sql, params } = builder.build(node);
|
|
818
|
+
let result;
|
|
819
|
+
if (this._datasource.plugins.length) {
|
|
820
|
+
result = await runPlugins(this._datasource, node, sql, params, this.entityMeta);
|
|
821
|
+
} else {
|
|
822
|
+
result = await this._datasource.execute(sql, params);
|
|
823
|
+
}
|
|
824
|
+
return result?.affectedRows ?? result?.rowCount ?? result?.changes ?? 0;
|
|
825
|
+
}
|
|
826
|
+
};
|
|
827
|
+
|
|
828
|
+
// src/mapper/base-mapper.ts
|
|
829
|
+
var BaseMapper = class {
|
|
830
|
+
entityMeta;
|
|
831
|
+
ds;
|
|
832
|
+
constructor(entityClass, datasource) {
|
|
833
|
+
this.entityMeta = getEntityMeta(entityClass);
|
|
834
|
+
this.ds = datasource;
|
|
835
|
+
}
|
|
836
|
+
// ---- 链式入口 ----
|
|
837
|
+
lambdaQuery() {
|
|
838
|
+
return new LambdaQueryWrapper(this.entityMeta).bindDataSource(this.ds);
|
|
839
|
+
}
|
|
840
|
+
lambdaUpdate() {
|
|
841
|
+
return new LambdaUpdateWrapper(this.entityMeta).bindDataSource(this.ds);
|
|
842
|
+
}
|
|
843
|
+
// ---- 新增 ----
|
|
844
|
+
async insert(entity) {
|
|
845
|
+
const { columns, values } = this.extractColumns(entity);
|
|
846
|
+
const node = { type: "insert", table: this.entityMeta.tableName, columns, values: [values] };
|
|
847
|
+
const { sql, params } = new SqlBuilder(this.ds.dialect).build(node);
|
|
848
|
+
const result = await this.executeWithPlugins(node, sql, params);
|
|
849
|
+
return result?.insertId ?? result?.[0]?.id ?? result?.lastInsertRowid ?? 0;
|
|
850
|
+
}
|
|
851
|
+
async insertBatch(entities) {
|
|
852
|
+
if (!entities.length) return 0;
|
|
853
|
+
const cols = this.getInsertableColumns();
|
|
854
|
+
const columns = cols.map((c) => c.columnName);
|
|
855
|
+
const values = entities.map((e) => cols.map((c) => e[c.propertyName]));
|
|
856
|
+
const node = { type: "insert", table: this.entityMeta.tableName, columns, values };
|
|
857
|
+
const { sql, params } = new SqlBuilder(this.ds.dialect).build(node);
|
|
858
|
+
const result = await this.executeWithPlugins(node, sql, params);
|
|
859
|
+
return result?.affectedRows ?? result?.rowCount ?? result?.changes ?? entities.length;
|
|
860
|
+
}
|
|
861
|
+
// ---- 删除 ----
|
|
862
|
+
async deleteById(id) {
|
|
863
|
+
const idCol = this.requireIdColumn();
|
|
864
|
+
const node = {
|
|
865
|
+
type: "delete",
|
|
866
|
+
table: this.entityMeta.tableName,
|
|
867
|
+
where: { logic: "AND", items: [{ column: idCol.columnName, op: "=", value: id }] }
|
|
868
|
+
};
|
|
869
|
+
const { sql, params } = new SqlBuilder(this.ds.dialect).build(node);
|
|
870
|
+
const result = await this.executeWithPlugins(node, sql, params);
|
|
871
|
+
return result?.affectedRows ?? result?.rowCount ?? result?.changes ?? 0;
|
|
872
|
+
}
|
|
873
|
+
async deleteBatchIds(ids) {
|
|
874
|
+
if (!ids.length) return 0;
|
|
875
|
+
const idCol = this.requireIdColumn();
|
|
876
|
+
const node = {
|
|
877
|
+
type: "delete",
|
|
878
|
+
table: this.entityMeta.tableName,
|
|
879
|
+
where: { logic: "AND", items: [{ column: idCol.columnName, op: "IN", value: ids }] }
|
|
880
|
+
};
|
|
881
|
+
const { sql, params } = new SqlBuilder(this.ds.dialect).build(node);
|
|
882
|
+
const result = await this.executeWithPlugins(node, sql, params);
|
|
883
|
+
return result?.affectedRows ?? result?.rowCount ?? result?.changes ?? 0;
|
|
884
|
+
}
|
|
885
|
+
async delete(wrapper) {
|
|
886
|
+
const group = wrapper.getConditionGroup();
|
|
887
|
+
const node = {
|
|
888
|
+
type: "delete",
|
|
889
|
+
table: this.entityMeta.tableName,
|
|
890
|
+
where: group.items.length ? group : null
|
|
891
|
+
};
|
|
892
|
+
const { sql, params } = new SqlBuilder(this.ds.dialect).build(node);
|
|
893
|
+
const result = await this.executeWithPlugins(node, sql, params);
|
|
894
|
+
return result?.affectedRows ?? result?.rowCount ?? result?.changes ?? 0;
|
|
895
|
+
}
|
|
896
|
+
// ---- 修改 ----
|
|
897
|
+
async updateById(entity) {
|
|
898
|
+
const idCol = this.requireIdColumn();
|
|
899
|
+
const idValue = entity[idCol.propertyName];
|
|
900
|
+
if (idValue == null) throw new Error("Entity must have id value for updateById");
|
|
901
|
+
const sets = this.entityMeta.columns.filter((c) => c.exist && !c.isPrimary && entity[c.propertyName] !== void 0).map((c) => ({ column: c.columnName, value: entity[c.propertyName] }));
|
|
902
|
+
if (!sets.length) throw new Error("No fields to update");
|
|
903
|
+
const node = {
|
|
904
|
+
type: "update",
|
|
905
|
+
table: this.entityMeta.tableName,
|
|
906
|
+
sets,
|
|
907
|
+
where: { logic: "AND", items: [{ column: idCol.columnName, op: "=", value: idValue }] }
|
|
908
|
+
};
|
|
909
|
+
const { sql, params } = new SqlBuilder(this.ds.dialect).build(node);
|
|
910
|
+
const result = await this.executeWithPlugins(node, sql, params);
|
|
911
|
+
return result?.affectedRows ?? result?.rowCount ?? result?.changes ?? 0;
|
|
912
|
+
}
|
|
913
|
+
async update(entity, wrapper) {
|
|
914
|
+
const sets = this.entityMeta.columns.filter((c) => c.exist && !c.isPrimary && entity[c.propertyName] !== void 0).map((c) => ({ column: c.columnName, value: entity[c.propertyName] }));
|
|
915
|
+
if (!sets.length) throw new Error("No fields to update");
|
|
916
|
+
const group = wrapper.getConditionGroup();
|
|
917
|
+
const node = {
|
|
918
|
+
type: "update",
|
|
919
|
+
table: this.entityMeta.tableName,
|
|
920
|
+
sets,
|
|
921
|
+
where: group.items.length ? group : null
|
|
922
|
+
};
|
|
923
|
+
const { sql, params } = new SqlBuilder(this.ds.dialect).build(node);
|
|
924
|
+
const result = await this.executeWithPlugins(node, sql, params);
|
|
925
|
+
return result?.affectedRows ?? result?.rowCount ?? result?.changes ?? 0;
|
|
926
|
+
}
|
|
927
|
+
// ---- 查询 ----
|
|
928
|
+
async selectById(id) {
|
|
929
|
+
const idCol = this.requireIdColumn();
|
|
930
|
+
return this.lambdaQuery().eq(idCol.propertyName, id).one();
|
|
931
|
+
}
|
|
932
|
+
async selectBatchIds(ids) {
|
|
933
|
+
if (!ids.length) return [];
|
|
934
|
+
const idCol = this.requireIdColumn();
|
|
935
|
+
return this.lambdaQuery().in(idCol.propertyName, ids).list();
|
|
936
|
+
}
|
|
937
|
+
async selectOne(wrapper) {
|
|
938
|
+
return wrapper.one();
|
|
939
|
+
}
|
|
940
|
+
async selectList(wrapper) {
|
|
941
|
+
return (wrapper ?? this.lambdaQuery()).list();
|
|
942
|
+
}
|
|
943
|
+
async selectCount(wrapper) {
|
|
944
|
+
return (wrapper ?? this.lambdaQuery()).count();
|
|
945
|
+
}
|
|
946
|
+
async selectPage(page, size, wrapper) {
|
|
947
|
+
return (wrapper ?? this.lambdaQuery()).pageResult(page, size);
|
|
948
|
+
}
|
|
949
|
+
// ---- 自定义 SQL ----
|
|
950
|
+
async rawQuery(sql, params = {}) {
|
|
951
|
+
const { parsedSql, parsedParams } = this.parseNamedParams(sql, params);
|
|
952
|
+
return this.ds.execute(parsedSql, parsedParams);
|
|
953
|
+
}
|
|
954
|
+
// ---- 内部方法 ----
|
|
955
|
+
extractColumns(entity) {
|
|
956
|
+
const cols = this.getInsertableColumns().filter((c) => entity[c.propertyName] !== void 0);
|
|
957
|
+
return {
|
|
958
|
+
columns: cols.map((c) => c.columnName),
|
|
959
|
+
values: cols.map((c) => entity[c.propertyName])
|
|
960
|
+
};
|
|
961
|
+
}
|
|
962
|
+
getInsertableColumns() {
|
|
963
|
+
return this.entityMeta.columns.filter((c) => c.exist && !(c.isPrimary && c.idType === "auto"));
|
|
964
|
+
}
|
|
965
|
+
requireIdColumn() {
|
|
966
|
+
if (!this.entityMeta.idColumn) throw new Error(`No @Id defined on ${this.entityMeta.target.name}`);
|
|
967
|
+
return this.entityMeta.idColumn;
|
|
968
|
+
}
|
|
969
|
+
parseNamedParams(sql, params) {
|
|
970
|
+
const parsedParams = [];
|
|
971
|
+
let index = 0;
|
|
972
|
+
const parsedSql = sql.replace(/#\{(\w+)\}/g, (_, key) => {
|
|
973
|
+
parsedParams.push(params[key]);
|
|
974
|
+
return this.ds.dialect.placeholder(++index);
|
|
975
|
+
});
|
|
976
|
+
return { parsedSql, parsedParams };
|
|
977
|
+
}
|
|
978
|
+
/** 通过插件链路执行 SQL */
|
|
979
|
+
executeWithPlugins(node, sql, params) {
|
|
980
|
+
if (this.ds.plugins.length) {
|
|
981
|
+
return runPlugins(this.ds, node, sql, params, this.entityMeta);
|
|
982
|
+
}
|
|
983
|
+
return this.ds.execute(sql, params);
|
|
984
|
+
}
|
|
985
|
+
};
|
|
986
|
+
export {
|
|
987
|
+
AbstractWrapper,
|
|
988
|
+
BaseMapper,
|
|
989
|
+
Column,
|
|
990
|
+
Id,
|
|
991
|
+
LambdaQueryWrapper,
|
|
992
|
+
LambdaUpdateWrapper,
|
|
993
|
+
MysqlDialect,
|
|
994
|
+
PostgresDialect,
|
|
995
|
+
SqlBuilder,
|
|
996
|
+
SqliteDialect,
|
|
997
|
+
Table,
|
|
998
|
+
Transactional,
|
|
999
|
+
createDataSource,
|
|
1000
|
+
createDialect,
|
|
1001
|
+
getDefaultDataSource,
|
|
1002
|
+
runPlugins,
|
|
1003
|
+
setDefaultDataSource,
|
|
1004
|
+
withTransaction
|
|
1005
|
+
};
|
|
1006
|
+
//# sourceMappingURL=index.mjs.map
|