@asla/yoursql 0.8.2 → 0.8.4
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/client/DbCursor.js +21 -0
- package/dist/client/DbPoolConnection.js +56 -0
- package/dist/client/DbPoolTransaction.js +98 -0
- package/dist/client/DbQuery.js +30 -0
- package/dist/client/errors.js +14 -0
- package/dist/client/mod.js +5 -0
- package/dist/sql_gen/mod.d.ts +3 -1
- package/dist/sql_gen/mod.js +19 -0
- package/dist/sql_gen/select/DbTable.d.ts +8 -7
- package/dist/sql_gen/select/DbTable.js +70 -0
- package/dist/sql_gen/select/TableQuery.d.ts +4 -4
- package/dist/sql_gen/select/TableQuery.js +68 -0
- package/dist/sql_gen/select/_statement.js +60 -0
- package/dist/sql_gen/select/chain_base.d.ts +44 -0
- package/dist/sql_gen/select/chain_base.js +27 -0
- package/dist/sql_gen/select/chain_modify.d.ts +33 -0
- package/dist/sql_gen/select/chain_select.d.ts +28 -0
- package/dist/sql_gen/select/query_chain_insert.d.ts +7 -5
- package/dist/sql_gen/select/query_chain_insert.js +67 -0
- package/dist/sql_gen/select/query_chain_select.d.ts +11 -10
- package/dist/sql_gen/select/query_chain_select.js +105 -0
- package/dist/sql_gen/sql_value/db_type.js +40 -0
- package/dist/sql_gen/sql_value/sql_value.d.ts +1 -1
- package/dist/sql_gen/sql_value/sql_value.js +304 -0
- package/dist/sql_gen/util.js +166 -0
- package/dist/sql_gen/your_table/checker.js +82 -0
- package/dist/sql_gen/your_table/infer_db_type.js +76 -0
- package/dist/sql_gen/your_table/table.js +33 -0
- package/package.json +3 -3
- package/dist/client.js +0 -209
- package/dist/sql_gen/select/query_chain_abstract.d.ts +0 -91
- package/dist/sql_gen.js +0 -1061
|
@@ -1,20 +1,22 @@
|
|
|
1
1
|
import { ConditionParam, Constructable, SelectParam } from "../util.ts";
|
|
2
|
-
import { SqlStatementDataset, SqlStatement
|
|
2
|
+
import { SqlStatementDataset, SqlStatement } from "./chain_base.ts";
|
|
3
|
+
import { ChainAfterConflictDo, ChainModifyReturning, ChainInsert, ChainDelete, ChainUpdate } from "./chain_modify.ts";
|
|
3
4
|
import { TableType } from "./type.ts";
|
|
4
|
-
export declare class SqlChainModify<T extends TableType = {}> extends SqlStatement implements
|
|
5
|
+
export declare class SqlChainModify<T extends TableType = {}> extends SqlStatement implements ChainInsert<T>, ChainUpdate<T>, ChainDelete<T> {
|
|
5
6
|
readonly sql: string;
|
|
6
7
|
constructor(sql: string);
|
|
7
8
|
returning<R extends {}>(returns: Constructable<SelectParam | "*">): SqlStatementDataset<R>;
|
|
8
|
-
onConflict(onConflict: Constructable<readonly string[] | string>):
|
|
9
|
+
onConflict(onConflict: Constructable<readonly string[] | string>): ChainAfterConflictDo<T>;
|
|
9
10
|
where(where: Constructable<ConditionParam | void>): ChainModifyReturning<T>;
|
|
10
11
|
toString(): string;
|
|
11
12
|
}
|
|
12
|
-
export declare class SqlInsertConflictBranch<T extends TableType = {}> implements
|
|
13
|
+
export declare class SqlInsertConflictBranch<T extends TableType = {}> implements ChainAfterConflictDo<T> {
|
|
13
14
|
readonly sql: string;
|
|
14
15
|
constructor(sql: string);
|
|
15
16
|
doUpdate(set?: Constructable<string | {
|
|
16
17
|
[key: string]: string | undefined;
|
|
17
|
-
}>):
|
|
18
|
+
}>): ChainModifyReturning<T>;
|
|
18
19
|
doNotThing(): ChainModifyReturning<T>;
|
|
20
|
+
toString(): string;
|
|
19
21
|
}
|
|
20
22
|
//# sourceMappingURL=query_chain_insert.d.ts.map
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { selectColumns, where } from '../util.js';
|
|
2
|
+
import { createUpdateSetFromObject } from './_statement.js';
|
|
3
|
+
import { SqlStatement, SqlTextStatementDataset } from './chain_base.js';
|
|
4
|
+
|
|
5
|
+
class SqlChainModify extends SqlStatement {
|
|
6
|
+
sql;
|
|
7
|
+
constructor(sql) {
|
|
8
|
+
super();
|
|
9
|
+
this.sql = sql;
|
|
10
|
+
}
|
|
11
|
+
returning(returns) {
|
|
12
|
+
if (typeof returns === "function")
|
|
13
|
+
returns = returns();
|
|
14
|
+
let columnsStr;
|
|
15
|
+
if (returns === "*") {
|
|
16
|
+
columnsStr = "*";
|
|
17
|
+
}
|
|
18
|
+
else {
|
|
19
|
+
columnsStr = selectColumns(returns);
|
|
20
|
+
}
|
|
21
|
+
let sql = this.toString() + "\nRETURNING " + columnsStr;
|
|
22
|
+
return new SqlTextStatementDataset(sql);
|
|
23
|
+
}
|
|
24
|
+
onConflict(onConflict) {
|
|
25
|
+
if (typeof onConflict === "function")
|
|
26
|
+
onConflict = onConflict();
|
|
27
|
+
if (typeof onConflict !== "string")
|
|
28
|
+
onConflict = onConflict.join(",");
|
|
29
|
+
let sql = this.toString() + `\nON CONFLICT (${onConflict})`;
|
|
30
|
+
return new SqlInsertConflictBranch(sql);
|
|
31
|
+
}
|
|
32
|
+
where(where$1) {
|
|
33
|
+
const sql = where(where$1);
|
|
34
|
+
return new SqlChainModify(this.toString() + sql);
|
|
35
|
+
}
|
|
36
|
+
toString() {
|
|
37
|
+
return this.sql;
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
class SqlInsertConflictBranch {
|
|
41
|
+
sql;
|
|
42
|
+
constructor(sql) {
|
|
43
|
+
this.sql = sql;
|
|
44
|
+
}
|
|
45
|
+
doUpdate(set) {
|
|
46
|
+
if (typeof set === "function")
|
|
47
|
+
set = set();
|
|
48
|
+
let sql = this.sql;
|
|
49
|
+
if (typeof set === "object") {
|
|
50
|
+
sql += "\nDO UPDATE ";
|
|
51
|
+
sql += createUpdateSetFromObject(set);
|
|
52
|
+
}
|
|
53
|
+
else if (set)
|
|
54
|
+
sql += "DO UPDATE\n" + set;
|
|
55
|
+
else
|
|
56
|
+
sql += "DO NOTHING";
|
|
57
|
+
return new SqlChainModify(sql);
|
|
58
|
+
}
|
|
59
|
+
doNotThing() {
|
|
60
|
+
return new SqlChainModify(this.sql + " DO NOTHING");
|
|
61
|
+
}
|
|
62
|
+
toString() {
|
|
63
|
+
return this.sql;
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
export { SqlChainModify, SqlInsertConflictBranch };
|
|
@@ -1,15 +1,16 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { SqlSelectable, SqlTextStatementDataset } from "./chain_base.ts";
|
|
2
|
+
import { ChainSelect, ChainSelectAfterHaving, ChainSelectAfterLimit, ChainSelectAfterOrderBy, ChainSelectAfterGroupBy, ChainSelectAfterWhere } from "./chain_select.ts";
|
|
2
3
|
import { OrderByParam, ConditionParam, SelectParam, Constructable } from "../util.ts";
|
|
3
4
|
import type { TableType } from "./type.ts";
|
|
4
5
|
/**
|
|
5
6
|
* @public ChainSelectWhere 的默认实现
|
|
6
7
|
*/
|
|
7
|
-
export declare class SqlSelectChain<T extends TableType> extends SqlTextStatementDataset<T> implements
|
|
8
|
-
where(param?: Constructable<ConditionParam | void>):
|
|
9
|
-
groupBy(columns: string | string[]):
|
|
10
|
-
having(param?: Constructable<ConditionParam | void>):
|
|
11
|
-
orderBy(param?: Constructable<OrderByParam | void>):
|
|
12
|
-
limit(limit?: number, offset?: number):
|
|
8
|
+
export declare class SqlSelectChain<T extends TableType> extends SqlTextStatementDataset<T> implements ChainSelect<T> {
|
|
9
|
+
where(param?: Constructable<ConditionParam | void>): ChainSelectAfterWhere<T>;
|
|
10
|
+
groupBy(columns: string | string[]): ChainSelectAfterGroupBy<T>;
|
|
11
|
+
having(param?: Constructable<ConditionParam | void>): ChainSelectAfterHaving<T>;
|
|
12
|
+
orderBy(param?: Constructable<OrderByParam | void>): ChainSelectAfterOrderBy<T>;
|
|
13
|
+
limit(limit?: number, offset?: number): ChainSelectAfterLimit<T>;
|
|
13
14
|
}
|
|
14
15
|
/** @public */
|
|
15
16
|
export declare class Selection {
|
|
@@ -25,7 +26,7 @@ export declare class Selection {
|
|
|
25
26
|
crossJoin(selectable: Constructable<SqlSelectable | string>, as?: string | undefined): Selection;
|
|
26
27
|
from(selectable: Constructable<SqlSelectable | string>, as?: string): Selection;
|
|
27
28
|
/** 选择全部列 */
|
|
28
|
-
select<T extends TableType = Record<string, any>>(columns: "*"):
|
|
29
|
+
select<T extends TableType = Record<string, any>>(columns: "*"): ChainSelect<T>;
|
|
29
30
|
/**
|
|
30
31
|
* 自定义SQL选择语句
|
|
31
32
|
* @example
|
|
@@ -33,7 +34,7 @@ export declare class Selection {
|
|
|
33
34
|
* selection.select("t.age, count(*) AS c") // SELECT t.age,count(*) AS c FROM ...
|
|
34
35
|
* ```
|
|
35
36
|
*/
|
|
36
|
-
select(columns: Constructable<SelectParam>):
|
|
37
|
+
select(columns: Constructable<SelectParam>): ChainSelect<Record<string, any>>;
|
|
37
38
|
/**
|
|
38
39
|
* 通过 object 选择 列
|
|
39
40
|
* @example
|
|
@@ -43,6 +44,6 @@ export declare class Selection {
|
|
|
43
44
|
*/
|
|
44
45
|
select<T extends TableType>(columns: Constructable<{
|
|
45
46
|
[key in keyof T]: string | boolean;
|
|
46
|
-
} | string>):
|
|
47
|
+
} | string>): ChainSelect<T>;
|
|
47
48
|
}
|
|
48
49
|
//# sourceMappingURL=query_chain_select.d.ts.map
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
import { SqlTextStatementDataset } from './chain_base.js';
|
|
2
|
+
import { where, having, orderBy, selectColumns } from '../util.js';
|
|
3
|
+
import { condition } from './_statement.js';
|
|
4
|
+
|
|
5
|
+
var _a;
|
|
6
|
+
/**
|
|
7
|
+
* @public ChainSelectWhere 的默认实现
|
|
8
|
+
*/
|
|
9
|
+
class SqlSelectChain extends SqlTextStatementDataset {
|
|
10
|
+
where(param) {
|
|
11
|
+
return new SqlSelectChain(this.toString() + where(param));
|
|
12
|
+
}
|
|
13
|
+
groupBy(columns) {
|
|
14
|
+
let sql = this.toString();
|
|
15
|
+
if (typeof columns === "string")
|
|
16
|
+
sql += " GROUP BY " + columns;
|
|
17
|
+
else
|
|
18
|
+
sql += " GROUP BY " + columns.join(",");
|
|
19
|
+
return new SqlSelectChain(sql);
|
|
20
|
+
}
|
|
21
|
+
having(param) {
|
|
22
|
+
return new SqlSelectChain(this.toString() + having(param));
|
|
23
|
+
}
|
|
24
|
+
orderBy(param) {
|
|
25
|
+
return new SqlSelectChain(this.toString() + orderBy(param));
|
|
26
|
+
}
|
|
27
|
+
limit(limit, offset) {
|
|
28
|
+
let sql = this.toString();
|
|
29
|
+
let type;
|
|
30
|
+
if (limit) {
|
|
31
|
+
type = typeof limit;
|
|
32
|
+
if (type === "number" || type === "bigint")
|
|
33
|
+
sql += "\nLIMIT " + limit;
|
|
34
|
+
else
|
|
35
|
+
throw new TypeError("limit 必须是个整数:" + limit);
|
|
36
|
+
}
|
|
37
|
+
if (offset) {
|
|
38
|
+
type = typeof offset;
|
|
39
|
+
if (type === "number" || type === "bigint")
|
|
40
|
+
sql += "\nOFFSET " + offset;
|
|
41
|
+
else
|
|
42
|
+
throw new TypeError("offset 必须是个整数:" + limit);
|
|
43
|
+
}
|
|
44
|
+
return new SqlTextStatementDataset(sql);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
function fromAs(selectable, as) {
|
|
48
|
+
if (typeof selectable === "function")
|
|
49
|
+
selectable = selectable();
|
|
50
|
+
let sql = typeof selectable === "string" ? selectable : selectable.toSelect();
|
|
51
|
+
if (as)
|
|
52
|
+
sql += " AS " + as;
|
|
53
|
+
return sql;
|
|
54
|
+
}
|
|
55
|
+
/** @public */
|
|
56
|
+
class Selection {
|
|
57
|
+
static from(selectable, as) {
|
|
58
|
+
return new this(selectable, as);
|
|
59
|
+
}
|
|
60
|
+
#sql;
|
|
61
|
+
constructor(selectable, as) {
|
|
62
|
+
this.#sql = fromAs(selectable, as);
|
|
63
|
+
}
|
|
64
|
+
toString() {
|
|
65
|
+
return "FROM " + this.#sql;
|
|
66
|
+
}
|
|
67
|
+
#join(type, selectable, as, on) {
|
|
68
|
+
let sql = this.#sql + "\n" + type + " " + fromAs(selectable, as);
|
|
69
|
+
if (on) {
|
|
70
|
+
sql += " ON " + condition(on);
|
|
71
|
+
}
|
|
72
|
+
return new _a(sql);
|
|
73
|
+
}
|
|
74
|
+
fullJoin(selectable, as, on) {
|
|
75
|
+
return this.#join("FULL JOIN", selectable, as, on);
|
|
76
|
+
}
|
|
77
|
+
innerJoin(selectable, as, on) {
|
|
78
|
+
return this.#join("INNER JOIN", selectable, as, on);
|
|
79
|
+
}
|
|
80
|
+
leftJoin(selectable, as, on) {
|
|
81
|
+
return this.#join("LEFT JOIN", selectable, as, on);
|
|
82
|
+
}
|
|
83
|
+
rightJoin(selectable, as, on) {
|
|
84
|
+
return this.#join("RIGHT JOIN", selectable, as, on);
|
|
85
|
+
}
|
|
86
|
+
naturalJoin(selectable, as) {
|
|
87
|
+
return this.#join("NATURAL JOIN", selectable, as);
|
|
88
|
+
}
|
|
89
|
+
crossJoin(selectable, as) {
|
|
90
|
+
return this.#join("CROSS JOIN", selectable, as);
|
|
91
|
+
}
|
|
92
|
+
from(selectable, as) {
|
|
93
|
+
return new _a(this.#sql + "," + fromAs(selectable, as));
|
|
94
|
+
}
|
|
95
|
+
select(columnsIn) {
|
|
96
|
+
if (typeof columnsIn === "function")
|
|
97
|
+
columnsIn = columnsIn();
|
|
98
|
+
let sql = "SELECT " + selectColumns(columnsIn);
|
|
99
|
+
sql += "\n" + this.toString();
|
|
100
|
+
return new SqlSelectChain(sql);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
_a = Selection;
|
|
104
|
+
|
|
105
|
+
export { Selection, SqlSelectChain };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { SqlValuesCreator } from './sql_value.js';
|
|
2
|
+
|
|
3
|
+
/** @public PgSql 转换器 */
|
|
4
|
+
const pgSqlTransformer = new Map([
|
|
5
|
+
[
|
|
6
|
+
Array,
|
|
7
|
+
function encodePgArray(value) {
|
|
8
|
+
if (value.length === 0)
|
|
9
|
+
return "NULL";
|
|
10
|
+
const valueStr = [];
|
|
11
|
+
let type;
|
|
12
|
+
let basicType;
|
|
13
|
+
for (let i = 0; i < value.length; i++) {
|
|
14
|
+
if (value[i] === null || value[i] === undefined)
|
|
15
|
+
valueStr[i] = this.toSqlStr(value[i]);
|
|
16
|
+
else if (type) {
|
|
17
|
+
valueStr[i] = this.toSqlStr(value[i], type);
|
|
18
|
+
}
|
|
19
|
+
else {
|
|
20
|
+
basicType = typeof value[i];
|
|
21
|
+
if (basicType === "object") {
|
|
22
|
+
type = this.getClassType(value[i]);
|
|
23
|
+
}
|
|
24
|
+
else
|
|
25
|
+
type = basicType;
|
|
26
|
+
valueStr[i] = this.toSqlStr(value[i], type);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
return "ARRAY[" + valueStr.join(",") + "]";
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
[
|
|
33
|
+
Date,
|
|
34
|
+
function (value) {
|
|
35
|
+
return SqlValuesCreator.string(value.toISOString());
|
|
36
|
+
},
|
|
37
|
+
],
|
|
38
|
+
]);
|
|
39
|
+
|
|
40
|
+
export { pgSqlTransformer };
|
|
@@ -0,0 +1,304 @@
|
|
|
1
|
+
import { getObjectListKeys } from '../util.js';
|
|
2
|
+
import { SqlStatementDataset } from '../select/chain_base.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* SQL 原始字符类。可以使用 String 类代替,这只是为了推断类型
|
|
6
|
+
* @public
|
|
7
|
+
*/
|
|
8
|
+
class SqlRaw extends String {
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* SQL value 生成器
|
|
12
|
+
* @public
|
|
13
|
+
*/
|
|
14
|
+
class SqlValuesCreator {
|
|
15
|
+
static create(map) {
|
|
16
|
+
const obj = new this(map);
|
|
17
|
+
const fn = obj.toSqlStr.bind(obj);
|
|
18
|
+
Reflect.setPrototypeOf(fn, obj);
|
|
19
|
+
return fn;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* 将字符串转为 SQL 的字符串值的形式(单引号会被转义)。
|
|
23
|
+
* @example 输入 a'b'c , 返回 a''b''c.
|
|
24
|
+
*/
|
|
25
|
+
static string(value) {
|
|
26
|
+
return "'" + value.replaceAll("'", "''") + "'";
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* @param map - 自定义对象转换
|
|
30
|
+
*/
|
|
31
|
+
constructor(map) {
|
|
32
|
+
this._map = new Map(map);
|
|
33
|
+
}
|
|
34
|
+
setTransformer(type_map, encoder) {
|
|
35
|
+
if (typeof type_map === "function") {
|
|
36
|
+
if (encoder)
|
|
37
|
+
this._map.set(type_map, encoder);
|
|
38
|
+
else
|
|
39
|
+
this._map.delete(type_map);
|
|
40
|
+
}
|
|
41
|
+
else {
|
|
42
|
+
for (const [type, encoder] of type_map) {
|
|
43
|
+
if (typeof type === "function" && typeof encoder === "function") {
|
|
44
|
+
this._map.set(type, encoder);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
_map;
|
|
50
|
+
/**
|
|
51
|
+
* 将 JS 对象转为 SQL 的字符值的形式 。 undefined 将被转换为 DEFAULT
|
|
52
|
+
* ```ts
|
|
53
|
+
* const v=SqlValuesCreator.create()
|
|
54
|
+
* v() 和 v.toSqlStr() 是等价的
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
toSqlStr(value, assertJsType) {
|
|
58
|
+
if (value === null)
|
|
59
|
+
return "NULL";
|
|
60
|
+
else if (value === undefined)
|
|
61
|
+
return "DEFAULT";
|
|
62
|
+
let basicType = typeof value;
|
|
63
|
+
if (assertJsType) {
|
|
64
|
+
if (typeof assertJsType === "function") {
|
|
65
|
+
if (basicType !== "object")
|
|
66
|
+
throw new AssertError("object", basicType);
|
|
67
|
+
let type = this._map.get(assertJsType);
|
|
68
|
+
if (!type) {
|
|
69
|
+
if (assertJsType === Object)
|
|
70
|
+
return this.defaultObject(value);
|
|
71
|
+
throw new Error("类型不存在");
|
|
72
|
+
}
|
|
73
|
+
return type.call(this, value);
|
|
74
|
+
}
|
|
75
|
+
else if (basicType !== assertJsType) {
|
|
76
|
+
throw new AssertError(assertJsType, basicType);
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
switch (basicType) {
|
|
80
|
+
case "bigint":
|
|
81
|
+
return value.toString();
|
|
82
|
+
case "number":
|
|
83
|
+
return value.toString();
|
|
84
|
+
case "string":
|
|
85
|
+
return SqlValuesCreator.string(value);
|
|
86
|
+
case "boolean":
|
|
87
|
+
return value.toString();
|
|
88
|
+
case "object": {
|
|
89
|
+
if (value instanceof String)
|
|
90
|
+
return value.toString();
|
|
91
|
+
const Class = this.getClassType(value);
|
|
92
|
+
if (Class)
|
|
93
|
+
return this._map.get(Class).call(this, value);
|
|
94
|
+
return this.defaultObject(value);
|
|
95
|
+
}
|
|
96
|
+
case "undefined":
|
|
97
|
+
return "DEFAULT";
|
|
98
|
+
default:
|
|
99
|
+
//function、symbol
|
|
100
|
+
let type = typeof value;
|
|
101
|
+
throw new Error("不支持 " + type + " 类型");
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* @deprecated 已废弃
|
|
106
|
+
* 获取值对应的 SqlValueEncoder
|
|
107
|
+
*/
|
|
108
|
+
getObjectType(value) {
|
|
109
|
+
for (const Class of this._map.keys()) {
|
|
110
|
+
if (value instanceof Class)
|
|
111
|
+
return this._map.get(Class);
|
|
112
|
+
}
|
|
113
|
+
return this.defaultObject;
|
|
114
|
+
}
|
|
115
|
+
/** 获取值对应已定义的类 */
|
|
116
|
+
getClassType(value) {
|
|
117
|
+
for (const Class of this._map.keys()) {
|
|
118
|
+
if (value instanceof Class)
|
|
119
|
+
return Class;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
defaultObject(value) {
|
|
123
|
+
return SqlValuesCreator.string(JSON.stringify(value));
|
|
124
|
+
}
|
|
125
|
+
objectListToValuesList(objectList, keys_types, keepUndefinedKey) {
|
|
126
|
+
if (objectList.length <= 0)
|
|
127
|
+
throw new Error("objectList 不能是空数组");
|
|
128
|
+
let keys;
|
|
129
|
+
let asserts;
|
|
130
|
+
if (!keys_types) {
|
|
131
|
+
keys = Array.from(getObjectListKeys(objectList, keepUndefinedKey));
|
|
132
|
+
asserts = [];
|
|
133
|
+
}
|
|
134
|
+
else if (keys_types instanceof Array) {
|
|
135
|
+
keys = keys_types;
|
|
136
|
+
asserts = [];
|
|
137
|
+
}
|
|
138
|
+
else {
|
|
139
|
+
keys = Object.keys(keys_types);
|
|
140
|
+
asserts = initColumnAssert(keys, keys_types);
|
|
141
|
+
}
|
|
142
|
+
let str = "(" + this._internalObjectToValues(objectList[0], keys, asserts) + ")";
|
|
143
|
+
let i = 1;
|
|
144
|
+
let j;
|
|
145
|
+
let value;
|
|
146
|
+
let rows;
|
|
147
|
+
try {
|
|
148
|
+
for (; i < objectList.length; i++) {
|
|
149
|
+
const object = objectList[i];
|
|
150
|
+
rows = [];
|
|
151
|
+
j = 0;
|
|
152
|
+
for (; j < keys.length; j++) {
|
|
153
|
+
value = object[keys[j]];
|
|
154
|
+
rows[j] = this.toSqlStr(value, asserts[j]?.assertJsType);
|
|
155
|
+
}
|
|
156
|
+
str += ",\n(" + rows.join(",") + ")";
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
catch (error) {
|
|
160
|
+
let message = error instanceof Error ? error.message : String(error);
|
|
161
|
+
throw new Error("第 " + i + " 项,字段 '" + keys[j] + "' 异常," + message);
|
|
162
|
+
}
|
|
163
|
+
return str;
|
|
164
|
+
}
|
|
165
|
+
objectToValues(object, keys_types) {
|
|
166
|
+
let type;
|
|
167
|
+
let keys;
|
|
168
|
+
if (keys_types instanceof Array) {
|
|
169
|
+
keys = keys_types;
|
|
170
|
+
type = [];
|
|
171
|
+
}
|
|
172
|
+
else if (keys_types) {
|
|
173
|
+
keys = Object.keys(keys_types);
|
|
174
|
+
type = initColumnAssert(keys, keys_types);
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
keys = Object.keys(object);
|
|
178
|
+
type = [];
|
|
179
|
+
}
|
|
180
|
+
return this._internalObjectToValues(object, keys, type);
|
|
181
|
+
}
|
|
182
|
+
_internalObjectToValues(object, keys, type) {
|
|
183
|
+
const values = [];
|
|
184
|
+
let i = 0;
|
|
185
|
+
let key;
|
|
186
|
+
let value;
|
|
187
|
+
let assertType;
|
|
188
|
+
try {
|
|
189
|
+
for (; i < keys.length; i++) {
|
|
190
|
+
key = keys[i];
|
|
191
|
+
value = object[key];
|
|
192
|
+
assertType = type[i];
|
|
193
|
+
if (assertType) {
|
|
194
|
+
values[i] = this.toSqlStr(value, assertType.assertJsType);
|
|
195
|
+
if (assertType.sqlType)
|
|
196
|
+
values[i] += "::" + assertType.sqlType;
|
|
197
|
+
}
|
|
198
|
+
else
|
|
199
|
+
values[i] = this.toSqlStr(value);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
catch (error) {
|
|
203
|
+
let message = error instanceof Error ? error.message : String(error);
|
|
204
|
+
throw new Error("字段 '" + key + "' 异常," + message);
|
|
205
|
+
}
|
|
206
|
+
return values.join(",");
|
|
207
|
+
}
|
|
208
|
+
/**
|
|
209
|
+
* 将数组列表转为 SQL 的一个 value
|
|
210
|
+
* @example 返回示例: " 'abc', '6', 'now()' "
|
|
211
|
+
*/
|
|
212
|
+
toValues(values) {
|
|
213
|
+
return values.map((v) => this.toSqlStr(v)).join(",");
|
|
214
|
+
}
|
|
215
|
+
createValues(asName, values, valuesTypes) {
|
|
216
|
+
if (values.length === 0)
|
|
217
|
+
throw new Error("values 不能为空");
|
|
218
|
+
const insertKeys = Object.keys(valuesTypes);
|
|
219
|
+
const defaultValues = [];
|
|
220
|
+
const asserts = new Array(insertKeys.length);
|
|
221
|
+
const valuesStr = new Array(values.length);
|
|
222
|
+
{
|
|
223
|
+
const column0 = new Array(insertKeys.length);
|
|
224
|
+
let columnName;
|
|
225
|
+
let item;
|
|
226
|
+
let sqlType;
|
|
227
|
+
let assertJsType;
|
|
228
|
+
let value;
|
|
229
|
+
for (let i = 0; i < insertKeys.length; i++) {
|
|
230
|
+
columnName = insertKeys[i];
|
|
231
|
+
item = valuesTypes[columnName];
|
|
232
|
+
if (typeof item === "string") {
|
|
233
|
+
sqlType = item;
|
|
234
|
+
defaultValues[i] = "NULL";
|
|
235
|
+
}
|
|
236
|
+
else {
|
|
237
|
+
sqlType = item.sqlType;
|
|
238
|
+
assertJsType = item.assertJsType;
|
|
239
|
+
asserts[i] = assertJsType;
|
|
240
|
+
defaultValues[i] = item.sqlDefault ?? "NULL";
|
|
241
|
+
}
|
|
242
|
+
value = values[0][columnName];
|
|
243
|
+
if (value === undefined)
|
|
244
|
+
column0[i] = defaultValues[i] + "::" + sqlType;
|
|
245
|
+
else
|
|
246
|
+
column0[i] = this.toSqlStr(value, assertJsType) + "::" + sqlType;
|
|
247
|
+
}
|
|
248
|
+
valuesStr[0] = "(" + column0.join(",") + ")";
|
|
249
|
+
}
|
|
250
|
+
let items = new Array(insertKeys.length);
|
|
251
|
+
let value;
|
|
252
|
+
for (let i = 1; i < values.length; i++) {
|
|
253
|
+
for (let j = 0; j < insertKeys.length; j++) {
|
|
254
|
+
value = values[i][insertKeys[j]];
|
|
255
|
+
if (value === undefined)
|
|
256
|
+
items[j] = defaultValues[j];
|
|
257
|
+
else
|
|
258
|
+
items[j] = this.toSqlStr(value, asserts[j]);
|
|
259
|
+
}
|
|
260
|
+
valuesStr[i] = "(" + items.join(",") + ")";
|
|
261
|
+
}
|
|
262
|
+
return new YourValuesAs(insertKeys, asName, valuesStr.join(",\n"));
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
class YourValuesAs extends SqlStatementDataset {
|
|
266
|
+
constructor(columns, asName, valuesStr) {
|
|
267
|
+
super();
|
|
268
|
+
this.#asName = asName;
|
|
269
|
+
this.#valuesStr = valuesStr;
|
|
270
|
+
this.#sql = `(VALUES\n${this.#valuesStr})\nAS ${this.#asName}(${columns.join(",")})`;
|
|
271
|
+
}
|
|
272
|
+
#asName;
|
|
273
|
+
#valuesStr;
|
|
274
|
+
#sql;
|
|
275
|
+
toSelect() {
|
|
276
|
+
return this.#sql;
|
|
277
|
+
}
|
|
278
|
+
toString() {
|
|
279
|
+
return this.#sql;
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
function initColumnAssert(keys, keys_types) {
|
|
283
|
+
let key;
|
|
284
|
+
let value;
|
|
285
|
+
let type = new Array(keys.length);
|
|
286
|
+
for (let i = 0; i < keys.length; i++) {
|
|
287
|
+
key = keys[i];
|
|
288
|
+
value = keys_types[key];
|
|
289
|
+
if (typeof value === "string") {
|
|
290
|
+
type[i] = { sqlType: value };
|
|
291
|
+
}
|
|
292
|
+
else {
|
|
293
|
+
type[i] = value;
|
|
294
|
+
}
|
|
295
|
+
}
|
|
296
|
+
return type;
|
|
297
|
+
}
|
|
298
|
+
class AssertError extends TypeError {
|
|
299
|
+
constructor(assertType, actual) {
|
|
300
|
+
super(`Assert ${assertType} type, Actual ${actual} type`);
|
|
301
|
+
}
|
|
302
|
+
}
|
|
303
|
+
|
|
304
|
+
export { SqlRaw, SqlValuesCreator };
|