@maiyunnet/kebab 4.1.0 → 5.0.1
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 +230 -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 +110 -261
- package/www/example/ctr/test.js +119 -112
- package/www/example/data/test.zip +0 -0
- 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 字段字符串或字段数组
|
|
@@ -258,6 +253,7 @@ export class Sql {
|
|
|
258
253
|
*/
|
|
259
254
|
select(c, f) {
|
|
260
255
|
this._data = [];
|
|
256
|
+
this._placeholder = 1;
|
|
261
257
|
let sql = 'SELECT ';
|
|
262
258
|
if (typeof c === 'string') {
|
|
263
259
|
sql += this.field(c);
|
|
@@ -267,7 +263,7 @@ export class Sql {
|
|
|
267
263
|
for (const i of c) {
|
|
268
264
|
if (Array.isArray(i)) {
|
|
269
265
|
// --- i: ['xx', ['x']] ---
|
|
270
|
-
sql += this.field(i[0]) + ', ';
|
|
266
|
+
sql += this.field(i[0].replace(/\?/g, () => this.placeholder())) + ', ';
|
|
271
267
|
this._data.push(...i[1]);
|
|
272
268
|
}
|
|
273
269
|
else {
|
|
@@ -297,6 +293,7 @@ export class Sql {
|
|
|
297
293
|
*/
|
|
298
294
|
update(f, s) {
|
|
299
295
|
this._data = [];
|
|
296
|
+
this._placeholder = 1;
|
|
300
297
|
const sql = `UPDATE ${this.field(f, this._pre)} SET ${this._updateSub(s)}`;
|
|
301
298
|
this._sql = [sql];
|
|
302
299
|
return this;
|
|
@@ -335,10 +332,10 @@ export class Sql {
|
|
|
335
332
|
}
|
|
336
333
|
else {
|
|
337
334
|
if (v[1] === '=') {
|
|
338
|
-
sql += this.field(v[0]) + ' =
|
|
335
|
+
sql += this.field(v[0]) + ' = ' + this.placeholder() + ', ';
|
|
339
336
|
}
|
|
340
337
|
else {
|
|
341
|
-
sql += this.field(v[0]) + ' = ' + this.field(v[0]) + ' ' + v[1] + '
|
|
338
|
+
sql += this.field(v[0]) + ' = ' + this.field(v[0]) + ' ' + v[1] + ' ' + this.placeholder() + ', ';
|
|
342
339
|
}
|
|
343
340
|
this._data.push(nv);
|
|
344
341
|
}
|
|
@@ -356,11 +353,11 @@ export class Sql {
|
|
|
356
353
|
}
|
|
357
354
|
else if (typeof v === 'string' || typeof v === 'number') {
|
|
358
355
|
// --- 2 ---
|
|
359
|
-
sql += '
|
|
356
|
+
sql += this.placeholder() + ', ';
|
|
360
357
|
this._data.push(v);
|
|
361
358
|
}
|
|
362
359
|
else if (Array.isArray(v)) {
|
|
363
|
-
if (v[0]?.
|
|
360
|
+
if (v[0]?.x === undefined && typeof v[0] === 'string' &&
|
|
364
361
|
v[0].includes('(') && v[0].includes(')')) {
|
|
365
362
|
// --- 4, 5: ['(CASE `id` WHEN 1 THEN ? WHEN 2 THEN ? END)', ['val1', 'val2']] ---
|
|
366
363
|
sql += this.field(v[0]) + ', ';
|
|
@@ -368,26 +365,42 @@ export class Sql {
|
|
|
368
365
|
this._data.push(...v[1]);
|
|
369
366
|
}
|
|
370
367
|
}
|
|
371
|
-
else if (v[0]?.
|
|
368
|
+
else if (v[0]?.y !== undefined) {
|
|
372
369
|
// --- 7 ---
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
370
|
+
if (this._service === ESERVICE.MYSQL) {
|
|
371
|
+
// --- MYSQL ---
|
|
372
|
+
sql += `ST_POLYGONFROMTEXT(${this.placeholder()}), `;
|
|
373
|
+
this._data.push(`POLYGON((${v.map(item => {
|
|
374
|
+
return `${item.x} ${item.y}`;
|
|
375
|
+
}).join(', ')}))`);
|
|
376
|
+
}
|
|
377
|
+
else {
|
|
378
|
+
// --- PGSQL ---
|
|
379
|
+
sql += `${this.placeholder()}, `;
|
|
380
|
+
this._data.push(`(${v.map(item => {
|
|
381
|
+
return `(${item.x}, ${item.y})`;
|
|
382
|
+
}).join(', ')})`);
|
|
383
|
+
}
|
|
379
384
|
}
|
|
380
385
|
else {
|
|
381
386
|
// --- v: json ---
|
|
382
|
-
sql += '
|
|
387
|
+
sql += this.placeholder() + ', ';
|
|
383
388
|
this._data.push(lText.stringifyJson(v));
|
|
384
389
|
}
|
|
385
390
|
}
|
|
386
391
|
else if (v.x !== undefined) {
|
|
387
392
|
if (v.y !== undefined) {
|
|
388
393
|
// --- 6: v: {'x': 1, 'y': 2} ---
|
|
389
|
-
|
|
390
|
-
|
|
394
|
+
if (this._service === ESERVICE.MYSQL) {
|
|
395
|
+
// --- MYSQL ---
|
|
396
|
+
sql += `ST_POINTFROMTEXT(${this.placeholder()}), `;
|
|
397
|
+
this._data.push(`POINT(${v.x} ${v.y})`);
|
|
398
|
+
}
|
|
399
|
+
else {
|
|
400
|
+
// --- PGSQL ---
|
|
401
|
+
sql += `${this.placeholder()}, `;
|
|
402
|
+
this._data.push(`(${v.x}, ${v.y})`);
|
|
403
|
+
}
|
|
391
404
|
}
|
|
392
405
|
else {
|
|
393
406
|
// --- v: json ---
|
|
@@ -397,14 +410,14 @@ export class Sql {
|
|
|
397
410
|
}
|
|
398
411
|
else {
|
|
399
412
|
// --- 8 ---
|
|
400
|
-
sql += '
|
|
413
|
+
sql += this.placeholder() + ', ';
|
|
401
414
|
this._data.push(lText.stringifyJson(v));
|
|
402
415
|
}
|
|
403
416
|
}
|
|
404
417
|
}
|
|
405
418
|
else if (v instanceof Buffer) {
|
|
406
419
|
// --- Buffer ---
|
|
407
|
-
sql += '
|
|
420
|
+
sql += this.placeholder() + ', ';
|
|
408
421
|
this._data.push(v);
|
|
409
422
|
}
|
|
410
423
|
else if (this._isField(v)) {
|
|
@@ -413,7 +426,7 @@ export class Sql {
|
|
|
413
426
|
}
|
|
414
427
|
else {
|
|
415
428
|
// --- json ---
|
|
416
|
-
sql += '
|
|
429
|
+
sql += this.placeholder() + ', ';
|
|
417
430
|
this._data.push(lText.stringifyJson(v));
|
|
418
431
|
}
|
|
419
432
|
}
|
|
@@ -427,6 +440,7 @@ export class Sql {
|
|
|
427
440
|
*/
|
|
428
441
|
delete(f) {
|
|
429
442
|
this._data = [];
|
|
443
|
+
this._placeholder = 1;
|
|
430
444
|
this._sql = ['DELETE FROM ' + this.field(f, this._pre)];
|
|
431
445
|
return this;
|
|
432
446
|
}
|
|
@@ -616,7 +630,7 @@ export class Sql {
|
|
|
616
630
|
// --- 3 ---
|
|
617
631
|
sql += this.field(v[0]) + ' ' + v[1].toUpperCase() + ' (';
|
|
618
632
|
for (const v1 of v[2]) {
|
|
619
|
-
sql += '
|
|
633
|
+
sql += this.placeholder() + ', ';
|
|
620
634
|
data.push(v1);
|
|
621
635
|
}
|
|
622
636
|
sql = sql.slice(0, -2) + ') AND ';
|
|
@@ -630,7 +644,7 @@ export class Sql {
|
|
|
630
644
|
sql += this.field(v[0]) + ' ' + v[1] + ' ' + this.field(nv.value) + ' AND ';
|
|
631
645
|
}
|
|
632
646
|
else {
|
|
633
|
-
sql += this.field(v[0]) + ' ' + v[1] + '
|
|
647
|
+
sql += this.field(v[0]) + ' ' + v[1] + ' ' + this.placeholder() + ' AND ';
|
|
634
648
|
data.push(nv);
|
|
635
649
|
}
|
|
636
650
|
}
|
|
@@ -660,7 +674,7 @@ export class Sql {
|
|
|
660
674
|
}
|
|
661
675
|
else if (typeof v === 'string' || typeof v === 'number') {
|
|
662
676
|
// --- 1 ---
|
|
663
|
-
sql += this.field(k) + ' =
|
|
677
|
+
sql += this.field(k) + ' = ' + this.placeholder() + ' AND ';
|
|
664
678
|
data.push(v);
|
|
665
679
|
}
|
|
666
680
|
else if (this._isField(v)) {
|
|
@@ -672,7 +686,7 @@ export class Sql {
|
|
|
672
686
|
if (v.length > 0) {
|
|
673
687
|
sql += this.field(k) + ' IN (';
|
|
674
688
|
for (const v1 of v) {
|
|
675
|
-
sql += '
|
|
689
|
+
sql += this.placeholder() + ', ';
|
|
676
690
|
data.push(v1);
|
|
677
691
|
}
|
|
678
692
|
sql = sql.slice(0, -2) + ') AND ';
|
|
@@ -732,12 +746,19 @@ export class Sql {
|
|
|
732
746
|
return this;
|
|
733
747
|
}
|
|
734
748
|
/**
|
|
735
|
-
* --- LIMIT ---
|
|
736
|
-
* @param a
|
|
737
|
-
* @param b
|
|
749
|
+
* --- LIMIT(limit、offset, limit) ---
|
|
750
|
+
* @param a 起始(offset)
|
|
751
|
+
* @param b 长度(limit)
|
|
738
752
|
*/
|
|
739
753
|
limit(a, b = 0) {
|
|
740
|
-
|
|
754
|
+
if (b) {
|
|
755
|
+
// --- offset, limit ---
|
|
756
|
+
this._sql.push(` LIMIT ${b} OFFSET ${a}`);
|
|
757
|
+
}
|
|
758
|
+
else {
|
|
759
|
+
// --- limit ---
|
|
760
|
+
this._sql.push(` LIMIT ${a}`);
|
|
761
|
+
}
|
|
741
762
|
return this;
|
|
742
763
|
}
|
|
743
764
|
/**
|
|
@@ -816,7 +837,7 @@ export class Sql {
|
|
|
816
837
|
}
|
|
817
838
|
return get(this.getPre(), {
|
|
818
839
|
'data': data,
|
|
819
|
-
'sql': sql
|
|
840
|
+
'sql': sql,
|
|
820
841
|
});
|
|
821
842
|
}
|
|
822
843
|
// --- 操作 ---
|
|
@@ -824,7 +845,16 @@ export class Sql {
|
|
|
824
845
|
* --- 获取 sql 语句 ---
|
|
825
846
|
*/
|
|
826
847
|
getSql() {
|
|
827
|
-
|
|
848
|
+
let sql = this._sql.join('');
|
|
849
|
+
if (this._pre) {
|
|
850
|
+
return this._alias.reduce((result, item) => {
|
|
851
|
+
if (this._service === ESERVICE.MYSQL) {
|
|
852
|
+
return result.replace(new RegExp('`' + this._pre + item + '`', 'g'), '`' + item + '`');
|
|
853
|
+
}
|
|
854
|
+
return result.replace(new RegExp(`"${this._pre}"."${item}"`, 'g'), '"' + item + '"');
|
|
855
|
+
}, sql);
|
|
856
|
+
}
|
|
857
|
+
return sql;
|
|
828
858
|
}
|
|
829
859
|
/**
|
|
830
860
|
* --- 获取全部 data ---
|
|
@@ -844,7 +874,7 @@ export class Sql {
|
|
|
844
874
|
* @param data
|
|
845
875
|
*/
|
|
846
876
|
format(sql, data) {
|
|
847
|
-
return
|
|
877
|
+
return format(sql ?? this.getSql(), data ?? this.getData(), this._service);
|
|
848
878
|
}
|
|
849
879
|
// --- 特殊方法 ---
|
|
850
880
|
/**
|
|
@@ -855,15 +885,20 @@ export class Sql {
|
|
|
855
885
|
this._sql.push(sql);
|
|
856
886
|
return this;
|
|
857
887
|
}
|
|
888
|
+
/** --- 获取占位符 --- */
|
|
889
|
+
placeholder() {
|
|
890
|
+
return this._service === ESERVICE.MYSQL ? '?' : `$${this._placeholder++}`;
|
|
891
|
+
}
|
|
858
892
|
/**
|
|
859
893
|
* --- 对字段进行包裹 ---
|
|
860
894
|
* @param str
|
|
861
895
|
* @param pre 表前缀,仅请在 field 表名时倒入前缀
|
|
862
|
-
* @param suf 表后缀,仅请在 field 表名时倒入后缀,前面加 # 代表要强制 AS
|
|
896
|
+
* @param suf 表后缀,仅请在 field 表名时倒入后缀,前面加 # 代表要强制 AS,可能是分表查询时用
|
|
863
897
|
*/
|
|
864
898
|
field(str, pre = '', suf = '') {
|
|
865
899
|
let left = '';
|
|
866
900
|
let right = '';
|
|
901
|
+
const q = this._service === ESERVICE.MYSQL ? '`' : '"';
|
|
867
902
|
if (Array.isArray(str)) {
|
|
868
903
|
this._data.push(...str[1]);
|
|
869
904
|
return this.field(str[0]);
|
|
@@ -896,7 +931,7 @@ export class Sql {
|
|
|
896
931
|
}
|
|
897
932
|
if (spacePos !== -1) {
|
|
898
933
|
const spaceRight = str.slice(spacePos + 1);
|
|
899
|
-
if (/^[a-zA-Z_`][\w`]*$/.test(spaceRight)) {
|
|
934
|
+
if (/^[a-zA-Z_`"][\w`"]*$/.test(spaceRight)) {
|
|
900
935
|
// --- OK ---
|
|
901
936
|
left = str.slice(0, spacePos);
|
|
902
937
|
right = spaceRight;
|
|
@@ -918,46 +953,87 @@ export class Sql {
|
|
|
918
953
|
}
|
|
919
954
|
if (right) {
|
|
920
955
|
// --- 处理右侧 ---
|
|
921
|
-
if (
|
|
922
|
-
right
|
|
956
|
+
if (this._service === ESERVICE.MYSQL) {
|
|
957
|
+
if (right.startsWith('`')) {
|
|
958
|
+
if (!left.includes('.')) {
|
|
959
|
+
// --- 存储表别名 ---
|
|
960
|
+
this._alias.push(right.slice(1, -1));
|
|
961
|
+
}
|
|
962
|
+
right = '`' + pre + right.slice(1);
|
|
963
|
+
}
|
|
964
|
+
else {
|
|
965
|
+
if (!left.includes('.')) {
|
|
966
|
+
// --- 存储表别名 ---
|
|
967
|
+
this._alias.push(right);
|
|
968
|
+
}
|
|
969
|
+
right = '`' + pre + right + '`';
|
|
970
|
+
}
|
|
971
|
+
right = ' AS ' + right;
|
|
923
972
|
}
|
|
924
973
|
else {
|
|
925
|
-
right
|
|
974
|
+
if (right.startsWith('"')) {
|
|
975
|
+
if (!left.includes('.')) {
|
|
976
|
+
// --- 存储表别名 ---
|
|
977
|
+
this._alias.push(right.slice(1, -1));
|
|
978
|
+
}
|
|
979
|
+
if (pre) {
|
|
980
|
+
right = `"${pre}".${right}`;
|
|
981
|
+
}
|
|
982
|
+
}
|
|
983
|
+
else {
|
|
984
|
+
if (!left.includes('.')) {
|
|
985
|
+
// --- 存储表别名 ---
|
|
986
|
+
this._alias.push(right);
|
|
987
|
+
}
|
|
988
|
+
right = (pre ? `"${pre}".` : '') + `"${right}"`;
|
|
989
|
+
}
|
|
990
|
+
right = ' AS ' + right;
|
|
926
991
|
}
|
|
927
|
-
right = ' AS ' + right;
|
|
928
992
|
}
|
|
929
993
|
else {
|
|
930
994
|
// --- 没有右侧 ---
|
|
931
995
|
if (sufAs) {
|
|
932
996
|
// --- 强制 AS ---
|
|
997
|
+
if (!left.includes('.')) {
|
|
998
|
+
// --- 存储表别名 ---
|
|
999
|
+
this._alias.push(left.startsWith('`') || left.startsWith('"') ? left.slice(1, -1) : left);
|
|
1000
|
+
}
|
|
933
1001
|
right = ' AS ' + this.field(left, pre);
|
|
934
1002
|
}
|
|
935
1003
|
}
|
|
936
1004
|
// --- 处理 left ---
|
|
937
|
-
if (/^[\w`_.*]+$/.test(left)) {
|
|
1005
|
+
if (/^[\w`"_.*]+$/.test(left)) {
|
|
938
1006
|
const l = left.split('.');
|
|
939
1007
|
if (l[0] === '*') {
|
|
940
1008
|
return '*' + right;
|
|
941
1009
|
}
|
|
942
|
-
if (l[0].startsWith('`')) {
|
|
943
|
-
l[0] = l[0].replace(
|
|
1010
|
+
if (l[0].startsWith('`') || l[0].startsWith(`"`)) {
|
|
1011
|
+
l[0] = l[0].replace(/[`"]/g, '');
|
|
944
1012
|
}
|
|
945
1013
|
if (l[1] === undefined) {
|
|
946
1014
|
// --- xxx ---
|
|
947
1015
|
if (/^[A-Z0-9_]+$/.test(l[0])) {
|
|
948
|
-
// --- 纯大写是内置函数,不能加 ` ---
|
|
1016
|
+
// --- 纯大写是内置函数,不能加 `" ---
|
|
949
1017
|
return l[0] + right;
|
|
950
1018
|
}
|
|
951
|
-
return
|
|
1019
|
+
return this._service === ESERVICE.MYSQL ?
|
|
1020
|
+
'`' + pre + l[0] + suf + '`' + right :
|
|
1021
|
+
(pre ? `"${pre}".` : '') + '"' + l[0] + suf + '"' + right;
|
|
952
1022
|
}
|
|
953
1023
|
// --- x.xxx ---
|
|
954
1024
|
// --- 只有在此模式才知道 . 前面的一定是表名,因此自动加 sql 级的 _pre ---
|
|
955
|
-
const w = l[1] === '*'
|
|
956
|
-
|
|
1025
|
+
const w = l[1] === '*'
|
|
1026
|
+
? '*' :
|
|
1027
|
+
(q + ((l[1].startsWith('`') || l[1].startsWith('"')) ?
|
|
1028
|
+
l[1].slice(1, -1) :
|
|
1029
|
+
l[1]) + q);
|
|
1030
|
+
return this._service === ESERVICE.MYSQL ?
|
|
1031
|
+
'`' + this._pre + l[0] + suf + '`.' + w + right :
|
|
1032
|
+
(this._pre ? `"${this._pre}".` : '') + '"' + l[0] + suf + '".' + w + right;
|
|
957
1033
|
}
|
|
958
1034
|
else {
|
|
959
|
-
// return left.replace(/([(, ])([a-zA-Z`_][\w`_.]*)(?=[), ])/g, (
|
|
960
|
-
return left.replace(/(^|[(, ])([a-zA-Z`_][\w`_.]*)(?=[), ]|$)/g, (t, t1, t2) => {
|
|
1035
|
+
// return left.replace(/([(, ])([a-zA-Z`"_][\w`"_.]*)(?=[), ])/g, (
|
|
1036
|
+
return left.replace(/(^|[(, ])([a-zA-Z`"_][\w`"_.]*)(?=[), ]|$)/g, (t, t1, t2) => {
|
|
961
1037
|
return t1 + this.field(t2, pre, suf);
|
|
962
1038
|
}) + right;
|
|
963
1039
|
}
|
|
@@ -982,12 +1058,34 @@ export function get(ctrPre, opt = {}) {
|
|
|
982
1058
|
return new Sql(ctrPre instanceof ctr.Ctr ? ctrPre.getPrototype('_config').sql.pre : ctrPre, opt);
|
|
983
1059
|
}
|
|
984
1060
|
/**
|
|
985
|
-
* --- 返回代入后的完整 SQL
|
|
1061
|
+
* --- 返回代入后的完整 SQL 字符串,这并不安全不能直接执行,只是用来调试打印 sql 语句 ---
|
|
986
1062
|
* @param sql SQL 字符串
|
|
987
1063
|
* @param data DATA 数据
|
|
1064
|
+
* @param service 服务商,默认 MySQL
|
|
988
1065
|
*/
|
|
989
|
-
export function format(sql, data) {
|
|
990
|
-
|
|
1066
|
+
export function format(sql, data, service = ESERVICE.MYSQL) {
|
|
1067
|
+
if (service === ESERVICE.MYSQL) {
|
|
1068
|
+
return mysql2.format(sql, data);
|
|
1069
|
+
}
|
|
1070
|
+
// --- PGSQL ---
|
|
1071
|
+
// --- PostgreSQL 手动替换占位符 ---
|
|
1072
|
+
let index = 0;
|
|
1073
|
+
return sql.replace(/\$\d+/g, () => {
|
|
1074
|
+
const val = data[index++];
|
|
1075
|
+
if (val === null) {
|
|
1076
|
+
return 'NULL';
|
|
1077
|
+
}
|
|
1078
|
+
if (typeof val === 'string') {
|
|
1079
|
+
return `'${lText.stringifyJson(val).slice(1, -1).replace(/'/g, "''").replace(/\\"/g, '"')}'`;
|
|
1080
|
+
}
|
|
1081
|
+
if (typeof val === 'number') {
|
|
1082
|
+
return val.toString();
|
|
1083
|
+
}
|
|
1084
|
+
if (val instanceof Buffer) {
|
|
1085
|
+
return `'\\x${val.toString('hex')}'`;
|
|
1086
|
+
}
|
|
1087
|
+
return `'${JSON.stringify(val).replace(/'/g, "''")}'`;
|
|
1088
|
+
});
|
|
991
1089
|
}
|
|
992
1090
|
/**
|
|
993
1091
|
* --- 将数组兑换为组合的对象(Array/Object mix) ---
|