@maiyunnet/kebab 7.4.1 → 7.5.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 +1 -1
- package/index.js +1 -1
- package/lib/sql.d.ts +14 -0
- package/lib/sql.js +73 -0
- package/package.json +1 -1
- package/sys/ctr.js +5 -0
- package/www/example/ctr/test.js +49 -0
package/index.d.ts
CHANGED
package/index.js
CHANGED
|
@@ -6,7 +6,7 @@
|
|
|
6
6
|
* --- 本文件用来定义每个目录实体地址的常量 ---
|
|
7
7
|
*/
|
|
8
8
|
/** --- 当前系统版本号 --- */
|
|
9
|
-
export const VER = '7.
|
|
9
|
+
export const VER = '7.5.0';
|
|
10
10
|
// --- 服务端用的路径 ---
|
|
11
11
|
const imu = decodeURIComponent(import.meta.url).replace('file://', '').replace(/^\/(\w:)/, '$1');
|
|
12
12
|
/** --- /xxx/xxx --- */
|
package/lib/sql.d.ts
CHANGED
|
@@ -10,6 +10,19 @@ export declare enum ESERVICE {
|
|
|
10
10
|
'MYSQL' = 0,
|
|
11
11
|
'PGSQL' = 1
|
|
12
12
|
}
|
|
13
|
+
/** --- JSON 查询操作符 --- */
|
|
14
|
+
export declare enum EJSON {
|
|
15
|
+
/** --- 包含 (MySQL: JSON_CONTAINS, PG: @>) --- */
|
|
16
|
+
'CONTAINS' = "json",
|
|
17
|
+
/** --- 被包含 (MySQL: JSON_CONTAINS, PG: <@) --- */
|
|
18
|
+
'CONTAINED_BY' = "json_in",
|
|
19
|
+
/** --- 存在 Key (MySQL: JSON_CONTAINS_PATH one, PG: ?) --- */
|
|
20
|
+
'HAS_KEY' = "json_key",
|
|
21
|
+
/** --- 存在任意 Key (MySQL: JSON_CONTAINS_PATH one, PG: ?|) --- */
|
|
22
|
+
'HAS_ANY_KEYS' = "json_any",
|
|
23
|
+
/** --- 存在所有 Key (MySQL: JSON_CONTAINS_PATH all, PG: ?&) --- */
|
|
24
|
+
'HAS_ALL_KEYS' = "json_all"
|
|
25
|
+
}
|
|
13
26
|
export declare class Sql {
|
|
14
27
|
/** --- ctr 对象 --- */
|
|
15
28
|
private readonly _ctr?;
|
|
@@ -145,6 +158,7 @@ export declare class Sql {
|
|
|
145
158
|
* --- 5. '$or': [{'city': 'bj'}, {'city': 'sh'}, [['age', '>', '10']]], 'type': '2' ---
|
|
146
159
|
* --- 6. 'city_in': column('city_out') ---
|
|
147
160
|
* --- 7. ['JSON_CONTAINS(`uid`, ?)', ['hello']] ---
|
|
161
|
+
* --- 8. ['info', 'json', {'a': 1}] ---
|
|
148
162
|
* @param s 筛选数据
|
|
149
163
|
*/
|
|
150
164
|
where(s: string | kebab.Json): this;
|
package/lib/sql.js
CHANGED
|
@@ -8,6 +8,20 @@ export var ESERVICE;
|
|
|
8
8
|
ESERVICE[ESERVICE["MYSQL"] = 0] = "MYSQL";
|
|
9
9
|
ESERVICE[ESERVICE["PGSQL"] = 1] = "PGSQL";
|
|
10
10
|
})(ESERVICE || (ESERVICE = {}));
|
|
11
|
+
/** --- JSON 查询操作符 --- */
|
|
12
|
+
export var EJSON;
|
|
13
|
+
(function (EJSON) {
|
|
14
|
+
/** --- 包含 (MySQL: JSON_CONTAINS, PG: @>) --- */
|
|
15
|
+
EJSON["CONTAINS"] = "json";
|
|
16
|
+
/** --- 被包含 (MySQL: JSON_CONTAINS, PG: <@) --- */
|
|
17
|
+
EJSON["CONTAINED_BY"] = "json_in";
|
|
18
|
+
/** --- 存在 Key (MySQL: JSON_CONTAINS_PATH one, PG: ?) --- */
|
|
19
|
+
EJSON["HAS_KEY"] = "json_key";
|
|
20
|
+
/** --- 存在任意 Key (MySQL: JSON_CONTAINS_PATH one, PG: ?|) --- */
|
|
21
|
+
EJSON["HAS_ANY_KEYS"] = "json_any";
|
|
22
|
+
/** --- 存在所有 Key (MySQL: JSON_CONTAINS_PATH all, PG: ?&) --- */
|
|
23
|
+
EJSON["HAS_ALL_KEYS"] = "json_all";
|
|
24
|
+
})(EJSON || (EJSON = {}));
|
|
11
25
|
/** --- field 用 token --- */
|
|
12
26
|
let columnToken = '';
|
|
13
27
|
export class Sql {
|
|
@@ -388,6 +402,7 @@ export class Sql {
|
|
|
388
402
|
* --- 5. '$or': [{'city': 'bj'}, {'city': 'sh'}, [['age', '>', '10']]], 'type': '2' ---
|
|
389
403
|
* --- 6. 'city_in': column('city_out') ---
|
|
390
404
|
* --- 7. ['JSON_CONTAINS(`uid`, ?)', ['hello']] ---
|
|
405
|
+
* --- 8. ['info', 'json', {'a': 1}] ---
|
|
391
406
|
* @param s 筛选数据
|
|
392
407
|
*/
|
|
393
408
|
where(s) {
|
|
@@ -437,6 +452,55 @@ export class Sql {
|
|
|
437
452
|
data.push(...v[1]);
|
|
438
453
|
}
|
|
439
454
|
}
|
|
455
|
+
else if (typeof v[1] === 'string' && ['json', 'json_in', 'json_key', 'json_any', 'json_all'].includes(v[1].toLowerCase())) {
|
|
456
|
+
// --- json ---
|
|
457
|
+
const op = v[1].toLowerCase();
|
|
458
|
+
const nv = v[2];
|
|
459
|
+
if (op === 'json') {
|
|
460
|
+
if (this._service === ESERVICE.MYSQL) {
|
|
461
|
+
sql += `JSON_CONTAINS(${this.field(v[0])}, ${this._placeholder()}) AND `;
|
|
462
|
+
data.push(lText.stringifyJson(nv));
|
|
463
|
+
}
|
|
464
|
+
else {
|
|
465
|
+
sql += `${this.field(v[0])} @> ${this._placeholder()} AND `;
|
|
466
|
+
data.push(lText.stringifyJson(nv));
|
|
467
|
+
}
|
|
468
|
+
}
|
|
469
|
+
else if (op === 'json_in') {
|
|
470
|
+
if (this._service === ESERVICE.MYSQL) {
|
|
471
|
+
sql += `JSON_CONTAINS(${this._placeholder()}, ${this.field(v[0])}) AND `;
|
|
472
|
+
data.push(lText.stringifyJson(nv));
|
|
473
|
+
}
|
|
474
|
+
else {
|
|
475
|
+
sql += `${this.field(v[0])} <@ ${this._placeholder()} AND `;
|
|
476
|
+
data.push(lText.stringifyJson(nv));
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
else {
|
|
480
|
+
// --- json_key, json_any, json_all ---
|
|
481
|
+
const keys = Array.isArray(nv) ? nv : [nv];
|
|
482
|
+
if (this._service === ESERVICE.MYSQL) {
|
|
483
|
+
const type = op === 'json_all' ? 'all' : 'one';
|
|
484
|
+
let pathSql = '';
|
|
485
|
+
for (const k of keys) {
|
|
486
|
+
pathSql += ', ' + this._placeholder();
|
|
487
|
+
data.push(k.startsWith('$') ? k : `$.${k}`);
|
|
488
|
+
}
|
|
489
|
+
sql += `JSON_CONTAINS_PATH(${this.field(v[0])}, '${type}'${pathSql}) AND `;
|
|
490
|
+
}
|
|
491
|
+
else {
|
|
492
|
+
if (op === 'json_key' && keys.length === 1) {
|
|
493
|
+
sql += `${this.field(v[0])} ? ${this._placeholder()} AND `;
|
|
494
|
+
data.push(keys[0]);
|
|
495
|
+
}
|
|
496
|
+
else {
|
|
497
|
+
const pgOp = op === 'json_all' ? '?&' : '?|';
|
|
498
|
+
sql += `${this.field(v[0])} ${pgOp} ${this._placeholder()} AND `;
|
|
499
|
+
data.push(keys);
|
|
500
|
+
}
|
|
501
|
+
}
|
|
502
|
+
}
|
|
503
|
+
}
|
|
440
504
|
else if (v[2] === null) {
|
|
441
505
|
// --- 3: null ---
|
|
442
506
|
let opera = v[1];
|
|
@@ -994,6 +1058,15 @@ export function format(sql, data, service = ESERVICE.MYSQL) {
|
|
|
994
1058
|
if (val instanceof Buffer) {
|
|
995
1059
|
return `'\\x${val.toString('hex')}'`;
|
|
996
1060
|
}
|
|
1061
|
+
if (Array.isArray(val)) {
|
|
1062
|
+
// --- PGSQL Array ---
|
|
1063
|
+
return `ARRAY[${val.map(v => {
|
|
1064
|
+
if (typeof v === 'string') {
|
|
1065
|
+
return `'${v.replace(/'/g, "''")}'`;
|
|
1066
|
+
}
|
|
1067
|
+
return v;
|
|
1068
|
+
}).join(', ')}]`;
|
|
1069
|
+
}
|
|
997
1070
|
return `'${lText.stringifyJson(val).replace(/'/g, "''")}'`;
|
|
998
1071
|
});
|
|
999
1072
|
}
|
package/package.json
CHANGED
package/sys/ctr.js
CHANGED
|
@@ -84,6 +84,11 @@ export class Ctr {
|
|
|
84
84
|
if (!this._timer) {
|
|
85
85
|
return;
|
|
86
86
|
}
|
|
87
|
+
if (this._res.headersSent) {
|
|
88
|
+
// --- 已经开始输出的,不能设置 timeout ---
|
|
89
|
+
lCore.debug('[CTR][TIMEOUT][SET] headersSent is true, can not set timeout');
|
|
90
|
+
return;
|
|
91
|
+
}
|
|
87
92
|
this._timer.timeout = num;
|
|
88
93
|
clearTimeout(this._timer.timer);
|
|
89
94
|
this._timer.timer = setTimeout(this._timer.callback, num);
|
package/www/example/ctr/test.js
CHANGED
|
@@ -187,6 +187,7 @@ export default class extends sCtr.Ctr {
|
|
|
187
187
|
`<br><a href="${this._config.const.urlBase}test/sql?type=upsert">View "test/sql?type=upsert"</a> <a href="${this._config.const.urlBase}test/sql?type=upsert&s=pgsql">pgsql</a>`,
|
|
188
188
|
`<br><a href="${this._config.const.urlBase}test/sql?type=delete">View "test/sql?type=delete"</a> <a href="${this._config.const.urlBase}test/sql?type=delete&s=pgsql">pgsql</a>`,
|
|
189
189
|
`<br><a href="${this._config.const.urlBase}test/sql?type=where">View "test/sql?type=where"</a> <a href="${this._config.const.urlBase}test/sql?type=where&s=pgsql">pgsql</a>`,
|
|
190
|
+
`<br><a href="${this._config.const.urlBase}test/sql?type=json">View "test/sql?type=json"</a> <a href="${this._config.const.urlBase}test/sql?type=json&s=pgsql">pgsql</a>`,
|
|
190
191
|
`<br><a href="${this._config.const.urlBase}test/sql?type=having">View "test/sql?type=having"</a> <a href="${this._config.const.urlBase}test/sql?type=having&s=pgsql">pgsql</a>`,
|
|
191
192
|
`<br><a href="${this._config.const.urlBase}test/sql?type=by">View "test/sql?type=by"</a> <a href="${this._config.const.urlBase}test/sql?type=by&s=pgsql">pgsql</a>`,
|
|
192
193
|
`<br><a href="${this._config.const.urlBase}test/sql?type=field">View "test/sql?type=field"</a> <a href="${this._config.const.urlBase}test/sql?type=field&s=pgsql">pgsql</a>`,
|
|
@@ -2561,6 +2562,44 @@ Result:<pre id="result">Nothing.</pre>`);
|
|
|
2561
2562
|
echo.push(`<pre>sql.delete('user').where({ 'id': '1' });</pre>
|
|
2562
2563
|
<b>getSql() :</b> ${s}<br>
|
|
2563
2564
|
<b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
|
|
2565
|
+
<b>format() :</b> ${sql.format(s, sd)}`);
|
|
2566
|
+
break;
|
|
2567
|
+
}
|
|
2568
|
+
case 'json': {
|
|
2569
|
+
// --- json contains ---
|
|
2570
|
+
let s = sql.select('*', 'user').where([['info', lSql.EJSON.CONTAINS, { 'a': 1 }]]).getSql();
|
|
2571
|
+
let sd = sql.getData();
|
|
2572
|
+
echo.push(`<pre>sql.select('*', 'user').where([['info', lSql.EJSON.CONTAINS, { 'a': 1 }]]);</pre>
|
|
2573
|
+
<b>getSql() :</b> ${s}<br>
|
|
2574
|
+
<b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
|
|
2575
|
+
<b>format() :</b> ${sql.format(s, sd)}<hr>`);
|
|
2576
|
+
// --- json contained by ---
|
|
2577
|
+
s = sql.select('*', 'user').where([['info', lSql.EJSON.CONTAINED_BY, { 'a': 1, 'b': 2 }]]).getSql();
|
|
2578
|
+
sd = sql.getData();
|
|
2579
|
+
echo.push(`<pre>sql.select('*', 'user').where([['info', lSql.EJSON.CONTAINED_BY, { 'a': 1, 'b': 2 }]]);</pre>
|
|
2580
|
+
<b>getSql() :</b> ${s}<br>
|
|
2581
|
+
<b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
|
|
2582
|
+
<b>format() :</b> ${sql.format(s, sd)}<hr>`);
|
|
2583
|
+
// --- json key exists ---
|
|
2584
|
+
s = sql.select('*', 'user').where([['info', lSql.EJSON.HAS_KEY, 'age']]).getSql();
|
|
2585
|
+
sd = sql.getData();
|
|
2586
|
+
echo.push(`<pre>sql.select('*', 'user').where([['info', lSql.EJSON.HAS_KEY, 'age']]);</pre>
|
|
2587
|
+
<b>getSql() :</b> ${s}<br>
|
|
2588
|
+
<b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
|
|
2589
|
+
<b>format() :</b> ${sql.format(s, sd)}<hr>`);
|
|
2590
|
+
// --- json any key exists ---
|
|
2591
|
+
s = sql.select('*', 'user').where([['info', lSql.EJSON.HAS_ANY_KEYS, ['age', 'name']]]).getSql();
|
|
2592
|
+
sd = sql.getData();
|
|
2593
|
+
echo.push(`<pre>sql.select('*', 'user').where([['info', lSql.EJSON.HAS_ANY_KEYS, ['age', 'name']]]);</pre>
|
|
2594
|
+
<b>getSql() :</b> ${s}<br>
|
|
2595
|
+
<b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
|
|
2596
|
+
<b>format() :</b> ${sql.format(s, sd)}<hr>`);
|
|
2597
|
+
// --- json all keys exist ---
|
|
2598
|
+
s = sql.select('*', 'user').where([['info', lSql.EJSON.HAS_ALL_KEYS, ['age', 'name']]]).getSql();
|
|
2599
|
+
sd = sql.getData();
|
|
2600
|
+
echo.push(`<pre>sql.select('*', 'user').where([['info', lSql.EJSON.HAS_ALL_KEYS, ['age', 'name']]]);</pre>
|
|
2601
|
+
<b>getSql() :</b> ${s}<br>
|
|
2602
|
+
<b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
|
|
2564
2603
|
<b>format() :</b> ${sql.format(s, sd)}`);
|
|
2565
2604
|
break;
|
|
2566
2605
|
}
|
|
@@ -2648,6 +2687,16 @@ Result:<pre id="result">Nothing.</pre>`);
|
|
|
2648
2687
|
echo.push(`<pre>sql.select('*', 'user').where([{ 'city': 'la', 'area': null }, ['age', '>', '10'], ['soft', '<>', null], ['ware', 'IS', null]]);</pre>
|
|
2649
2688
|
<b>getSql() :</b> ${s}<br>
|
|
2650
2689
|
<b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
|
|
2690
|
+
<b>format() :</b> ${sql.format(s, sd)}<hr>`);
|
|
2691
|
+
s = sql.select('*', 'user').where([
|
|
2692
|
+
['info', 'json', { 'a': 1 }]
|
|
2693
|
+
]).getSql();
|
|
2694
|
+
sd = sql.getData();
|
|
2695
|
+
echo.push(`<pre>sql.select('*', 'user').where([
|
|
2696
|
+
['info', 'json', { 'a': 1 }]
|
|
2697
|
+
]);</pre>
|
|
2698
|
+
<b>getSql() :</b> ${s}<br>
|
|
2699
|
+
<b>getData():</b> <pre>${JSON.stringify(sd, undefined, 4)}</pre>
|
|
2651
2700
|
<b>format() :</b> ${sql.format(s, sd)}`);
|
|
2652
2701
|
break;
|
|
2653
2702
|
}
|