@maiyunnet/kebab 4.1.0 → 5.0.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/index.d.ts +7 -2
- package/index.js +1 -1
- package/lib/db/conn.d.ts +91 -0
- package/lib/db/conn.js +328 -0
- package/lib/db/pool.d.ts +61 -0
- package/lib/db/pool.js +281 -0
- package/lib/db/tran.d.ts +33 -0
- package/lib/db/tran.js +122 -0
- package/lib/db.d.ts +35 -169
- package/lib/db.js +21 -582
- package/lib/scan.js +2 -2
- package/lib/sql.d.ts +24 -25
- package/lib/sql.js +227 -132
- package/lib/time.d.ts +1 -1
- package/lib/time.js +1 -1
- package/lib/turnstile.js +1 -1
- package/lib/vector.d.ts +9 -4
- package/lib/vector.js +46 -27
- package/package.json +6 -5
- package/sys/cmd.js +29 -6
- package/sys/mod.d.ts +8 -26
- package/sys/mod.js +108 -259
- package/www/example/ctr/test.js +119 -112
- package/www/example/mod/test.js +22 -0
package/lib/sql.js
CHANGED
|
@@ -4,7 +4,13 @@ import * as lCore from '#kebab/lib/core.js';
|
|
|
4
4
|
import * as mysql2 from 'mysql2/promise';
|
|
5
5
|
// --- 库和定义 ---
|
|
6
6
|
import * as ctr from '#kebab/sys/ctr.js';
|
|
7
|
-
/** ---
|
|
7
|
+
/** --- 服务商定义 --- */
|
|
8
|
+
export var ESERVICE;
|
|
9
|
+
(function (ESERVICE) {
|
|
10
|
+
ESERVICE[ESERVICE["MYSQL"] = 0] = "MYSQL";
|
|
11
|
+
ESERVICE[ESERVICE["PGSQL"] = 1] = "PGSQL";
|
|
12
|
+
})(ESERVICE || (ESERVICE = {}));
|
|
13
|
+
/** --- field 用 token --- */
|
|
8
14
|
let columnToken = '';
|
|
9
15
|
export class Sql {
|
|
10
16
|
// --- 实例化 ---
|
|
@@ -15,9 +21,14 @@ export class Sql {
|
|
|
15
21
|
this._sql = [];
|
|
16
22
|
/** --- 所有 data 数据 --- */
|
|
17
23
|
this._data = [];
|
|
24
|
+
/** --- 表别名列表 --- */
|
|
25
|
+
this._alias = [];
|
|
26
|
+
/** --- PostgreSQL 占位符计数器 --- */
|
|
27
|
+
this._placeholder = 1;
|
|
18
28
|
/** --- where 的 data 的开始处和结束处 --- */
|
|
19
29
|
this._whereDataPosition = [0, 0];
|
|
20
30
|
this._pre = pre ?? '';
|
|
31
|
+
this._service = opt.service ?? ESERVICE.MYSQL;
|
|
21
32
|
if (opt.data) {
|
|
22
33
|
this._data = opt.data;
|
|
23
34
|
}
|
|
@@ -32,20 +43,12 @@ export class Sql {
|
|
|
32
43
|
*/
|
|
33
44
|
insert(table) {
|
|
34
45
|
this._data = [];
|
|
46
|
+
this._placeholder = 1;
|
|
47
|
+
this._alias.length = 0;
|
|
35
48
|
const sql = 'INSERT INTO ' + this.field(table, this._pre);
|
|
36
49
|
this._sql = [sql];
|
|
37
50
|
return this;
|
|
38
51
|
}
|
|
39
|
-
/**
|
|
40
|
-
* --- 替换已经存在的唯一索引数据,不存在则插入 ---
|
|
41
|
-
* @param table 表名
|
|
42
|
-
*/
|
|
43
|
-
replace(table) {
|
|
44
|
-
this._data = [];
|
|
45
|
-
const sql = 'REPLACE INTO ' + this.field(table, this._pre);
|
|
46
|
-
this._sql = [sql];
|
|
47
|
-
return this;
|
|
48
|
-
}
|
|
49
52
|
/**
|
|
50
53
|
* --- 实际插入数据的数据 ---
|
|
51
54
|
* @param cs [] 数据列或字段列
|
|
@@ -78,48 +81,64 @@ export class Sql {
|
|
|
78
81
|
sql += 'NULL, ';
|
|
79
82
|
}
|
|
80
83
|
else if (typeof v1 === 'string' || typeof v1 === 'number') {
|
|
81
|
-
sql += '
|
|
84
|
+
sql += this.placeholder() + ', ';
|
|
82
85
|
this._data.push(v1);
|
|
83
86
|
}
|
|
84
87
|
else if (Array.isArray(v1)) {
|
|
85
|
-
if (v1[0]?.
|
|
88
|
+
if (v1[0]?.x === undefined && typeof v1[0] === 'string' &&
|
|
86
89
|
v1[0].includes('(') && v1[0].includes(')')) {
|
|
87
90
|
// --- v1: ['POINT(?)', ['20']] ---
|
|
88
|
-
sql += this.field(v1[0]) + ', ';
|
|
91
|
+
sql += this.field(v1[0].replace(/\?/g, () => this.placeholder())) + ', ';
|
|
89
92
|
if (v1[1]) {
|
|
90
93
|
this._data.push(...v1[1]);
|
|
91
94
|
}
|
|
92
95
|
}
|
|
93
|
-
else if (v1[0]?.
|
|
94
|
-
// --- v1: [
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
96
|
+
else if (v1[0]?.y !== undefined) {
|
|
97
|
+
// --- v1: [{'x': 1, 'y': 2}, { ... }, { ... }, ... ]---
|
|
98
|
+
if (this._service === ESERVICE.MYSQL) {
|
|
99
|
+
// --- MYSQL ---
|
|
100
|
+
sql += `ST_POLYGONFROMTEXT(${this.placeholder()}), `;
|
|
101
|
+
this._data.push(`POLYGON((${v1.map(item => {
|
|
102
|
+
return `${item.x} ${item.y}`;
|
|
103
|
+
}).join(', ')}))`);
|
|
104
|
+
}
|
|
105
|
+
else {
|
|
106
|
+
// --- PGSQL ---
|
|
107
|
+
sql += `${this.placeholder()}, `;
|
|
108
|
+
this._data.push(`(${v1.map(item => {
|
|
109
|
+
return `(${item.x}, ${item.y})`;
|
|
110
|
+
}).join(', ')})`);
|
|
111
|
+
}
|
|
101
112
|
}
|
|
102
113
|
else {
|
|
103
114
|
// --- v1: json ---
|
|
104
|
-
sql += '
|
|
115
|
+
sql += this.placeholder() + ', ';
|
|
105
116
|
this._data.push(lText.stringifyJson(v1));
|
|
106
117
|
}
|
|
107
118
|
}
|
|
108
119
|
else if (v1.x !== undefined) {
|
|
109
120
|
if (v1.y !== undefined) {
|
|
110
121
|
// --- v1: {'x': 1, 'y': 2} ---
|
|
111
|
-
|
|
112
|
-
|
|
122
|
+
if (this._service === ESERVICE.MYSQL) {
|
|
123
|
+
// --- MYSQL ---
|
|
124
|
+
sql += `ST_POINTFROMTEXT(${this.placeholder()}), `;
|
|
125
|
+
this._data.push(`POINT(${v1.x} ${v1.y})`);
|
|
126
|
+
}
|
|
127
|
+
else {
|
|
128
|
+
// --- PGSQL ---
|
|
129
|
+
sql += `${this.placeholder()}, `;
|
|
130
|
+
this._data.push(`(${v1.x}, ${v1.y})`);
|
|
131
|
+
}
|
|
113
132
|
}
|
|
114
133
|
else {
|
|
115
134
|
// --- v1: json ---
|
|
116
|
-
sql += '
|
|
135
|
+
sql += this.placeholder() + ', ';
|
|
117
136
|
this._data.push(lText.stringifyJson(v1));
|
|
118
137
|
}
|
|
119
138
|
}
|
|
120
139
|
else if (v1 instanceof Buffer) {
|
|
121
140
|
// --- Buffer ---
|
|
122
|
-
sql += '
|
|
141
|
+
sql += this.placeholder() + ', ';
|
|
123
142
|
this._data.push(v);
|
|
124
143
|
}
|
|
125
144
|
else if (this._isField(v1)) {
|
|
@@ -128,7 +147,7 @@ export class Sql {
|
|
|
128
147
|
}
|
|
129
148
|
else {
|
|
130
149
|
// --- json ---
|
|
131
|
-
sql += '
|
|
150
|
+
sql += this.placeholder() + ', ';
|
|
132
151
|
this._data.push(lText.stringifyJson(v1));
|
|
133
152
|
}
|
|
134
153
|
}
|
|
@@ -152,48 +171,64 @@ export class Sql {
|
|
|
152
171
|
values += 'NULL, ';
|
|
153
172
|
}
|
|
154
173
|
else if (typeof v === 'string' || typeof v === 'number') {
|
|
155
|
-
values += '
|
|
174
|
+
values += this.placeholder() + ', ';
|
|
156
175
|
this._data.push(v);
|
|
157
176
|
}
|
|
158
177
|
else if (Array.isArray(v)) {
|
|
159
|
-
if (v[0]?.
|
|
178
|
+
if (v[0]?.x === undefined && typeof v[0] === 'string' &&
|
|
160
179
|
v[0].includes('(') && v[0].includes(')')) {
|
|
161
180
|
// --- v: ['POINT(?)', ['20']] ---
|
|
162
|
-
values += this.field(v[0]) + ', ';
|
|
181
|
+
values += this.field(v[0].replace(/\?/g, () => this.placeholder())) + ', ';
|
|
163
182
|
if (v[1] !== undefined) {
|
|
164
183
|
this._data.push(...v[1]);
|
|
165
184
|
}
|
|
166
185
|
}
|
|
167
|
-
else if (v[0]?.
|
|
168
|
-
// --- v: [
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
186
|
+
else if (v[0]?.y !== undefined) {
|
|
187
|
+
// --- v: [{'x': 1, 'y': 2}, { ... }, { ... }, ... ]---
|
|
188
|
+
if (this._service === ESERVICE.MYSQL) {
|
|
189
|
+
// --- MYSQL ---
|
|
190
|
+
values += `ST_POLYGONFROMTEXT(${this.placeholder()}), `;
|
|
191
|
+
this._data.push(`POLYGON((${v.map(item => {
|
|
192
|
+
return `${item.x} ${item.y}`;
|
|
193
|
+
}).join(', ')}))`);
|
|
194
|
+
}
|
|
195
|
+
else {
|
|
196
|
+
// --- PGSQL ---
|
|
197
|
+
values += `${this.placeholder()}, `;
|
|
198
|
+
this._data.push(`(${v.map(item => {
|
|
199
|
+
return `(${item.x}, ${item.y})`;
|
|
200
|
+
}).join(', ')})`);
|
|
201
|
+
}
|
|
175
202
|
}
|
|
176
203
|
else {
|
|
177
204
|
// --- v: json ---
|
|
178
|
-
values += '
|
|
205
|
+
values += this.placeholder() + ', ';
|
|
179
206
|
this._data.push(lText.stringifyJson(v));
|
|
180
207
|
}
|
|
181
208
|
}
|
|
182
209
|
else if (v.x !== undefined) {
|
|
183
210
|
if (v.y !== undefined) {
|
|
184
211
|
// --- v: {'x': 1, 'y': 2} ---
|
|
185
|
-
|
|
186
|
-
|
|
212
|
+
if (this._service === ESERVICE.MYSQL) {
|
|
213
|
+
// --- MYSQL ---
|
|
214
|
+
values += `ST_POINTFROMTEXT(${this.placeholder()}), `;
|
|
215
|
+
this._data.push(`POINT(${v.x} ${v.y})`);
|
|
216
|
+
}
|
|
217
|
+
else {
|
|
218
|
+
// --- PGSQL ---
|
|
219
|
+
values += `${this.placeholder()}, `;
|
|
220
|
+
this._data.push(`(${v.x}, ${v.y})`);
|
|
221
|
+
}
|
|
187
222
|
}
|
|
188
223
|
else {
|
|
189
224
|
// --- v: json ---
|
|
190
|
-
values += '
|
|
225
|
+
values += this.placeholder() + ', ';
|
|
191
226
|
this._data.push(lText.stringifyJson(v));
|
|
192
227
|
}
|
|
193
228
|
}
|
|
194
229
|
else if (v instanceof Buffer) {
|
|
195
230
|
// --- Buffer ---
|
|
196
|
-
values += '
|
|
231
|
+
values += this.placeholder() + ', ';
|
|
197
232
|
this._data.push(v);
|
|
198
233
|
}
|
|
199
234
|
else if (this._isField(v)) {
|
|
@@ -202,7 +237,7 @@ export class Sql {
|
|
|
202
237
|
}
|
|
203
238
|
else {
|
|
204
239
|
// --- json ---
|
|
205
|
-
values += '
|
|
240
|
+
values += this.placeholder() + ', ';
|
|
206
241
|
this._data.push(lText.stringifyJson(v));
|
|
207
242
|
}
|
|
208
243
|
}
|
|
@@ -211,46 +246,6 @@ export class Sql {
|
|
|
211
246
|
this._sql.push(sql);
|
|
212
247
|
return this;
|
|
213
248
|
}
|
|
214
|
-
/**
|
|
215
|
-
* --- 不存在则插入,衔接在 insert 之后 ---
|
|
216
|
-
* @param table 表名
|
|
217
|
-
* @param insert {'xx': 'xx', 'xx': 'xx'}
|
|
218
|
-
* @param where [{'xx': 'xx', 'xx': 'xx'}], {'xx': 'xx'}
|
|
219
|
-
*/
|
|
220
|
-
notExists(table, insert, where) {
|
|
221
|
-
let sql = '(';
|
|
222
|
-
const values = [];
|
|
223
|
-
for (const field in insert) {
|
|
224
|
-
const val = insert[field];
|
|
225
|
-
sql += this.field(field) + ', ';
|
|
226
|
-
values.push(val);
|
|
227
|
-
}
|
|
228
|
-
sql = sql.slice(0, -2) + ') SELECT ';
|
|
229
|
-
for (const value of values) {
|
|
230
|
-
if (Array.isArray(value)) {
|
|
231
|
-
sql += value[0] + ', ';
|
|
232
|
-
this._data.push(...value[1]);
|
|
233
|
-
}
|
|
234
|
-
else {
|
|
235
|
-
sql += '?, ';
|
|
236
|
-
this._data.push(value);
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
sql = sql.slice(0, -2) + ' FROM DUAL WHERE NOT EXISTS (SELECT `id` FROM ' + this.field(table, this._pre) + ' WHERE ' + this._whereSub(where) + ')';
|
|
240
|
-
this._sql.push(sql);
|
|
241
|
-
return this;
|
|
242
|
-
}
|
|
243
|
-
/**
|
|
244
|
-
* --- 当不能 insert 时,update(仅能配合 insert 方法用) ---
|
|
245
|
-
* @param s 更新数据
|
|
246
|
-
*/
|
|
247
|
-
duplicate(s) {
|
|
248
|
-
if (Array.isArray(s) ? s.length : Object.keys(s).length) {
|
|
249
|
-
const sql = ' ON DUPLICATE KEY UPDATE ' + this._updateSub(s);
|
|
250
|
-
this._sql.push(sql);
|
|
251
|
-
}
|
|
252
|
-
return this;
|
|
253
|
-
}
|
|
254
249
|
/**
|
|
255
250
|
* --- '*', 'xx' ---
|
|
256
251
|
* @param c 字段字符串或字段数组
|
|
@@ -267,7 +262,7 @@ export class Sql {
|
|
|
267
262
|
for (const i of c) {
|
|
268
263
|
if (Array.isArray(i)) {
|
|
269
264
|
// --- i: ['xx', ['x']] ---
|
|
270
|
-
sql += this.field(i[0]) + ', ';
|
|
265
|
+
sql += this.field(i[0].replace(/\?/g, () => this.placeholder())) + ', ';
|
|
271
266
|
this._data.push(...i[1]);
|
|
272
267
|
}
|
|
273
268
|
else {
|
|
@@ -335,10 +330,10 @@ export class Sql {
|
|
|
335
330
|
}
|
|
336
331
|
else {
|
|
337
332
|
if (v[1] === '=') {
|
|
338
|
-
sql += this.field(v[0]) + ' =
|
|
333
|
+
sql += this.field(v[0]) + ' = ' + this.placeholder() + ', ';
|
|
339
334
|
}
|
|
340
335
|
else {
|
|
341
|
-
sql += this.field(v[0]) + ' = ' + this.field(v[0]) + ' ' + v[1] + '
|
|
336
|
+
sql += this.field(v[0]) + ' = ' + this.field(v[0]) + ' ' + v[1] + ' ' + this.placeholder() + ', ';
|
|
342
337
|
}
|
|
343
338
|
this._data.push(nv);
|
|
344
339
|
}
|
|
@@ -356,11 +351,11 @@ export class Sql {
|
|
|
356
351
|
}
|
|
357
352
|
else if (typeof v === 'string' || typeof v === 'number') {
|
|
358
353
|
// --- 2 ---
|
|
359
|
-
sql += '
|
|
354
|
+
sql += this.placeholder() + ', ';
|
|
360
355
|
this._data.push(v);
|
|
361
356
|
}
|
|
362
357
|
else if (Array.isArray(v)) {
|
|
363
|
-
if (v[0]?.
|
|
358
|
+
if (v[0]?.x === undefined && typeof v[0] === 'string' &&
|
|
364
359
|
v[0].includes('(') && v[0].includes(')')) {
|
|
365
360
|
// --- 4, 5: ['(CASE `id` WHEN 1 THEN ? WHEN 2 THEN ? END)', ['val1', 'val2']] ---
|
|
366
361
|
sql += this.field(v[0]) + ', ';
|
|
@@ -368,26 +363,42 @@ export class Sql {
|
|
|
368
363
|
this._data.push(...v[1]);
|
|
369
364
|
}
|
|
370
365
|
}
|
|
371
|
-
else if (v[0]?.
|
|
366
|
+
else if (v[0]?.y !== undefined) {
|
|
372
367
|
// --- 7 ---
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
368
|
+
if (this._service === ESERVICE.MYSQL) {
|
|
369
|
+
// --- MYSQL ---
|
|
370
|
+
sql += `ST_POLYGONFROMTEXT(${this.placeholder()}), `;
|
|
371
|
+
this._data.push(`POLYGON((${v.map(item => {
|
|
372
|
+
return `${item.x} ${item.y}`;
|
|
373
|
+
}).join(', ')}))`);
|
|
374
|
+
}
|
|
375
|
+
else {
|
|
376
|
+
// --- PGSQL ---
|
|
377
|
+
sql += `${this.placeholder()}, `;
|
|
378
|
+
this._data.push(`(${v.map(item => {
|
|
379
|
+
return `(${item.x}, ${item.y})`;
|
|
380
|
+
}).join(', ')})`);
|
|
381
|
+
}
|
|
379
382
|
}
|
|
380
383
|
else {
|
|
381
384
|
// --- v: json ---
|
|
382
|
-
sql += '
|
|
385
|
+
sql += this.placeholder() + ', ';
|
|
383
386
|
this._data.push(lText.stringifyJson(v));
|
|
384
387
|
}
|
|
385
388
|
}
|
|
386
389
|
else if (v.x !== undefined) {
|
|
387
390
|
if (v.y !== undefined) {
|
|
388
391
|
// --- 6: v: {'x': 1, 'y': 2} ---
|
|
389
|
-
|
|
390
|
-
|
|
392
|
+
if (this._service === ESERVICE.MYSQL) {
|
|
393
|
+
// --- MYSQL ---
|
|
394
|
+
sql += `ST_POINTFROMTEXT(${this.placeholder()}), `;
|
|
395
|
+
this._data.push(`POINT(${v.x} ${v.y})`);
|
|
396
|
+
}
|
|
397
|
+
else {
|
|
398
|
+
// --- PGSQL ---
|
|
399
|
+
sql += `${this.placeholder()}, `;
|
|
400
|
+
this._data.push(`(${v.x}, ${v.y})`);
|
|
401
|
+
}
|
|
391
402
|
}
|
|
392
403
|
else {
|
|
393
404
|
// --- v: json ---
|
|
@@ -397,14 +408,14 @@ export class Sql {
|
|
|
397
408
|
}
|
|
398
409
|
else {
|
|
399
410
|
// --- 8 ---
|
|
400
|
-
sql += '
|
|
411
|
+
sql += this.placeholder() + ', ';
|
|
401
412
|
this._data.push(lText.stringifyJson(v));
|
|
402
413
|
}
|
|
403
414
|
}
|
|
404
415
|
}
|
|
405
416
|
else if (v instanceof Buffer) {
|
|
406
417
|
// --- Buffer ---
|
|
407
|
-
sql += '
|
|
418
|
+
sql += this.placeholder() + ', ';
|
|
408
419
|
this._data.push(v);
|
|
409
420
|
}
|
|
410
421
|
else if (this._isField(v)) {
|
|
@@ -413,7 +424,7 @@ export class Sql {
|
|
|
413
424
|
}
|
|
414
425
|
else {
|
|
415
426
|
// --- json ---
|
|
416
|
-
sql += '
|
|
427
|
+
sql += this.placeholder() + ', ';
|
|
417
428
|
this._data.push(lText.stringifyJson(v));
|
|
418
429
|
}
|
|
419
430
|
}
|
|
@@ -616,7 +627,7 @@ export class Sql {
|
|
|
616
627
|
// --- 3 ---
|
|
617
628
|
sql += this.field(v[0]) + ' ' + v[1].toUpperCase() + ' (';
|
|
618
629
|
for (const v1 of v[2]) {
|
|
619
|
-
sql += '
|
|
630
|
+
sql += this.placeholder() + ', ';
|
|
620
631
|
data.push(v1);
|
|
621
632
|
}
|
|
622
633
|
sql = sql.slice(0, -2) + ') AND ';
|
|
@@ -630,7 +641,7 @@ export class Sql {
|
|
|
630
641
|
sql += this.field(v[0]) + ' ' + v[1] + ' ' + this.field(nv.value) + ' AND ';
|
|
631
642
|
}
|
|
632
643
|
else {
|
|
633
|
-
sql += this.field(v[0]) + ' ' + v[1] + '
|
|
644
|
+
sql += this.field(v[0]) + ' ' + v[1] + ' ' + this.placeholder() + ' AND ';
|
|
634
645
|
data.push(nv);
|
|
635
646
|
}
|
|
636
647
|
}
|
|
@@ -660,7 +671,7 @@ export class Sql {
|
|
|
660
671
|
}
|
|
661
672
|
else if (typeof v === 'string' || typeof v === 'number') {
|
|
662
673
|
// --- 1 ---
|
|
663
|
-
sql += this.field(k) + ' =
|
|
674
|
+
sql += this.field(k) + ' = ' + this.placeholder() + ' AND ';
|
|
664
675
|
data.push(v);
|
|
665
676
|
}
|
|
666
677
|
else if (this._isField(v)) {
|
|
@@ -672,7 +683,7 @@ export class Sql {
|
|
|
672
683
|
if (v.length > 0) {
|
|
673
684
|
sql += this.field(k) + ' IN (';
|
|
674
685
|
for (const v1 of v) {
|
|
675
|
-
sql += '
|
|
686
|
+
sql += this.placeholder() + ', ';
|
|
676
687
|
data.push(v1);
|
|
677
688
|
}
|
|
678
689
|
sql = sql.slice(0, -2) + ') AND ';
|
|
@@ -732,12 +743,19 @@ export class Sql {
|
|
|
732
743
|
return this;
|
|
733
744
|
}
|
|
734
745
|
/**
|
|
735
|
-
* --- LIMIT ---
|
|
736
|
-
* @param a
|
|
737
|
-
* @param b
|
|
746
|
+
* --- LIMIT(limit、offset, limit) ---
|
|
747
|
+
* @param a 起始(offset)
|
|
748
|
+
* @param b 长度(limit)
|
|
738
749
|
*/
|
|
739
750
|
limit(a, b = 0) {
|
|
740
|
-
|
|
751
|
+
if (b) {
|
|
752
|
+
// --- offset, limit ---
|
|
753
|
+
this._sql.push(` LIMIT ${b} OFFSET ${a}`);
|
|
754
|
+
}
|
|
755
|
+
else {
|
|
756
|
+
// --- limit ---
|
|
757
|
+
this._sql.push(` LIMIT ${a}`);
|
|
758
|
+
}
|
|
741
759
|
return this;
|
|
742
760
|
}
|
|
743
761
|
/**
|
|
@@ -816,7 +834,7 @@ export class Sql {
|
|
|
816
834
|
}
|
|
817
835
|
return get(this.getPre(), {
|
|
818
836
|
'data': data,
|
|
819
|
-
'sql': sql
|
|
837
|
+
'sql': sql,
|
|
820
838
|
});
|
|
821
839
|
}
|
|
822
840
|
// --- 操作 ---
|
|
@@ -824,7 +842,16 @@ export class Sql {
|
|
|
824
842
|
* --- 获取 sql 语句 ---
|
|
825
843
|
*/
|
|
826
844
|
getSql() {
|
|
827
|
-
|
|
845
|
+
let sql = this._sql.join('');
|
|
846
|
+
if (this._pre) {
|
|
847
|
+
return this._alias.reduce((result, item) => {
|
|
848
|
+
if (this._service === ESERVICE.MYSQL) {
|
|
849
|
+
return result.replace(new RegExp('`' + this._pre + item + '`', 'g'), '`' + item + '`');
|
|
850
|
+
}
|
|
851
|
+
return result.replace(new RegExp(`"${this._pre}"."${item}"`, 'g'), '"' + item + '"');
|
|
852
|
+
}, sql);
|
|
853
|
+
}
|
|
854
|
+
return sql;
|
|
828
855
|
}
|
|
829
856
|
/**
|
|
830
857
|
* --- 获取全部 data ---
|
|
@@ -844,7 +871,7 @@ export class Sql {
|
|
|
844
871
|
* @param data
|
|
845
872
|
*/
|
|
846
873
|
format(sql, data) {
|
|
847
|
-
return
|
|
874
|
+
return format(sql ?? this.getSql(), data ?? this.getData(), this._service);
|
|
848
875
|
}
|
|
849
876
|
// --- 特殊方法 ---
|
|
850
877
|
/**
|
|
@@ -855,15 +882,20 @@ export class Sql {
|
|
|
855
882
|
this._sql.push(sql);
|
|
856
883
|
return this;
|
|
857
884
|
}
|
|
885
|
+
/** --- 获取占位符 --- */
|
|
886
|
+
placeholder() {
|
|
887
|
+
return this._service === ESERVICE.MYSQL ? '?' : `$${this._placeholder++}`;
|
|
888
|
+
}
|
|
858
889
|
/**
|
|
859
890
|
* --- 对字段进行包裹 ---
|
|
860
891
|
* @param str
|
|
861
892
|
* @param pre 表前缀,仅请在 field 表名时倒入前缀
|
|
862
|
-
* @param suf 表后缀,仅请在 field 表名时倒入后缀,前面加 # 代表要强制 AS
|
|
893
|
+
* @param suf 表后缀,仅请在 field 表名时倒入后缀,前面加 # 代表要强制 AS,可能是分表查询时用
|
|
863
894
|
*/
|
|
864
895
|
field(str, pre = '', suf = '') {
|
|
865
896
|
let left = '';
|
|
866
897
|
let right = '';
|
|
898
|
+
const q = this._service === ESERVICE.MYSQL ? '`' : '"';
|
|
867
899
|
if (Array.isArray(str)) {
|
|
868
900
|
this._data.push(...str[1]);
|
|
869
901
|
return this.field(str[0]);
|
|
@@ -896,7 +928,7 @@ export class Sql {
|
|
|
896
928
|
}
|
|
897
929
|
if (spacePos !== -1) {
|
|
898
930
|
const spaceRight = str.slice(spacePos + 1);
|
|
899
|
-
if (/^[a-zA-Z_`][\w`]*$/.test(spaceRight)) {
|
|
931
|
+
if (/^[a-zA-Z_`"][\w`"]*$/.test(spaceRight)) {
|
|
900
932
|
// --- OK ---
|
|
901
933
|
left = str.slice(0, spacePos);
|
|
902
934
|
right = spaceRight;
|
|
@@ -918,46 +950,87 @@ export class Sql {
|
|
|
918
950
|
}
|
|
919
951
|
if (right) {
|
|
920
952
|
// --- 处理右侧 ---
|
|
921
|
-
if (
|
|
922
|
-
right
|
|
953
|
+
if (this._service === ESERVICE.MYSQL) {
|
|
954
|
+
if (right.startsWith('`')) {
|
|
955
|
+
if (!left.includes('.')) {
|
|
956
|
+
// --- 存储表别名 ---
|
|
957
|
+
this._alias.push(right.slice(1, -1));
|
|
958
|
+
}
|
|
959
|
+
right = '`' + pre + right.slice(1);
|
|
960
|
+
}
|
|
961
|
+
else {
|
|
962
|
+
if (!left.includes('.')) {
|
|
963
|
+
// --- 存储表别名 ---
|
|
964
|
+
this._alias.push(right);
|
|
965
|
+
}
|
|
966
|
+
right = '`' + pre + right + '`';
|
|
967
|
+
}
|
|
968
|
+
right = ' AS ' + right;
|
|
923
969
|
}
|
|
924
970
|
else {
|
|
925
|
-
right
|
|
971
|
+
if (right.startsWith('"')) {
|
|
972
|
+
if (!left.includes('.')) {
|
|
973
|
+
// --- 存储表别名 ---
|
|
974
|
+
this._alias.push(right.slice(1, -1));
|
|
975
|
+
}
|
|
976
|
+
if (pre) {
|
|
977
|
+
right = `"${pre}".${right}`;
|
|
978
|
+
}
|
|
979
|
+
}
|
|
980
|
+
else {
|
|
981
|
+
if (!left.includes('.')) {
|
|
982
|
+
// --- 存储表别名 ---
|
|
983
|
+
this._alias.push(right);
|
|
984
|
+
}
|
|
985
|
+
right = (pre ? `"${pre}".` : '') + `"${right}"`;
|
|
986
|
+
}
|
|
987
|
+
right = ' AS ' + right;
|
|
926
988
|
}
|
|
927
|
-
right = ' AS ' + right;
|
|
928
989
|
}
|
|
929
990
|
else {
|
|
930
991
|
// --- 没有右侧 ---
|
|
931
992
|
if (sufAs) {
|
|
932
993
|
// --- 强制 AS ---
|
|
994
|
+
if (!left.includes('.')) {
|
|
995
|
+
// --- 存储表别名 ---
|
|
996
|
+
this._alias.push(left.startsWith('`') || left.startsWith('"') ? left.slice(1, -1) : left);
|
|
997
|
+
}
|
|
933
998
|
right = ' AS ' + this.field(left, pre);
|
|
934
999
|
}
|
|
935
1000
|
}
|
|
936
1001
|
// --- 处理 left ---
|
|
937
|
-
if (/^[\w`_.*]+$/.test(left)) {
|
|
1002
|
+
if (/^[\w`"_.*]+$/.test(left)) {
|
|
938
1003
|
const l = left.split('.');
|
|
939
1004
|
if (l[0] === '*') {
|
|
940
1005
|
return '*' + right;
|
|
941
1006
|
}
|
|
942
|
-
if (l[0].startsWith('`')) {
|
|
943
|
-
l[0] = l[0].replace(
|
|
1007
|
+
if (l[0].startsWith('`') || l[0].startsWith(`"`)) {
|
|
1008
|
+
l[0] = l[0].replace(/[`"]/g, '');
|
|
944
1009
|
}
|
|
945
1010
|
if (l[1] === undefined) {
|
|
946
1011
|
// --- xxx ---
|
|
947
1012
|
if (/^[A-Z0-9_]+$/.test(l[0])) {
|
|
948
|
-
// --- 纯大写是内置函数,不能加 ` ---
|
|
1013
|
+
// --- 纯大写是内置函数,不能加 `" ---
|
|
949
1014
|
return l[0] + right;
|
|
950
1015
|
}
|
|
951
|
-
return
|
|
1016
|
+
return this._service === ESERVICE.MYSQL ?
|
|
1017
|
+
'`' + pre + l[0] + suf + '`' + right :
|
|
1018
|
+
(pre ? `"${pre}".` : '') + '"' + l[0] + suf + '"' + right;
|
|
952
1019
|
}
|
|
953
1020
|
// --- x.xxx ---
|
|
954
1021
|
// --- 只有在此模式才知道 . 前面的一定是表名,因此自动加 sql 级的 _pre ---
|
|
955
|
-
const w = l[1] === '*'
|
|
956
|
-
|
|
1022
|
+
const w = l[1] === '*'
|
|
1023
|
+
? '*' :
|
|
1024
|
+
(q + ((l[1].startsWith('`') || l[1].startsWith('"')) ?
|
|
1025
|
+
l[1].slice(1, -1) :
|
|
1026
|
+
l[1]) + q);
|
|
1027
|
+
return this._service === ESERVICE.MYSQL ?
|
|
1028
|
+
'`' + this._pre + l[0] + suf + '`.' + w + right :
|
|
1029
|
+
(this._pre ? `"${this._pre}".` : '') + '"' + l[0] + suf + '".' + w + right;
|
|
957
1030
|
}
|
|
958
1031
|
else {
|
|
959
|
-
// return left.replace(/([(, ])([a-zA-Z`_][\w`_.]*)(?=[), ])/g, (
|
|
960
|
-
return left.replace(/(^|[(, ])([a-zA-Z`_][\w`_.]*)(?=[), ]|$)/g, (t, t1, t2) => {
|
|
1032
|
+
// return left.replace(/([(, ])([a-zA-Z`"_][\w`"_.]*)(?=[), ])/g, (
|
|
1033
|
+
return left.replace(/(^|[(, ])([a-zA-Z`"_][\w`"_.]*)(?=[), ]|$)/g, (t, t1, t2) => {
|
|
961
1034
|
return t1 + this.field(t2, pre, suf);
|
|
962
1035
|
}) + right;
|
|
963
1036
|
}
|
|
@@ -982,12 +1055,34 @@ export function get(ctrPre, opt = {}) {
|
|
|
982
1055
|
return new Sql(ctrPre instanceof ctr.Ctr ? ctrPre.getPrototype('_config').sql.pre : ctrPre, opt);
|
|
983
1056
|
}
|
|
984
1057
|
/**
|
|
985
|
-
* --- 返回代入后的完整 SQL
|
|
1058
|
+
* --- 返回代入后的完整 SQL 字符串,这并不安全不能直接执行,只是用来调试打印 sql 语句 ---
|
|
986
1059
|
* @param sql SQL 字符串
|
|
987
1060
|
* @param data DATA 数据
|
|
1061
|
+
* @param service 服务商,默认 MySQL
|
|
988
1062
|
*/
|
|
989
|
-
export function format(sql, data) {
|
|
990
|
-
|
|
1063
|
+
export function format(sql, data, service = ESERVICE.MYSQL) {
|
|
1064
|
+
if (service === ESERVICE.MYSQL) {
|
|
1065
|
+
return mysql2.format(sql, data);
|
|
1066
|
+
}
|
|
1067
|
+
// --- PGSQL ---
|
|
1068
|
+
// --- PostgreSQL 手动替换占位符 ---
|
|
1069
|
+
let index = 0;
|
|
1070
|
+
return sql.replace(/\$\d+/g, () => {
|
|
1071
|
+
const val = data[index++];
|
|
1072
|
+
if (val === null) {
|
|
1073
|
+
return 'NULL';
|
|
1074
|
+
}
|
|
1075
|
+
if (typeof val === 'string') {
|
|
1076
|
+
return `'${lText.stringifyJson(val).slice(1, -1).replace(/'/g, "''").replace(/\\"/g, '"')}'`;
|
|
1077
|
+
}
|
|
1078
|
+
if (typeof val === 'number') {
|
|
1079
|
+
return val.toString();
|
|
1080
|
+
}
|
|
1081
|
+
if (val instanceof Buffer) {
|
|
1082
|
+
return `'\\x${val.toString('hex')}'`;
|
|
1083
|
+
}
|
|
1084
|
+
return `'${JSON.stringify(val).replace(/'/g, "''")}'`;
|
|
1085
|
+
});
|
|
991
1086
|
}
|
|
992
1087
|
/**
|
|
993
1088
|
* --- 将数组兑换为组合的对象(Array/Object mix) ---
|
package/lib/time.d.ts
CHANGED
|
@@ -70,6 +70,6 @@ export declare function isMs(time: number): boolean;
|
|
|
70
70
|
* --- 将时间对象转换为时间字符串 ---
|
|
71
71
|
* @param zone 时区小时或 ctr 对象,如 8,设置 null 则以系统时区为准
|
|
72
72
|
* @param f 转换格式
|
|
73
|
-
* @param date
|
|
73
|
+
* @param date 时间对象秒/毫秒级数字均可
|
|
74
74
|
*/
|
|
75
75
|
export declare function format(zone: number | sCtr.Ctr | null, f: string, date?: Date | number): string;
|