@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
|
@@ -0,0 +1,166 @@
|
|
|
1
|
+
import { condition } from './select/_statement.js';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* 获取对象数组中的 key 的集合
|
|
5
|
+
* @public
|
|
6
|
+
* @param keepUndefinedKey - 是否保留值为 undefined 的 key
|
|
7
|
+
*/
|
|
8
|
+
function getObjectListKeys(objectList, keepUndefinedKey) {
|
|
9
|
+
let keys = new Set();
|
|
10
|
+
for (let i = 0; i < objectList.length; i++) {
|
|
11
|
+
let obj = objectList[i];
|
|
12
|
+
let hasKeys = Object.keys(obj);
|
|
13
|
+
let k;
|
|
14
|
+
for (let j = 0; j < hasKeys.length; j++) {
|
|
15
|
+
k = hasKeys[j];
|
|
16
|
+
if (typeof k !== "string")
|
|
17
|
+
continue;
|
|
18
|
+
if (!keepUndefinedKey && obj[k] === undefined)
|
|
19
|
+
continue;
|
|
20
|
+
keys.add(k);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
return keys;
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* 生成 WHERE 语句
|
|
27
|
+
* @public
|
|
28
|
+
* @example
|
|
29
|
+
* ```ts
|
|
30
|
+
* where(['a=1','b=2']) // "\nWHERE a=1 AND b=2"
|
|
31
|
+
* where(['a=1','b=2'],"OR") // "\nWHERE a=1 OR b=2"
|
|
32
|
+
* where("a=1 OR b=2") // "\nWHERE a=1 OR b=2"
|
|
33
|
+
* where(()=>"a=1 OR b=2") // "\nWHERE a=1 AND b=2"
|
|
34
|
+
* where([]) // ""
|
|
35
|
+
* where(undefined) // ""
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
function where(conditions, type) {
|
|
39
|
+
const sql = condition(conditions, type);
|
|
40
|
+
if (sql)
|
|
41
|
+
return "\nWHERE " + sql;
|
|
42
|
+
return "";
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
*
|
|
46
|
+
* 生成 HAVING 语句
|
|
47
|
+
* @public
|
|
48
|
+
*/
|
|
49
|
+
function having(conditions, type) {
|
|
50
|
+
const sql = condition(conditions, type);
|
|
51
|
+
if (sql)
|
|
52
|
+
return "\nHAVING " + sql;
|
|
53
|
+
return "";
|
|
54
|
+
}
|
|
55
|
+
/**
|
|
56
|
+
* @public
|
|
57
|
+
* @example
|
|
58
|
+
* ```ts
|
|
59
|
+
* selectColumns({c1: true, c2: "count(*)", c3: "column"}) // "c1,count(*) AS c2,column as c3"
|
|
60
|
+
* selectColumns("c1,count(*) AS c2,column as c3") // "c1,count(*) AS c2,column as c3"
|
|
61
|
+
* ```
|
|
62
|
+
*/
|
|
63
|
+
function selectColumns(columns) {
|
|
64
|
+
if (typeof columns === "function")
|
|
65
|
+
columns = columns();
|
|
66
|
+
switch (typeof columns) {
|
|
67
|
+
case "string":
|
|
68
|
+
return columns;
|
|
69
|
+
case "object": {
|
|
70
|
+
if (columns instanceof Array) {
|
|
71
|
+
if (columns.length === 0)
|
|
72
|
+
throw new Error("没有选择任何列");
|
|
73
|
+
return columns.join(",");
|
|
74
|
+
}
|
|
75
|
+
else {
|
|
76
|
+
let sql = "";
|
|
77
|
+
const keys = Object.keys(columns);
|
|
78
|
+
if (keys.length === 0)
|
|
79
|
+
throw new Error("没有选择任何列");
|
|
80
|
+
let k = keys[0];
|
|
81
|
+
let v = columns[k];
|
|
82
|
+
if (typeof v === "string")
|
|
83
|
+
sql += v + " AS " + k;
|
|
84
|
+
else
|
|
85
|
+
sql += k;
|
|
86
|
+
for (let i = 1; i < keys.length; i++) {
|
|
87
|
+
k = keys[i];
|
|
88
|
+
v = columns[k];
|
|
89
|
+
sql += ",";
|
|
90
|
+
if (typeof v === "string")
|
|
91
|
+
sql += v + " AS " + k;
|
|
92
|
+
else
|
|
93
|
+
sql += k;
|
|
94
|
+
}
|
|
95
|
+
return sql;
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
default:
|
|
99
|
+
throw new TypeError("columns 应为 string 或 object 类型");
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* 生成 ORDER BY 语句, d
|
|
104
|
+
* @public
|
|
105
|
+
* @example
|
|
106
|
+
* ```ts
|
|
107
|
+
* // 以下生成 "\nORDER BY age DESC NULLS FIRST,num ASC"
|
|
108
|
+
* orderBy("age DESC NULLS FIRST,num ASC");
|
|
109
|
+
* orderBy(["age DESC NULLS FIRST", "num ASC"]);
|
|
110
|
+
* orderBy([
|
|
111
|
+
* { key: "age", asc: false, nullLast: false },
|
|
112
|
+
* { key: "num", asc: true },
|
|
113
|
+
* ]);
|
|
114
|
+
* orderBy({ age: "DESC NULLS FIRST", num: true });
|
|
115
|
+
*
|
|
116
|
+
* orderBy([]) // ""
|
|
117
|
+
* orderBy({}) // ""
|
|
118
|
+
* ```
|
|
119
|
+
*/
|
|
120
|
+
function orderBy(by) {
|
|
121
|
+
if (typeof by === "function")
|
|
122
|
+
by = by();
|
|
123
|
+
let sql = "";
|
|
124
|
+
if (!by)
|
|
125
|
+
return sql;
|
|
126
|
+
if (typeof by === "string") {
|
|
127
|
+
sql += "\nORDER BY " + by;
|
|
128
|
+
}
|
|
129
|
+
else if (by instanceof Array) {
|
|
130
|
+
if (by.length) {
|
|
131
|
+
sql += "\nORDER BY " + handlerOrderValue(by[0]);
|
|
132
|
+
for (let i = 1; i < by.length; i++)
|
|
133
|
+
sql += "," + handlerOrderValue(by[i]);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
else {
|
|
137
|
+
let keys = Object.keys(by);
|
|
138
|
+
if (keys.length) {
|
|
139
|
+
let key = keys[0];
|
|
140
|
+
let value = by[key];
|
|
141
|
+
sql += "\nORDER BY " + key + " " + (typeof value === "string" ? value : value ? "ASC" : "DESC");
|
|
142
|
+
for (let i = 1; i < keys.length; i++) {
|
|
143
|
+
key = keys[i];
|
|
144
|
+
value = by[key];
|
|
145
|
+
sql += "," + key + " ";
|
|
146
|
+
if (typeof value === "string")
|
|
147
|
+
sql += value;
|
|
148
|
+
else
|
|
149
|
+
sql += value ? "ASC" : "DESC";
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
return sql;
|
|
154
|
+
}
|
|
155
|
+
function handlerOrderValue(value) {
|
|
156
|
+
if (typeof value === "string")
|
|
157
|
+
return value;
|
|
158
|
+
else {
|
|
159
|
+
let str = value.key + " " + (value.asc ? "ASC" : "DESC");
|
|
160
|
+
if (value.nullLast !== undefined)
|
|
161
|
+
str += value.nullLast ? " NULLS LAST" : " NULLS FIRST";
|
|
162
|
+
return str;
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
export { getObjectListKeys, having, orderBy, selectColumns, where };
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { CustomDbType } from './infer_db_type.js';
|
|
2
|
+
|
|
3
|
+
/** @public */
|
|
4
|
+
class TypeChecker {
|
|
5
|
+
map;
|
|
6
|
+
constructor(map) {
|
|
7
|
+
this.map = map;
|
|
8
|
+
}
|
|
9
|
+
check(value) {
|
|
10
|
+
const map = this.map;
|
|
11
|
+
let v;
|
|
12
|
+
for (const [k, expect] of map) {
|
|
13
|
+
v = value[k];
|
|
14
|
+
let err;
|
|
15
|
+
if (v === null) {
|
|
16
|
+
if (expect.notNull)
|
|
17
|
+
throw new Error(`${k} 不能为空`);
|
|
18
|
+
continue;
|
|
19
|
+
}
|
|
20
|
+
else if (v === undefined) {
|
|
21
|
+
if (expect.sqlDefault === undefined && expect.notNull)
|
|
22
|
+
throw new Error(`${k} 不能为 undefined`);
|
|
23
|
+
continue;
|
|
24
|
+
}
|
|
25
|
+
else if (expect.isArray) {
|
|
26
|
+
if (v instanceof Array)
|
|
27
|
+
err = this.checkArray(v, expect.type);
|
|
28
|
+
else
|
|
29
|
+
err = getErrStr(`Array<${expect.type.name}>`, typeof v);
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
err = this.checkItem(v, expect.type);
|
|
33
|
+
}
|
|
34
|
+
if (err)
|
|
35
|
+
throw new Error(`Key ${k} error: ${err}`);
|
|
36
|
+
}
|
|
37
|
+
return value;
|
|
38
|
+
}
|
|
39
|
+
checkList(value) {
|
|
40
|
+
let i = 0;
|
|
41
|
+
try {
|
|
42
|
+
for (let i = 0; i < value.length; i++) {
|
|
43
|
+
this.check(value[i]);
|
|
44
|
+
}
|
|
45
|
+
return value;
|
|
46
|
+
}
|
|
47
|
+
catch (error) {
|
|
48
|
+
throw new Error(`Item ${i}, ${error.message}`);
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
checkArray(v, expect) {
|
|
52
|
+
let err;
|
|
53
|
+
for (let i = 0; i < v.length; i++) {
|
|
54
|
+
err = this.checkItem(v[i], expect);
|
|
55
|
+
if (err)
|
|
56
|
+
return `Item[${i}] ${err}`;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
checkItem(v, expect) {
|
|
60
|
+
if (expect instanceof CustomDbType) {
|
|
61
|
+
if (expect.is(v))
|
|
62
|
+
return;
|
|
63
|
+
}
|
|
64
|
+
else {
|
|
65
|
+
if (v instanceof expect)
|
|
66
|
+
return;
|
|
67
|
+
}
|
|
68
|
+
let actName = typeof v;
|
|
69
|
+
if (actName === "object") {
|
|
70
|
+
if (v === null)
|
|
71
|
+
actName = "null";
|
|
72
|
+
else
|
|
73
|
+
actName = v.constructor?.name ?? "object";
|
|
74
|
+
}
|
|
75
|
+
return getErrStr(expect.name, typeof v);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
function getErrStr(expect, actual) {
|
|
79
|
+
return `Expect ${expect}, Actual ${actual}`;
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
export { TypeChecker };
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 表格列的信息
|
|
3
|
+
* @public
|
|
4
|
+
*/
|
|
5
|
+
class ColumnMeta {
|
|
6
|
+
type;
|
|
7
|
+
sqlType;
|
|
8
|
+
notNull;
|
|
9
|
+
isArray;
|
|
10
|
+
sqlDefault;
|
|
11
|
+
constructor(type,
|
|
12
|
+
/** 数据库原始数据类型 */
|
|
13
|
+
sqlType,
|
|
14
|
+
/** 是否非空 */
|
|
15
|
+
notNull = false,
|
|
16
|
+
/** 是否是数组类型 */
|
|
17
|
+
isArray = false,
|
|
18
|
+
/** 数据库原始默认值 */
|
|
19
|
+
sqlDefault) {
|
|
20
|
+
this.type = type;
|
|
21
|
+
this.sqlType = sqlType;
|
|
22
|
+
this.notNull = notNull;
|
|
23
|
+
this.isArray = isArray;
|
|
24
|
+
this.sqlDefault = sqlDefault;
|
|
25
|
+
}
|
|
26
|
+
/** 校验 value 的类型 */
|
|
27
|
+
checkValue(value) {
|
|
28
|
+
if (typeof this.type === "function")
|
|
29
|
+
return value instanceof this.type;
|
|
30
|
+
return this.type.is(value);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* 数据库类型到JS类型的映射
|
|
35
|
+
* @public
|
|
36
|
+
*/
|
|
37
|
+
class YourTypeMap {
|
|
38
|
+
typeMap;
|
|
39
|
+
static create(rawTypeMap) {
|
|
40
|
+
return new this(rawTypeMap);
|
|
41
|
+
}
|
|
42
|
+
constructor(typeMap = {}) {
|
|
43
|
+
this.typeMap = typeMap;
|
|
44
|
+
}
|
|
45
|
+
genColumn(type, notNull, defaultValue) {
|
|
46
|
+
const constructor = Reflect.get(this.typeMap, type);
|
|
47
|
+
const column = new ColumnMeta(constructor, type, notNull, false, defaultValue);
|
|
48
|
+
return column;
|
|
49
|
+
}
|
|
50
|
+
genArrColumn(type, notNull, defaultValue) {
|
|
51
|
+
const constructor = Reflect.get(this.typeMap, type);
|
|
52
|
+
const column = new ColumnMeta(constructor, type + "[]", notNull, true, defaultValue);
|
|
53
|
+
return column;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
function baseType(v) {
|
|
57
|
+
return typeof v === this.name;
|
|
58
|
+
}
|
|
59
|
+
/**
|
|
60
|
+
* 自定义数据类型
|
|
61
|
+
* @public
|
|
62
|
+
*/
|
|
63
|
+
class CustomDbType {
|
|
64
|
+
is;
|
|
65
|
+
name;
|
|
66
|
+
static bigint = new CustomDbType(baseType, "bigint");
|
|
67
|
+
static number = new CustomDbType(baseType, "number");
|
|
68
|
+
static string = new CustomDbType(baseType, "string");
|
|
69
|
+
static boolean = new CustomDbType(baseType, "boolean");
|
|
70
|
+
constructor(is, name) {
|
|
71
|
+
this.is = is;
|
|
72
|
+
this.name = name;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export { ColumnMeta, CustomDbType, YourTypeMap };
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { DbTableQuery } from '../select/TableQuery.js';
|
|
2
|
+
import { TypeChecker } from './checker.js';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* 完整数据库表数据
|
|
6
|
+
* @public
|
|
7
|
+
*/
|
|
8
|
+
class YourTable extends DbTableQuery {
|
|
9
|
+
define;
|
|
10
|
+
constructor(name, define, sqlValue) {
|
|
11
|
+
super(name, sqlValue);
|
|
12
|
+
this.define = define;
|
|
13
|
+
this.columns = Object.keys(define);
|
|
14
|
+
}
|
|
15
|
+
columns;
|
|
16
|
+
getColumnMeta(name) {
|
|
17
|
+
return Reflect.get(this.define, name);
|
|
18
|
+
}
|
|
19
|
+
createTypeChecker(keys) {
|
|
20
|
+
let map = new Map();
|
|
21
|
+
let defined = this.define;
|
|
22
|
+
let k;
|
|
23
|
+
for (let i = 0; i < keys.length; i++) {
|
|
24
|
+
k = keys[i];
|
|
25
|
+
if (defined[k] === undefined)
|
|
26
|
+
throw new Error(`key ${k} 未定义`);
|
|
27
|
+
map.set(k, defined[k]);
|
|
28
|
+
}
|
|
29
|
+
return new TypeChecker(map);
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
export { YourTable };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@asla/yoursql",
|
|
3
|
-
"version": "0.8.
|
|
3
|
+
"version": "0.8.4",
|
|
4
4
|
"description": "",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"types": "./dist/mod.d.ts",
|
|
@@ -29,8 +29,8 @@
|
|
|
29
29
|
"url": "https://github.com/asnowc/yoursql"
|
|
30
30
|
},
|
|
31
31
|
"exports": {
|
|
32
|
-
".": "./dist/sql_gen.js",
|
|
33
|
-
"./client": "./dist/client.js"
|
|
32
|
+
".": "./dist/sql_gen/mod.js",
|
|
33
|
+
"./client": "./dist/client/mod.js"
|
|
34
34
|
},
|
|
35
35
|
"files": [
|
|
36
36
|
"dist/**/*.js",
|
package/dist/client.js
DELETED
|
@@ -1,209 +0,0 @@
|
|
|
1
|
-
/** @public */
|
|
2
|
-
class ParallelQueryError extends Error {
|
|
3
|
-
constructor() {
|
|
4
|
-
super("The previous query was not completed and cannot be executed");
|
|
5
|
-
}
|
|
6
|
-
}
|
|
7
|
-
/** @public */
|
|
8
|
-
class ConnectionNotAvailableError extends Error {
|
|
9
|
-
constructor(message) {
|
|
10
|
-
super(message);
|
|
11
|
-
}
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* SQL 查询相关操作
|
|
16
|
-
* @public
|
|
17
|
-
*/
|
|
18
|
-
class DbQuery {
|
|
19
|
-
/** 单语句查询受影响的行 */
|
|
20
|
-
queryCount(sql) {
|
|
21
|
-
return this.query(sql.toString()).then((res) => {
|
|
22
|
-
if (res.rowCount === null)
|
|
23
|
-
return 0;
|
|
24
|
-
return res.rowCount;
|
|
25
|
-
});
|
|
26
|
-
}
|
|
27
|
-
queryRows(sql) {
|
|
28
|
-
return this.query(sql.toString()).then((res) => res.rows);
|
|
29
|
-
}
|
|
30
|
-
multipleQueryRows(sql) {
|
|
31
|
-
return this.multipleQuery(sql.toString()).then((res) => res.map((item) => item.rows ?? []));
|
|
32
|
-
}
|
|
33
|
-
async queryMap(sql, key) {
|
|
34
|
-
const { rows } = await this.query(sql.toString());
|
|
35
|
-
let map = new Map();
|
|
36
|
-
for (let i = 0; i < rows.length; i++) {
|
|
37
|
-
map.set(rows[i][key], rows[i]);
|
|
38
|
-
}
|
|
39
|
-
return map;
|
|
40
|
-
}
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
/** @public */
|
|
44
|
-
class DbCursor {
|
|
45
|
-
// implement
|
|
46
|
-
[Symbol.asyncDispose]() {
|
|
47
|
-
return this.close();
|
|
48
|
-
}
|
|
49
|
-
async *[Symbol.asyncIterator]() {
|
|
50
|
-
let data = await this.read();
|
|
51
|
-
try {
|
|
52
|
-
while (data.length) {
|
|
53
|
-
yield* data;
|
|
54
|
-
data = await this.read();
|
|
55
|
-
}
|
|
56
|
-
}
|
|
57
|
-
finally {
|
|
58
|
-
await this.close();
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
/**
|
|
64
|
-
|
|
65
|
-
/**
|
|
66
|
-
* 池连接
|
|
67
|
-
* @public
|
|
68
|
-
*/
|
|
69
|
-
class DbPoolConnection extends DbQuery {
|
|
70
|
-
constructor(conn, onRelease) {
|
|
71
|
-
super();
|
|
72
|
-
this.#conn = conn;
|
|
73
|
-
this.#onRelease = onRelease;
|
|
74
|
-
}
|
|
75
|
-
#onRelease;
|
|
76
|
-
//implement
|
|
77
|
-
async begin(mode) {
|
|
78
|
-
await this.query("BEGIN" + (mode ? " TRANSACTION ISOLATION LEVEL " + mode : ""));
|
|
79
|
-
}
|
|
80
|
-
#conn;
|
|
81
|
-
query(sql) {
|
|
82
|
-
if (!this.#conn)
|
|
83
|
-
return Promise.reject(new ConnectionNotAvailableError("Connection already release"));
|
|
84
|
-
return this.#conn.query(sql);
|
|
85
|
-
}
|
|
86
|
-
multipleQuery(sql) {
|
|
87
|
-
if (!this.#conn)
|
|
88
|
-
return Promise.reject(new ConnectionNotAvailableError("Connection already release"));
|
|
89
|
-
return this.#conn.multipleQuery(sql);
|
|
90
|
-
}
|
|
91
|
-
//implement
|
|
92
|
-
async rollback() {
|
|
93
|
-
await this.query("ROLLBACK");
|
|
94
|
-
}
|
|
95
|
-
//implement
|
|
96
|
-
async commit() {
|
|
97
|
-
await this.query("COMMIT");
|
|
98
|
-
}
|
|
99
|
-
get released() {
|
|
100
|
-
return !this.#conn;
|
|
101
|
-
}
|
|
102
|
-
/** 调用 release() 时,如果事务未提交,则抛出异常 */
|
|
103
|
-
release() {
|
|
104
|
-
if (this.#conn) {
|
|
105
|
-
this.#conn = undefined;
|
|
106
|
-
this.#onRelease();
|
|
107
|
-
}
|
|
108
|
-
}
|
|
109
|
-
//implement
|
|
110
|
-
[Symbol.dispose]() {
|
|
111
|
-
return this.release();
|
|
112
|
-
}
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
/**
|
|
116
|
-
* @public
|
|
117
|
-
* 池连接事务
|
|
118
|
-
*/
|
|
119
|
-
class DbPoolTransaction extends DbQuery {
|
|
120
|
-
mode;
|
|
121
|
-
constructor(connect, mode) {
|
|
122
|
-
super();
|
|
123
|
-
this.mode = mode;
|
|
124
|
-
this.#query = (sql) => {
|
|
125
|
-
return new Promise((resolve, reject) => {
|
|
126
|
-
this.#pending = connect()
|
|
127
|
-
.then((conn) => {
|
|
128
|
-
this.#conn = conn;
|
|
129
|
-
const promise = conn.multipleQuery("BEGIN" + (this.mode ? " TRANSACTION ISOLATION LEVEL " + this.mode : "") + ";\n" + sql);
|
|
130
|
-
this.#pending = promise;
|
|
131
|
-
this.#query = this.#queryAfter;
|
|
132
|
-
return promise;
|
|
133
|
-
})
|
|
134
|
-
.then((res) => {
|
|
135
|
-
this.#pending = undefined;
|
|
136
|
-
resolve(res[1]);
|
|
137
|
-
}, (e) => {
|
|
138
|
-
this.#pending = undefined;
|
|
139
|
-
reject(e);
|
|
140
|
-
if (this.#conn)
|
|
141
|
-
this.#release(this.#conn, e);
|
|
142
|
-
});
|
|
143
|
-
});
|
|
144
|
-
};
|
|
145
|
-
}
|
|
146
|
-
#pending;
|
|
147
|
-
#conn;
|
|
148
|
-
async commit() {
|
|
149
|
-
if (this.#pending)
|
|
150
|
-
throw new ParallelQueryError();
|
|
151
|
-
if (this.#conn) {
|
|
152
|
-
const promise = this.#conn.query("COMMIT");
|
|
153
|
-
this.#release(this.#conn);
|
|
154
|
-
await promise;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
async rollback() {
|
|
158
|
-
if (this.#pending)
|
|
159
|
-
throw new ParallelQueryError();
|
|
160
|
-
if (this.#conn) {
|
|
161
|
-
const promise = this.#conn.query("ROLLBACK");
|
|
162
|
-
this.#release(this.#conn);
|
|
163
|
-
await promise;
|
|
164
|
-
}
|
|
165
|
-
}
|
|
166
|
-
savePoint(savePoint) {
|
|
167
|
-
return this.query("SAVEPOINT" + savePoint).then(() => { });
|
|
168
|
-
}
|
|
169
|
-
rollbackTo(savePoint) {
|
|
170
|
-
return this.query("ROLLBACK TO " + savePoint).then(() => { });
|
|
171
|
-
}
|
|
172
|
-
/** 拿到连接后执行这个 */
|
|
173
|
-
#queryAfter(sql) {
|
|
174
|
-
return this.#conn.query(sql).then((res) => {
|
|
175
|
-
this.#pending = undefined;
|
|
176
|
-
return res;
|
|
177
|
-
}, (e) => {
|
|
178
|
-
this.#pending = undefined;
|
|
179
|
-
this.#release(this.#conn, e);
|
|
180
|
-
throw e;
|
|
181
|
-
});
|
|
182
|
-
}
|
|
183
|
-
#query;
|
|
184
|
-
query(sql) {
|
|
185
|
-
if (this.#pending)
|
|
186
|
-
return Promise.reject(new ParallelQueryError());
|
|
187
|
-
return this.#query(sql.toString());
|
|
188
|
-
}
|
|
189
|
-
multipleQuery(sql) {
|
|
190
|
-
if (this.#pending)
|
|
191
|
-
return Promise.reject(new ParallelQueryError());
|
|
192
|
-
return this.#query(sql.toString());
|
|
193
|
-
}
|
|
194
|
-
#error;
|
|
195
|
-
#release(conn, error = new ConnectionNotAvailableError("Connection already release")) {
|
|
196
|
-
this.#error = error;
|
|
197
|
-
this.#query = () => Promise.reject(this.#error);
|
|
198
|
-
this.#conn = undefined;
|
|
199
|
-
conn.release();
|
|
200
|
-
}
|
|
201
|
-
get released() {
|
|
202
|
-
return !!this.#error;
|
|
203
|
-
}
|
|
204
|
-
[Symbol.asyncDispose]() {
|
|
205
|
-
return this.rollback();
|
|
206
|
-
}
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
export { ConnectionNotAvailableError, DbCursor, DbPoolConnection, DbPoolTransaction, DbQuery, ParallelQueryError };
|
|
@@ -1,91 +0,0 @@
|
|
|
1
|
-
import { ConditionParam, Constructable, OrderByParam, SelectParam } from "../util.ts";
|
|
2
|
-
import { TableType } from "./type.ts";
|
|
3
|
-
/** @public */
|
|
4
|
-
export declare abstract class SqlStatement {
|
|
5
|
-
/** 获取 SQL 语句 */
|
|
6
|
-
abstract toString(): string;
|
|
7
|
-
}
|
|
8
|
-
/**
|
|
9
|
-
* 可选择项。可以是 table、查询结果等,它能被 select 语句选择
|
|
10
|
-
* @example
|
|
11
|
-
* ```ts
|
|
12
|
-
* declare const item: SqlStatementDataset
|
|
13
|
-
* await query(`select * from ${item.toSelect()}`)
|
|
14
|
-
*
|
|
15
|
-
* ```
|
|
16
|
-
* @public
|
|
17
|
-
*/
|
|
18
|
-
export interface SqlSelectable {
|
|
19
|
-
/**
|
|
20
|
-
* 转成子选择语句, 你可以使用 select form xxx 选择
|
|
21
|
-
* 如果是 table 则是 table name
|
|
22
|
-
* 如果是 选择语句,则是 (xxx)
|
|
23
|
-
*/
|
|
24
|
-
toSelect(): string;
|
|
25
|
-
}
|
|
26
|
-
/** @public */
|
|
27
|
-
export declare abstract class SqlStatementDataset<T> extends SqlStatement implements SqlSelectable {
|
|
28
|
-
/**
|
|
29
|
-
* 转成子选择语句, 你可以使用 select form xxx 选择
|
|
30
|
-
* 如果是 table 则是 table name
|
|
31
|
-
* 如果是 选择语句,则是 (xxx)
|
|
32
|
-
*/
|
|
33
|
-
toSelect(): string;
|
|
34
|
-
}
|
|
35
|
-
/** @public */
|
|
36
|
-
export interface ChainSelectLimit<T extends TableType> extends SqlStatementDataset<T> {
|
|
37
|
-
limit(limit?: number | bigint, offset?: number | bigint): SqlStatementDataset<T>;
|
|
38
|
-
}
|
|
39
|
-
/** @public */
|
|
40
|
-
export interface ChainSelectOrderBy<T extends TableType> extends ChainSelectLimit<T> {
|
|
41
|
-
orderBy(param: Constructable<OrderByParam | void>): ChainSelectLimit<T>;
|
|
42
|
-
}
|
|
43
|
-
/** @public */
|
|
44
|
-
export interface ChainSelectHaving<T extends TableType> extends ChainSelectOrderBy<T> {
|
|
45
|
-
having(param: Constructable<ConditionParam | void>): ChainSelectLimit<T>;
|
|
46
|
-
}
|
|
47
|
-
/** @public */
|
|
48
|
-
export interface ChainSelectGroupBy<T extends TableType> extends ChainSelectOrderBy<T> {
|
|
49
|
-
groupBy(columns: string | string[]): ChainSelectHaving<T>;
|
|
50
|
-
}
|
|
51
|
-
/** @public */
|
|
52
|
-
export interface ChainSelectWhere<T extends TableType> extends ChainSelectGroupBy<T> {
|
|
53
|
-
where(param: Constructable<ConditionParam | void>): ChainSelectGroupBy<T>;
|
|
54
|
-
}
|
|
55
|
-
/** @public */
|
|
56
|
-
export interface ChainModifyReturning<T extends TableType = {}> extends SqlStatement {
|
|
57
|
-
returning(columns: "*"): SqlStatementDataset<T>;
|
|
58
|
-
returning(columns: Constructable<SelectParam>): SqlStatementDataset<Record<string, any>>;
|
|
59
|
-
returning<R extends TableType>(columns: Constructable<SelectParam>): SqlStatementDataset<R>;
|
|
60
|
-
}
|
|
61
|
-
/** @public */
|
|
62
|
-
export interface ChainModifyWhere<T extends TableType = {}> extends ChainModifyReturning<T> {
|
|
63
|
-
where(where: Constructable<ConditionParam | void>): ChainModifyReturning<T>;
|
|
64
|
-
}
|
|
65
|
-
/** @public */
|
|
66
|
-
export interface ChainConflictDo<T extends TableType = {}> {
|
|
67
|
-
doNotThing(): ChainModifyReturning<T>;
|
|
68
|
-
/**
|
|
69
|
-
* 需要注意 SQL 注入
|
|
70
|
-
*/
|
|
71
|
-
doUpdate(set: Constructable<string | {
|
|
72
|
-
[key in keyof T]?: string;
|
|
73
|
-
}>): ChainModifyWhere<T>;
|
|
74
|
-
toString(): string;
|
|
75
|
-
}
|
|
76
|
-
/** @public */
|
|
77
|
-
export interface ChainOnConflict<T extends TableType = {}> extends ChainModifyReturning<T> {
|
|
78
|
-
onConflict(option: Constructable<readonly (keyof T)[] | string>): ChainConflictDo<T>;
|
|
79
|
-
}
|
|
80
|
-
/** @public */
|
|
81
|
-
export declare class SqlTextStatementDataset<T> extends SqlStatementDataset<T> {
|
|
82
|
-
readonly sql: string;
|
|
83
|
-
constructor(sql: string);
|
|
84
|
-
toString(): string;
|
|
85
|
-
}
|
|
86
|
-
/**
|
|
87
|
-
* 推断查询结果的类型
|
|
88
|
-
* @public
|
|
89
|
-
*/
|
|
90
|
-
export type InferQueryResult<T> = T extends SqlStatementDataset<infer P> ? P : never;
|
|
91
|
-
//# sourceMappingURL=query_chain_abstract.d.ts.map
|