@asla/yoursql 0.8.2 → 0.8.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/sql_gen.js DELETED
@@ -1,1061 +0,0 @@
1
- function condition(conditions, type = "AND") {
2
- if (typeof conditions === "function")
3
- conditions = conditions();
4
- if (!conditions)
5
- return;
6
- if (typeof conditions === "string")
7
- return conditions;
8
- else {
9
- if (conditions.length) {
10
- let sql = "";
11
- type = " " + type + " ";
12
- sql += conditions[0];
13
- for (let i = 1; i < conditions.length; i++)
14
- sql += type + conditions[i];
15
- return sql;
16
- }
17
- return;
18
- }
19
- }
20
- function createUpdateSetFromObject(set) {
21
- const updateKey = Object.keys(set);
22
- let i = 0;
23
- let key;
24
- let value;
25
- let sql;
26
- for (; i < updateKey.length; i++) {
27
- key = updateKey[i];
28
- value = set[key];
29
- if (value === undefined)
30
- continue;
31
- if (typeof value === "string") {
32
- if (value) {
33
- sql = "SET\n" + key + "= " + value;
34
- break;
35
- }
36
- }
37
- else
38
- throw new TypeError(`key ${key} 类型错误(${typeof value})`);
39
- }
40
- if (sql) {
41
- i++;
42
- for (; i < updateKey.length; i++) {
43
- key = updateKey[i];
44
- value = set[key];
45
- if (value === undefined)
46
- continue;
47
- if (typeof value === "string") {
48
- if (value)
49
- sql += "," + key + "= " + value;
50
- }
51
- else
52
- throw new TypeError(`key ${key} 类型错误(${typeof value})`);
53
- }
54
- return sql;
55
- }
56
- else
57
- throw new Error("值不能为空");
58
- }
59
-
60
- /**
61
- * 获取对象数组中的 key 的集合
62
- * @public
63
- * @param keepUndefinedKey - 是否保留值为 undefined 的 key
64
- */
65
- function getObjectListKeys(objectList, keepUndefinedKey) {
66
- let keys = new Set();
67
- for (let i = 0; i < objectList.length; i++) {
68
- let obj = objectList[i];
69
- let hasKeys = Object.keys(obj);
70
- let k;
71
- for (let j = 0; j < hasKeys.length; j++) {
72
- k = hasKeys[j];
73
- if (typeof k !== "string")
74
- continue;
75
- if (!keepUndefinedKey && obj[k] === undefined)
76
- continue;
77
- keys.add(k);
78
- }
79
- }
80
- return keys;
81
- }
82
- /**
83
- * 生成 WHERE 语句
84
- * @public
85
- * @example
86
- * ```ts
87
- * where(['a=1','b=2']) // "\nWHERE a=1 AND b=2"
88
- * where(['a=1','b=2'],"OR") // "\nWHERE a=1 OR b=2"
89
- * where("a=1 OR b=2") // "\nWHERE a=1 OR b=2"
90
- * where(()=>"a=1 OR b=2") // "\nWHERE a=1 AND b=2"
91
- * where([]) // ""
92
- * where(undefined) // ""
93
- * ```
94
- */
95
- function where(conditions, type) {
96
- const sql = condition(conditions, type);
97
- if (sql)
98
- return "\nWHERE " + sql;
99
- return "";
100
- }
101
- /**
102
- *
103
- * 生成 HAVING 语句
104
- * @public
105
- */
106
- function having(conditions, type) {
107
- const sql = condition(conditions, type);
108
- if (sql)
109
- return "\nHAVING " + sql;
110
- return "";
111
- }
112
- /**
113
- * @public
114
- * @example
115
- * ```ts
116
- * selectColumns({c1: true, c2: "count(*)", c3: "column"}) // "c1,count(*) AS c2,column as c3"
117
- * selectColumns("c1,count(*) AS c2,column as c3") // "c1,count(*) AS c2,column as c3"
118
- * ```
119
- */
120
- function selectColumns(columns) {
121
- if (typeof columns === "function")
122
- columns = columns();
123
- switch (typeof columns) {
124
- case "string":
125
- return columns;
126
- case "object": {
127
- if (columns instanceof Array) {
128
- if (columns.length === 0)
129
- throw new Error("没有选择任何列");
130
- return columns.join(",");
131
- }
132
- else {
133
- let sql = "";
134
- const keys = Object.keys(columns);
135
- if (keys.length === 0)
136
- throw new Error("没有选择任何列");
137
- let k = keys[0];
138
- let v = columns[k];
139
- if (typeof v === "string")
140
- sql += v + " AS " + k;
141
- else
142
- sql += k;
143
- for (let i = 1; i < keys.length; i++) {
144
- k = keys[i];
145
- v = columns[k];
146
- sql += ",";
147
- if (typeof v === "string")
148
- sql += v + " AS " + k;
149
- else
150
- sql += k;
151
- }
152
- return sql;
153
- }
154
- }
155
- default:
156
- throw new TypeError("columns 应为 string 或 object 类型");
157
- }
158
- }
159
- /**
160
- * 生成 ORDER BY 语句, d
161
- * @public
162
- * @example
163
- * ```ts
164
- * // 以下生成 "\nORDER BY age DESC NULLS FIRST,num ASC"
165
- * orderBy("age DESC NULLS FIRST,num ASC");
166
- * orderBy(["age DESC NULLS FIRST", "num ASC"]);
167
- * orderBy([
168
- * { key: "age", asc: false, nullLast: false },
169
- * { key: "num", asc: true },
170
- * ]);
171
- * orderBy({ age: "DESC NULLS FIRST", num: true });
172
- *
173
- * orderBy([]) // ""
174
- * orderBy({}) // ""
175
- * ```
176
- */
177
- function orderBy(by) {
178
- if (typeof by === "function")
179
- by = by();
180
- let sql = "";
181
- if (!by)
182
- return sql;
183
- if (typeof by === "string") {
184
- sql += "\nORDER BY " + by;
185
- }
186
- else if (by instanceof Array) {
187
- if (by.length) {
188
- sql += "\nORDER BY " + handlerOrderValue(by[0]);
189
- for (let i = 1; i < by.length; i++)
190
- sql += "," + handlerOrderValue(by[i]);
191
- }
192
- }
193
- else {
194
- let keys = Object.keys(by);
195
- if (keys.length) {
196
- let key = keys[0];
197
- let value = by[key];
198
- sql += "\nORDER BY " + key + " " + (typeof value === "string" ? value : value ? "ASC" : "DESC");
199
- for (let i = 1; i < keys.length; i++) {
200
- key = keys[i];
201
- value = by[key];
202
- sql += "," + key + " ";
203
- if (typeof value === "string")
204
- sql += value;
205
- else
206
- sql += value ? "ASC" : "DESC";
207
- }
208
- }
209
- }
210
- return sql;
211
- }
212
- function handlerOrderValue(value) {
213
- if (typeof value === "string")
214
- return value;
215
- else {
216
- let str = value.key + " " + (value.asc ? "ASC" : "DESC");
217
- if (value.nullLast !== undefined)
218
- str += value.nullLast ? " NULLS LAST" : " NULLS FIRST";
219
- return str;
220
- }
221
- }
222
-
223
- /** @public */
224
- class SqlStatement {
225
- }
226
- /** @public */
227
- class SqlStatementDataset extends SqlStatement {
228
- /**
229
- * 转成子选择语句, 你可以使用 select form xxx 选择
230
- * 如果是 table 则是 table name
231
- * 如果是 选择语句,则是 (xxx)
232
- */
233
- toSelect() {
234
- return "(" + this.toString() + ")";
235
- }
236
- }
237
- /** @public */
238
- class SqlTextStatementDataset extends SqlStatementDataset {
239
- sql;
240
- constructor(sql) {
241
- super();
242
- this.sql = sql;
243
- }
244
- toString() {
245
- return this.sql;
246
- }
247
- }
248
-
249
- /**
250
- * SQL 原始字符类。可以使用 String 类代替,这只是为了推断类型
251
- * @public
252
- */
253
- class SqlRaw extends String {
254
- }
255
- /**
256
- * SQL value 生成器
257
- * @public
258
- */
259
- class SqlValuesCreator {
260
- static create(map) {
261
- const obj = new this(map);
262
- const fn = obj.toSqlStr.bind(obj);
263
- Reflect.setPrototypeOf(fn, obj);
264
- return fn;
265
- }
266
- /**
267
- * 将字符串转为 SQL 的字符串值的形式(单引号会被转义)。
268
- * @example 输入 a'b'c , 返回 a''b''c.
269
- */
270
- static string(value) {
271
- return "'" + value.replaceAll("'", "''") + "'";
272
- }
273
- /**
274
- * @param map - 自定义对象转换
275
- */
276
- constructor(map) {
277
- this._map = new Map(map);
278
- }
279
- setTransformer(type_map, encoder) {
280
- if (typeof type_map === "function") {
281
- if (encoder)
282
- this._map.set(type_map, encoder);
283
- else
284
- this._map.delete(type_map);
285
- }
286
- else {
287
- for (const [type, encoder] of type_map) {
288
- if (typeof type === "function" && typeof encoder === "function") {
289
- this._map.set(type, encoder);
290
- }
291
- }
292
- }
293
- }
294
- _map;
295
- /**
296
- * 将 JS 对象转为 SQL 的字符值的形式 。 undefined 将被转换为 DEFAULT
297
- * ```ts
298
- * const v=SqlValuesCreator.create()
299
- * v() 和 v.toSqlStr() 是等价的
300
- * ```
301
- */
302
- toSqlStr(value, assertJsType) {
303
- if (value === null)
304
- return "NULL";
305
- else if (value === undefined)
306
- return "DEFAULT";
307
- let basicType = typeof value;
308
- if (assertJsType) {
309
- if (typeof assertJsType === "function") {
310
- if (basicType !== "object")
311
- throw new AssertError("object", basicType);
312
- let type = this._map.get(assertJsType);
313
- if (!type) {
314
- if (assertJsType === Object)
315
- return this.defaultObject(value);
316
- throw new Error("类型不存在");
317
- }
318
- return type.call(this, value);
319
- }
320
- else if (basicType !== assertJsType) {
321
- throw new AssertError(assertJsType, basicType);
322
- }
323
- }
324
- switch (basicType) {
325
- case "bigint":
326
- return value.toString();
327
- case "number":
328
- return value.toString();
329
- case "string":
330
- return SqlValuesCreator.string(value);
331
- case "boolean":
332
- return value.toString();
333
- case "object": {
334
- if (value instanceof String)
335
- return value.toString();
336
- const Class = this.getClassType(value);
337
- if (Class)
338
- return this._map.get(Class).call(this, value);
339
- return this.defaultObject(value);
340
- }
341
- case "undefined":
342
- return "DEFAULT";
343
- default:
344
- //function、symbol
345
- let type = typeof value;
346
- throw new Error("不支持 " + type + " 类型");
347
- }
348
- }
349
- /**
350
- * @deprecated 已废弃
351
- * 获取值对应的 SqlValueEncoder
352
- */
353
- getObjectType(value) {
354
- for (const Class of this._map.keys()) {
355
- if (value instanceof Class)
356
- return this._map.get(Class);
357
- }
358
- return this.defaultObject;
359
- }
360
- /** 获取值对应已定义的类 */
361
- getClassType(value) {
362
- for (const Class of this._map.keys()) {
363
- if (value instanceof Class)
364
- return Class;
365
- }
366
- }
367
- defaultObject(value) {
368
- return SqlValuesCreator.string(JSON.stringify(value));
369
- }
370
- objectListToValuesList(objectList, keys_types, keepUndefinedKey) {
371
- if (objectList.length <= 0)
372
- throw new Error("objectList 不能是空数组");
373
- let keys;
374
- let asserts;
375
- if (!keys_types) {
376
- keys = Array.from(getObjectListKeys(objectList, keepUndefinedKey));
377
- asserts = [];
378
- }
379
- else if (keys_types instanceof Array) {
380
- keys = keys_types;
381
- asserts = [];
382
- }
383
- else {
384
- keys = Object.keys(keys_types);
385
- asserts = initColumnAssert(keys, keys_types);
386
- }
387
- let str = "(" + this._internalObjectToValues(objectList[0], keys, asserts) + ")";
388
- let i = 1;
389
- let j;
390
- let value;
391
- let rows;
392
- try {
393
- for (; i < objectList.length; i++) {
394
- const object = objectList[i];
395
- rows = [];
396
- j = 0;
397
- for (; j < keys.length; j++) {
398
- value = object[keys[j]];
399
- rows[j] = this.toSqlStr(value, asserts[j]?.assertJsType);
400
- }
401
- str += ",\n(" + rows.join(",") + ")";
402
- }
403
- }
404
- catch (error) {
405
- let message = error instanceof Error ? error.message : String(error);
406
- throw new Error("第 " + i + " 项,字段 '" + keys[j] + "' 异常," + message);
407
- }
408
- return str;
409
- }
410
- objectToValues(object, keys_types) {
411
- let type;
412
- let keys;
413
- if (keys_types instanceof Array) {
414
- keys = keys_types;
415
- type = [];
416
- }
417
- else if (keys_types) {
418
- keys = Object.keys(keys_types);
419
- type = initColumnAssert(keys, keys_types);
420
- }
421
- else {
422
- keys = Object.keys(object);
423
- type = [];
424
- }
425
- return this._internalObjectToValues(object, keys, type);
426
- }
427
- _internalObjectToValues(object, keys, type) {
428
- const values = [];
429
- let i = 0;
430
- let key;
431
- let value;
432
- let assertType;
433
- try {
434
- for (; i < keys.length; i++) {
435
- key = keys[i];
436
- value = object[key];
437
- assertType = type[i];
438
- if (assertType) {
439
- values[i] = this.toSqlStr(value, assertType.assertJsType);
440
- if (assertType.sqlType)
441
- values[i] += "::" + assertType.sqlType;
442
- }
443
- else
444
- values[i] = this.toSqlStr(value);
445
- }
446
- }
447
- catch (error) {
448
- let message = error instanceof Error ? error.message : String(error);
449
- throw new Error("字段 '" + key + "' 异常," + message);
450
- }
451
- return values.join(",");
452
- }
453
- /**
454
- * 将数组列表转为 SQL 的一个 value
455
- * @example 返回示例: " 'abc', '6', 'now()' "
456
- */
457
- toValues(values) {
458
- return values.map((v) => this.toSqlStr(v)).join(",");
459
- }
460
- createValues(asName, values, valuesTypes) {
461
- if (values.length === 0)
462
- throw new Error("values 不能为空");
463
- const insertKeys = Object.keys(valuesTypes);
464
- const defaultValues = [];
465
- const asserts = new Array(insertKeys.length);
466
- const valuesStr = new Array(values.length);
467
- {
468
- const column0 = new Array(insertKeys.length);
469
- let columnName;
470
- let item;
471
- let sqlType;
472
- let assertJsType;
473
- let value;
474
- for (let i = 0; i < insertKeys.length; i++) {
475
- columnName = insertKeys[i];
476
- item = valuesTypes[columnName];
477
- if (typeof item === "string") {
478
- sqlType = item;
479
- defaultValues[i] = "NULL";
480
- }
481
- else {
482
- sqlType = item.sqlType;
483
- assertJsType = item.assertJsType;
484
- asserts[i] = assertJsType;
485
- defaultValues[i] = item.sqlDefault ?? "NULL";
486
- }
487
- value = values[0][columnName];
488
- if (value === undefined)
489
- column0[i] = defaultValues[i] + "::" + sqlType;
490
- else
491
- column0[i] = this.toSqlStr(value, assertJsType) + "::" + sqlType;
492
- }
493
- valuesStr[0] = "(" + column0.join(",") + ")";
494
- }
495
- let items = new Array(insertKeys.length);
496
- let value;
497
- for (let i = 1; i < values.length; i++) {
498
- for (let j = 0; j < insertKeys.length; j++) {
499
- value = values[i][insertKeys[j]];
500
- if (value === undefined)
501
- items[j] = defaultValues[j];
502
- else
503
- items[j] = this.toSqlStr(value, asserts[j]);
504
- }
505
- valuesStr[i] = "(" + items.join(",") + ")";
506
- }
507
- return new YourValuesAs(insertKeys, asName, valuesStr.join(",\n"));
508
- }
509
- }
510
- class YourValuesAs extends SqlStatementDataset {
511
- constructor(columns, asName, valuesStr) {
512
- super();
513
- this.#asName = asName;
514
- this.#valuesStr = valuesStr;
515
- this.#sql = `(VALUES\n${this.#valuesStr})\nAS ${this.#asName}(${columns.join(",")})`;
516
- }
517
- #asName;
518
- #valuesStr;
519
- #sql;
520
- toSelect() {
521
- return this.#sql;
522
- }
523
- toString() {
524
- return this.#sql;
525
- }
526
- }
527
- function initColumnAssert(keys, keys_types) {
528
- let key;
529
- let value;
530
- let type = new Array(keys.length);
531
- for (let i = 0; i < keys.length; i++) {
532
- key = keys[i];
533
- value = keys_types[key];
534
- if (typeof value === "string") {
535
- type[i] = { sqlType: value };
536
- }
537
- else {
538
- type[i] = value;
539
- }
540
- }
541
- return type;
542
- }
543
- class AssertError extends TypeError {
544
- constructor(assertType, actual) {
545
- super(`Assert ${assertType} type, Actual ${actual} type`);
546
- }
547
- }
548
-
549
- /** @public PgSql 转换器 */
550
- const pgSqlTransformer = new Map([
551
- [
552
- Array,
553
- function encodePgArray(value) {
554
- if (value.length === 0)
555
- return "NULL";
556
- const valueStr = [];
557
- let type;
558
- let basicType;
559
- for (let i = 0; i < value.length; i++) {
560
- if (value[i] === null || value[i] === undefined)
561
- valueStr[i] = this.toSqlStr(value[i]);
562
- else if (type) {
563
- valueStr[i] = this.toSqlStr(value[i], type);
564
- }
565
- else {
566
- basicType = typeof value[i];
567
- if (basicType === "object") {
568
- type = this.getClassType(value[i]);
569
- }
570
- else
571
- type = basicType;
572
- valueStr[i] = this.toSqlStr(value[i], type);
573
- }
574
- }
575
- return "ARRAY[" + valueStr.join(",") + "]";
576
- },
577
- ],
578
- [
579
- Date,
580
- function (value) {
581
- return SqlValuesCreator.string(value.toISOString());
582
- },
583
- ],
584
- ]);
585
-
586
- var _a;
587
- /**
588
- * @public ChainSelectWhere 的默认实现
589
- */
590
- class SqlSelectChain extends SqlTextStatementDataset {
591
- where(param) {
592
- return new SqlSelectChain(this.toString() + where(param));
593
- }
594
- groupBy(columns) {
595
- let sql = this.toString();
596
- if (typeof columns === "string")
597
- sql += " GROUP BY " + columns;
598
- else
599
- sql += " GROUP BY " + columns.join(",");
600
- return new SqlSelectChain(sql);
601
- }
602
- having(param) {
603
- return new SqlSelectChain(this.toString() + having(param));
604
- }
605
- orderBy(param) {
606
- return new SqlSelectChain(this.toString() + orderBy(param));
607
- }
608
- limit(limit, offset) {
609
- let sql = this.toString();
610
- let type;
611
- if (limit) {
612
- type = typeof limit;
613
- if (type === "number" || type === "bigint")
614
- sql += "\nLIMIT " + limit;
615
- else
616
- throw new TypeError("limit 必须是个整数:" + limit);
617
- }
618
- if (offset) {
619
- type = typeof offset;
620
- if (type === "number" || type === "bigint")
621
- sql += "\nOFFSET " + offset;
622
- else
623
- throw new TypeError("offset 必须是个整数:" + limit);
624
- }
625
- return new SqlTextStatementDataset(sql);
626
- }
627
- }
628
- function fromAs(selectable, as) {
629
- if (typeof selectable === "function")
630
- selectable = selectable();
631
- let sql = typeof selectable === "string" ? selectable : selectable.toSelect();
632
- if (as)
633
- sql += " AS " + as;
634
- return sql;
635
- }
636
- /** @public */
637
- class Selection {
638
- static from(selectable, as) {
639
- return new this(selectable, as);
640
- }
641
- #sql;
642
- constructor(selectable, as) {
643
- this.#sql = fromAs(selectable, as);
644
- }
645
- toString() {
646
- return "FROM " + this.#sql;
647
- }
648
- #join(type, selectable, as, on) {
649
- let sql = this.#sql + "\n" + type + " " + fromAs(selectable, as);
650
- if (on) {
651
- sql += " ON " + condition(on);
652
- }
653
- return new _a(sql);
654
- }
655
- fullJoin(selectable, as, on) {
656
- return this.#join("FULL JOIN", selectable, as, on);
657
- }
658
- innerJoin(selectable, as, on) {
659
- return this.#join("INNER JOIN", selectable, as, on);
660
- }
661
- leftJoin(selectable, as, on) {
662
- return this.#join("LEFT JOIN", selectable, as, on);
663
- }
664
- rightJoin(selectable, as, on) {
665
- return this.#join("RIGHT JOIN", selectable, as, on);
666
- }
667
- naturalJoin(selectable, as) {
668
- return this.#join("NATURAL JOIN", selectable, as);
669
- }
670
- crossJoin(selectable, as) {
671
- return this.#join("CROSS JOIN", selectable, as);
672
- }
673
- from(selectable, as) {
674
- return new _a(this.#sql + "," + fromAs(selectable, as));
675
- }
676
- select(columnsIn) {
677
- if (typeof columnsIn === "function")
678
- columnsIn = columnsIn();
679
- let sql = "SELECT " + selectColumns(columnsIn);
680
- sql += "\n" + this.toString();
681
- return new SqlSelectChain(sql);
682
- }
683
- }
684
- _a = Selection;
685
-
686
- class SqlChainModify extends SqlStatement {
687
- sql;
688
- constructor(sql) {
689
- super();
690
- this.sql = sql;
691
- }
692
- returning(returns) {
693
- if (typeof returns === "function")
694
- returns = returns();
695
- let columnsStr;
696
- if (returns === "*") {
697
- columnsStr = "*";
698
- }
699
- else {
700
- columnsStr = selectColumns(returns);
701
- }
702
- let sql = this.toString() + "\nRETURNING " + columnsStr;
703
- return new SqlTextStatementDataset(sql);
704
- }
705
- onConflict(onConflict) {
706
- if (typeof onConflict === "function")
707
- onConflict = onConflict();
708
- if (typeof onConflict !== "string")
709
- onConflict = onConflict.join(",");
710
- let sql = this.toString() + `\nON CONFLICT (${onConflict})`;
711
- return new SqlInsertConflictBranch(sql);
712
- }
713
- where(where$1) {
714
- const sql = where(where$1);
715
- return new SqlChainModify(this.toString() + sql);
716
- }
717
- toString() {
718
- return this.sql;
719
- }
720
- }
721
- class SqlInsertConflictBranch {
722
- sql;
723
- constructor(sql) {
724
- this.sql = sql;
725
- }
726
- doUpdate(set) {
727
- if (typeof set === "function")
728
- set = set();
729
- let sql = this.sql;
730
- if (typeof set === "object") {
731
- sql += "\nDO UPDATE ";
732
- sql += createUpdateSetFromObject(set);
733
- }
734
- else if (set)
735
- sql += "DO UPDATE SET\n" + set;
736
- else
737
- sql += "DO NOTHING";
738
- return new SqlChainModify(sql);
739
- }
740
- doNotThing() {
741
- return new SqlChainModify(this.sql + " DO NOTHING");
742
- }
743
- }
744
-
745
- /**
746
- * 数据库表
747
- * @public
748
- */
749
- class DbTable {
750
- name;
751
- constructor(name) {
752
- this.name = name;
753
- }
754
- fromAs(as) {
755
- return new Selection(this.name, as);
756
- }
757
- select(columns, as) {
758
- return this.fromAs(as).select(columns);
759
- }
760
- /**
761
- * INSERT 语句,需要注意 SQL 注入
762
- * @example
763
- * ```ts
764
- * table.insert(["age","name"], "VALUES (18, 'hi'), (17, 'hh')") // INSERT INTO table(age,name) VALUES(18, 'hi'), (17, 'hh')
765
- * ```
766
- */
767
- insert(columns, values) {
768
- if (typeof columns !== "string" || !columns)
769
- throw new TypeError("columns 必须是有效的 string 类型");
770
- if (typeof values === "function")
771
- values = values();
772
- if (typeof values !== "string")
773
- throw new TypeError("values 必须是 string 或 function 类型");
774
- let sql = `INSERT INTO ${this.name}(${columns})\n${values}`;
775
- return new SqlChainModify(sql);
776
- }
777
- /**
778
- * UPDATE 语句,需要注意 SQL 注入
779
- * @example
780
- * ```ts
781
- * table.update("age=3, name='hi'") // "UPDATE table SET age=3, name='hi'"
782
- * table.update({age: "3", name: "'hi'", k1: undefined, k2: ""}) // "UPDATE table SET age=3, name='hi'"
783
- * ```
784
- */
785
- update(values) {
786
- if (typeof values === "function")
787
- values = values();
788
- switch (typeof values) {
789
- case "object": {
790
- let sql = createUpdateSetFromObject(values);
791
- return new SqlChainModify("UPDATE " + this.name + " " + sql);
792
- }
793
- case "string":
794
- return new SqlChainModify("UPDATE " + this.name + " SET\n" + values);
795
- default:
796
- throw new TypeError("参数 values 错误");
797
- }
798
- }
799
- delete(option = {}) {
800
- let sql = "DELETE FROM " + this.name;
801
- sql += where(option.where);
802
- return new SqlChainModify(sql);
803
- }
804
- toSelect() {
805
- return this.name;
806
- }
807
- }
808
-
809
- /** @public */
810
- class DbTableQuery extends DbTable {
811
- statement;
812
- constructor(name, statement) {
813
- super(name);
814
- this.statement = statement;
815
- }
816
- insert(values_column, _values) {
817
- if (_values)
818
- return super.insert(values_column, _values);
819
- let values = values_column;
820
- if (typeof values === "function")
821
- values = values();
822
- if (typeof values !== "object")
823
- throw new TypeError("values 类型错误");
824
- let valuesStr;
825
- let insertCol;
826
- if (values instanceof Array) {
827
- if (values.length === 0)
828
- throw new Error("值不能为空");
829
- insertCol = Array.from(getObjectListKeys(values));
830
- valuesStr = `VALUES\n${this.statement.objectListToValuesList(values, insertCol)}`;
831
- }
832
- else {
833
- insertCol = Object.keys(values);
834
- valuesStr = `VALUES\n(${this.statement.objectToValues(values, insertCol)})`;
835
- }
836
- if (insertCol.length === 0)
837
- throw new Error("插入列不能为空");
838
- const columnStr = insertCol.join(",");
839
- let sql = `INSERT INTO ${this.name} (${columnStr})\n${valuesStr}`;
840
- return new SqlChainModify(sql);
841
- }
842
- /**
843
- * UPDATE 语句,与 update() 不同的是,它会将值进行安全转换
844
- * @example
845
- * ```ts
846
- * table.update({age:3, name:"hi"}, true) // "UPDATE table SET age=3, name='hi'"
847
- * ```
848
- */
849
- updateFrom(values) {
850
- if (typeof values === "function")
851
- values = values();
852
- let setStr;
853
- if (typeof values === "string")
854
- setStr = values;
855
- else {
856
- const updateKey = Object.entries(values);
857
- let setList = [];
858
- for (const [k, v] of updateKey) {
859
- if (v === undefined)
860
- continue;
861
- setList.push(k + "= " + this.statement.toSqlStr(v));
862
- }
863
- setStr = setList.join(",\n");
864
- }
865
- if (!setStr)
866
- throw new Error("值不能为空");
867
- let sql = `UPDATE ${this.name} SET\n${setStr}`;
868
- return new SqlChainModify(sql);
869
- }
870
- }
871
-
872
- /**
873
- * 表格列的信息
874
- * @public
875
- */
876
- class ColumnMeta {
877
- type;
878
- sqlType;
879
- notNull;
880
- isArray;
881
- sqlDefault;
882
- constructor(type,
883
- /** 数据库原始数据类型 */
884
- sqlType,
885
- /** 是否非空 */
886
- notNull = false,
887
- /** 是否是数组类型 */
888
- isArray = false,
889
- /** 数据库原始默认值 */
890
- sqlDefault) {
891
- this.type = type;
892
- this.sqlType = sqlType;
893
- this.notNull = notNull;
894
- this.isArray = isArray;
895
- this.sqlDefault = sqlDefault;
896
- }
897
- /** 校验 value 的类型 */
898
- checkValue(value) {
899
- if (typeof this.type === "function")
900
- return value instanceof this.type;
901
- return this.type.is(value);
902
- }
903
- }
904
- /**
905
- * 数据库类型到JS类型的映射
906
- * @public
907
- */
908
- class YourTypeMap {
909
- typeMap;
910
- static create(rawTypeMap) {
911
- return new this(rawTypeMap);
912
- }
913
- constructor(typeMap = {}) {
914
- this.typeMap = typeMap;
915
- }
916
- genColumn(type, notNull, defaultValue) {
917
- const constructor = Reflect.get(this.typeMap, type);
918
- const column = new ColumnMeta(constructor, type, notNull, false, defaultValue);
919
- return column;
920
- }
921
- genArrColumn(type, notNull, defaultValue) {
922
- const constructor = Reflect.get(this.typeMap, type);
923
- const column = new ColumnMeta(constructor, type + "[]", notNull, true, defaultValue);
924
- return column;
925
- }
926
- }
927
- function baseType(v) {
928
- return typeof v === this.name;
929
- }
930
- /**
931
- * 自定义数据类型
932
- * @public
933
- */
934
- class CustomDbType {
935
- is;
936
- name;
937
- static bigint = new CustomDbType(baseType, "bigint");
938
- static number = new CustomDbType(baseType, "number");
939
- static string = new CustomDbType(baseType, "string");
940
- static boolean = new CustomDbType(baseType, "boolean");
941
- constructor(is, name) {
942
- this.is = is;
943
- this.name = name;
944
- }
945
- }
946
-
947
- /** @public */
948
- class TypeChecker {
949
- map;
950
- constructor(map) {
951
- this.map = map;
952
- }
953
- check(value) {
954
- const map = this.map;
955
- let v;
956
- for (const [k, expect] of map) {
957
- v = value[k];
958
- let err;
959
- if (v === null) {
960
- if (expect.notNull)
961
- throw new Error(`${k} 不能为空`);
962
- continue;
963
- }
964
- else if (v === undefined) {
965
- if (expect.sqlDefault === undefined && expect.notNull)
966
- throw new Error(`${k} 不能为 undefined`);
967
- continue;
968
- }
969
- else if (expect.isArray) {
970
- if (v instanceof Array)
971
- err = this.checkArray(v, expect.type);
972
- else
973
- err = getErrStr(`Array<${expect.type.name}>`, typeof v);
974
- }
975
- else {
976
- err = this.checkItem(v, expect.type);
977
- }
978
- if (err)
979
- throw new Error(`Key ${k} error: ${err}`);
980
- }
981
- return value;
982
- }
983
- checkList(value) {
984
- let i = 0;
985
- try {
986
- for (let i = 0; i < value.length; i++) {
987
- this.check(value[i]);
988
- }
989
- return value;
990
- }
991
- catch (error) {
992
- throw new Error(`Item ${i}, ${error.message}`);
993
- }
994
- }
995
- checkArray(v, expect) {
996
- let err;
997
- for (let i = 0; i < v.length; i++) {
998
- err = this.checkItem(v[i], expect);
999
- if (err)
1000
- return `Item[${i}] ${err}`;
1001
- }
1002
- }
1003
- checkItem(v, expect) {
1004
- if (expect instanceof CustomDbType) {
1005
- if (expect.is(v))
1006
- return;
1007
- }
1008
- else {
1009
- if (v instanceof expect)
1010
- return;
1011
- }
1012
- let actName = typeof v;
1013
- if (actName === "object") {
1014
- if (v === null)
1015
- actName = "null";
1016
- else
1017
- actName = v.constructor?.name ?? "object";
1018
- }
1019
- return getErrStr(expect.name, typeof v);
1020
- }
1021
- }
1022
- function getErrStr(expect, actual) {
1023
- return `Expect ${expect}, Actual ${actual}`;
1024
- }
1025
-
1026
- /**
1027
- * 完整数据库表数据
1028
- * @public
1029
- */
1030
- class YourTable extends DbTableQuery {
1031
- define;
1032
- constructor(name, define, sqlValue) {
1033
- super(name, sqlValue);
1034
- this.define = define;
1035
- this.columns = Object.keys(define);
1036
- }
1037
- columns;
1038
- getColumnMeta(name) {
1039
- return Reflect.get(this.define, name);
1040
- }
1041
- createTypeChecker(keys) {
1042
- let map = new Map();
1043
- let defined = this.define;
1044
- let k;
1045
- for (let i = 0; i < keys.length; i++) {
1046
- k = keys[i];
1047
- if (defined[k] === undefined)
1048
- throw new Error(`key ${k} 未定义`);
1049
- map.set(k, defined[k]);
1050
- }
1051
- return new TypeChecker(map);
1052
- }
1053
- }
1054
-
1055
- /**
1056
- * 默认的 SqlValuesCreator 实列
1057
- * @public
1058
- */
1059
- const v = SqlValuesCreator.create(pgSqlTransformer);
1060
-
1061
- export { ColumnMeta, CustomDbType, DbTable, DbTableQuery, Selection, SqlRaw, SqlSelectChain, SqlStatement, SqlStatementDataset, SqlTextStatementDataset, SqlValuesCreator, TypeChecker, YourTable, YourTypeMap, getObjectListKeys, having, orderBy, pgSqlTransformer, selectColumns, v, where };