@asla/yoursql 0.12.1 → 0.13.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/README.md +26 -84
- package/dist/sql_gen/mod.js +1 -2
- package/dist/sql_gen/sql_value/SqlValuesDataset.d.ts +29 -0
- package/dist/sql_gen/sql_value/SqlValuesDataset.js +53 -0
- package/dist/sql_gen/sql_value/_to_values.d.ts +24 -0
- package/dist/sql_gen/sql_value/_to_values.js +91 -0
- package/dist/sql_gen/sql_value/sql_value.d.ts +7 -19
- package/dist/sql_gen/sql_value/sql_value.js +15 -108
- package/dist/sql_gen/statement/insert_chain.d.ts +8 -0
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -70,42 +70,31 @@ import { v } from "@asla/yoursql";
|
|
|
70
70
|
v.toValues([1, "abc", null, undefined, { key: "value" }]); // `1,'abc',NULL,DEFAULT,'{"key":"value"}'`
|
|
71
71
|
```
|
|
72
72
|
|
|
73
|
-
#### v.
|
|
73
|
+
#### v.createExplicitValues() 和 v.createImplicitValues()
|
|
74
74
|
|
|
75
|
-
|
|
75
|
+
转换单个对象或对象数组为 VALUES
|
|
76
76
|
|
|
77
77
|
```ts
|
|
78
78
|
import { v } from "@asla/yoursql";
|
|
79
|
-
const obj = { a: "a1", b: "b1", c: undefined, d: "d1" };
|
|
80
|
-
v.objectToValue(obj); // "'a1','b1',DEFAULT,'d1'"
|
|
81
|
-
v.objectToValue(obj, ["b", "a"]); // "'b1','a1'"
|
|
82
|
-
v.objectToValue(obj, [{ a: "TEXT", b: {} }]); // 'a1'::TEXT,'b1'"
|
|
83
|
-
```
|
|
84
|
-
|
|
85
|
-
#### v.objectListToValues()
|
|
86
79
|
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
```ts
|
|
90
|
-
import { v } from "@asla/yoursql";
|
|
91
|
-
|
|
92
|
-
const values = [{ a: 1, b: 2 }, { c: 3 }];
|
|
80
|
+
const values = [{ a: 1, b: undefined }, { c: 3 }];
|
|
93
81
|
|
|
94
82
|
// 这将自动选择数组中所有键的并集
|
|
95
|
-
v.
|
|
83
|
+
v.createExplicitValues(values).text; // "(1,NULL,NULL),(NULL,NULL,3)"
|
|
84
|
+
v.createImplicitValues(values).text; // "(1,DEFAULT,NULL),(NULL,NULL,3)"
|
|
96
85
|
|
|
97
86
|
// 或者你可以指定选择键并指定顺序
|
|
98
|
-
const valueStr = v.
|
|
87
|
+
const valueStr = v.createExplicitValues(values, ["c", "b"]).text; // "(NULL,2),(3,NULL)"
|
|
99
88
|
|
|
100
89
|
const sql = `INSERT INTO user(name, role) VALUES ${valueStr}`;
|
|
101
90
|
```
|
|
102
91
|
|
|
103
|
-
|
|
92
|
+
可以指定 SQL类型和 JS 类型断言
|
|
104
93
|
|
|
105
94
|
```ts
|
|
106
95
|
const objectList = [{ age: 1, name: "hhh" }, { age: 2, name: "row2" }, { age: 3, name: "row3" }, {}];
|
|
107
96
|
|
|
108
|
-
v.
|
|
97
|
+
v.createExplicitValues("customName", objectList, {
|
|
109
98
|
age: { sqlType: "INT", sqlDefault: "MAXIMUM(1,2)" },
|
|
110
99
|
name: "TEXT",
|
|
111
100
|
});
|
|
@@ -162,12 +151,24 @@ import {
|
|
|
162
151
|
|
|
163
152
|
```ts
|
|
164
153
|
class YourQuery extends DbQuery {
|
|
165
|
-
|
|
154
|
+
execute(sql: QueryInput | MultipleQueryInput): Promise<void> {
|
|
155
|
+
// implement
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
query<T extends MultipleQueryResult = MultipleQueryResult>(sql: MultipleQueryInput): Promise<T>;
|
|
159
|
+
query<T = any>(sql: QueryDataInput<T>): Promise<QueryRowsResult<T>>;
|
|
160
|
+
query<T = any>(sql: QueryInput): Promise<QueryRowsResult<T>>;
|
|
161
|
+
query<T = any>(sql: QueryInput | MultipleQueryInput): Promise<QueryRowsResult<T>> {
|
|
166
162
|
// implement
|
|
167
163
|
}
|
|
168
164
|
multipleQuery<T extends MultipleQueryResult = MultipleQueryResult>(sql: StringLike): Promise<T> {
|
|
169
165
|
// implement
|
|
170
166
|
}
|
|
167
|
+
/**
|
|
168
|
+
* 执行多语句的方法
|
|
169
|
+
* @deprecated 不建议使用。改用 query()
|
|
170
|
+
*/
|
|
171
|
+
abstract multipleQuery<T extends MultipleQueryResult = MultipleQueryResult>(sql: SqlLike | SqlLike[]): Promise<T>;
|
|
171
172
|
}
|
|
172
173
|
const db: DbQuery = new YourQuery();
|
|
173
174
|
```
|
|
@@ -183,10 +184,10 @@ const count: number = await db.queryCount(sqlText);
|
|
|
183
184
|
const rows: Map<string, Row> = await db.queryMap<Row>(sqlText, "name");
|
|
184
185
|
```
|
|
185
186
|
|
|
186
|
-
#### DbQueryPool
|
|
187
|
+
#### DbQueryPool 抽象类
|
|
187
188
|
|
|
188
189
|
```ts
|
|
189
|
-
class YourPool extends
|
|
190
|
+
class YourPool extends DbQueryPool {
|
|
190
191
|
// implement
|
|
191
192
|
}
|
|
192
193
|
const pool: DbQueryPool = new YourPool();
|
|
@@ -203,7 +204,7 @@ try {
|
|
|
203
204
|
}
|
|
204
205
|
```
|
|
205
206
|
|
|
206
|
-
或者,使用 `using` 语法更优雅
|
|
207
|
+
或者,使用 `using` 语法更优雅 (推荐)
|
|
207
208
|
|
|
208
209
|
```ts
|
|
209
210
|
using conn = await pool.connect();
|
|
@@ -224,7 +225,7 @@ try {
|
|
|
224
225
|
}
|
|
225
226
|
```
|
|
226
227
|
|
|
227
|
-
或者,使用 `using` 语法更优雅
|
|
228
|
+
或者,使用 `using` 语法更优雅 (推荐)
|
|
228
229
|
|
|
229
230
|
```ts
|
|
230
231
|
await using conn = pool.begin();
|
|
@@ -250,7 +251,7 @@ while (rows.length) {
|
|
|
250
251
|
}
|
|
251
252
|
```
|
|
252
253
|
|
|
253
|
-
或者使用 `for await of` 更优雅
|
|
254
|
+
或者使用 `for await of` 更优雅 (推荐)
|
|
254
255
|
|
|
255
256
|
```ts
|
|
256
257
|
const cursor = await pool.cursor(sqlText);
|
|
@@ -259,62 +260,3 @@ for await (const element of cursor) {
|
|
|
259
260
|
if (conditions) break; //提前关闭游标
|
|
260
261
|
}
|
|
261
262
|
```
|
|
262
|
-
|
|
263
|
-
### 扩展查询链
|
|
264
|
-
|
|
265
|
-
```ts
|
|
266
|
-
import { v, SqlStatement, SqlStatementDataset, SqlValuesCreator } from "@asla/yoursql";
|
|
267
|
-
import type { DbCursor, QueryResult, QueryRowsResult } from "@asla/yoursql/client";
|
|
268
|
-
|
|
269
|
-
declare const pool: DbQueryPool = new YourPool(); // 你需要实现一个 DbQueryPool
|
|
270
|
-
|
|
271
|
-
export interface QueryableSql {
|
|
272
|
-
query(): Promise<QueryResult>;
|
|
273
|
-
queryCount(): Promise<number>;
|
|
274
|
-
}
|
|
275
|
-
export interface QueryableDataSql<T> extends QueryableSql {
|
|
276
|
-
queryRows(): Promise<T[]>;
|
|
277
|
-
queryMap<K>(key: string): Promise<Map<K, T>>;
|
|
278
|
-
cursor(): Promise<DbCursor<T>>;
|
|
279
|
-
}
|
|
280
|
-
declare module "@asla/yoursql" {
|
|
281
|
-
interface SqlStatement extends QueryableSql {}
|
|
282
|
-
interface SqlStatementDataset<T> extends QueryableDataSql<T> {}
|
|
283
|
-
}
|
|
284
|
-
const base: QueryableSql = {
|
|
285
|
-
queryCount(): Promise<number> {
|
|
286
|
-
return dbPool.queryCount(this.toString());
|
|
287
|
-
},
|
|
288
|
-
query(): Promise<QueryRowsResult<any>> {
|
|
289
|
-
return dbPool.query<any>(this);
|
|
290
|
-
},
|
|
291
|
-
};
|
|
292
|
-
const obj: QueryableDataSql<any> = {
|
|
293
|
-
...base,
|
|
294
|
-
cursor(): Promise<DbCursor<any>> {
|
|
295
|
-
return dbPool.cursor(this.toString());
|
|
296
|
-
},
|
|
297
|
-
queryMap<K>(key: string): Promise<Map<K, any>> {
|
|
298
|
-
return dbPool.queryMap(this.toString(), key);
|
|
299
|
-
},
|
|
300
|
-
queryRows(): Promise<any[]> {
|
|
301
|
-
return dbPool.queryRows(this.toString());
|
|
302
|
-
},
|
|
303
|
-
};
|
|
304
|
-
|
|
305
|
-
Object.assign(SqlStatement.prototype, base);
|
|
306
|
-
Object.assign(SqlStatementDataset.prototype, obj);
|
|
307
|
-
```
|
|
308
|
-
|
|
309
|
-
现在,以及扩展了 SqlStatement 和 SqlStatementDataset 类的原型链,你可以从 select 等语句直接调用查询方法了
|
|
310
|
-
|
|
311
|
-
```ts
|
|
312
|
-
import { Selection, v } from "@asla/yoursql";
|
|
313
|
-
|
|
314
|
-
const searchName = "Bob";
|
|
315
|
-
const rows = await Selection.from("user", "u")
|
|
316
|
-
.innerJoin("role", "r", "u.id=r.user_id")
|
|
317
|
-
.select({ uid: "u.id", rid: "r.id", example: "u.id||r.id" })
|
|
318
|
-
.where(`u.name LIKE %${v(searchName)}%`)
|
|
319
|
-
.queryRows();
|
|
320
|
-
```
|
package/dist/sql_gen/mod.js
CHANGED
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
import { pgSqlTransformer } from './sql_value/db_type.js';
|
|
2
2
|
import { SqlValuesCreator } from './sql_value/sql_value.js';
|
|
3
|
-
export { SqlExplicitValuesStatement } from './sql_value/sql_value.js';
|
|
4
3
|
export { SqlStatement, SqlStatementDataset, SqlTextStatementDataset } from './SqlStatement.js';
|
|
5
4
|
export { select } from './statement/select.js';
|
|
6
5
|
export { insertInto } from './statement/insert.js';
|
|
@@ -11,7 +10,7 @@ export { selectColumns } from './util.js';
|
|
|
11
10
|
export { TypeChecker } from './your_table/checker.js';
|
|
12
11
|
export { ColumnMeta, CustomDbType, YourTypeMap } from './your_table/infer_db_type.js';
|
|
13
12
|
export { YourTable } from './your_table/table.js';
|
|
14
|
-
export { TemplateSqlStatement
|
|
13
|
+
export { TemplateSqlStatement } from './sql_value/ValueSqlTemplate.js';
|
|
15
14
|
export { orderBy } from './statement/select_impl.js';
|
|
16
15
|
|
|
17
16
|
/**
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/** @public */
|
|
2
|
+
export interface SqlValuesDataset {
|
|
3
|
+
readonly columns: readonly string[];
|
|
4
|
+
readonly text: string;
|
|
5
|
+
toSelect(name: string): string;
|
|
6
|
+
}
|
|
7
|
+
export declare class ExplicitSqlValues implements SqlValuesDataset {
|
|
8
|
+
#private;
|
|
9
|
+
columns: readonly string[];
|
|
10
|
+
readonly columnsSqlType: readonly string[];
|
|
11
|
+
constructor(columns: readonly string[], columnsSqlType: readonly string[], firstValues: string[], nextRows: string[]);
|
|
12
|
+
get text(): string;
|
|
13
|
+
/**
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* const t = v.createImplicitValues(
|
|
17
|
+
* [
|
|
18
|
+
* { id: 1, name: "name1" },
|
|
19
|
+
* { id: 2, name: "name2" },
|
|
20
|
+
* ],
|
|
21
|
+
* { id: "INT", name: "VARCHAR" },
|
|
22
|
+
* );
|
|
23
|
+
* // 返回 (VALUES (1::INT,'name1'::VARCHAR),(2,'name2')) AS t1(id,name)
|
|
24
|
+
* t.toSelect("t1(id,name)")
|
|
25
|
+
* ```
|
|
26
|
+
*/
|
|
27
|
+
toSelect(name: string): string;
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=SqlValuesDataset.d.ts.map
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
class ExplicitSqlValues {
|
|
2
|
+
columns;
|
|
3
|
+
columnsSqlType;
|
|
4
|
+
constructor(columns, columnsSqlType, firstValues, nextRows) {
|
|
5
|
+
this.columns = columns;
|
|
6
|
+
this.columnsSqlType = columnsSqlType;
|
|
7
|
+
this.#firstValues = firstValues;
|
|
8
|
+
this.#rows = nextRows;
|
|
9
|
+
}
|
|
10
|
+
#rows;
|
|
11
|
+
#firstValues;
|
|
12
|
+
#text;
|
|
13
|
+
get text() {
|
|
14
|
+
if (!this.#text) {
|
|
15
|
+
this.#text = this.#genText();
|
|
16
|
+
}
|
|
17
|
+
return this.#text;
|
|
18
|
+
}
|
|
19
|
+
#genText() {
|
|
20
|
+
const { columnsSqlType } = this;
|
|
21
|
+
const firstValues = this.#firstValues;
|
|
22
|
+
let firstRow = new Array(firstValues.length);
|
|
23
|
+
for (let i = 0; i < firstValues.length; i++) {
|
|
24
|
+
firstRow[i] = firstValues[i];
|
|
25
|
+
if (columnsSqlType[i])
|
|
26
|
+
firstRow[i] += "::" + columnsSqlType[i];
|
|
27
|
+
}
|
|
28
|
+
const base = "(" + firstRow.join(",") + ")";
|
|
29
|
+
if (this.#rows.length === 0) {
|
|
30
|
+
return base;
|
|
31
|
+
}
|
|
32
|
+
return "(" + firstRow.join(",") + "),\n" + this.#rows.join(",\n");
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* @example
|
|
36
|
+
* ```ts
|
|
37
|
+
* const t = v.createImplicitValues(
|
|
38
|
+
* [
|
|
39
|
+
* { id: 1, name: "name1" },
|
|
40
|
+
* { id: 2, name: "name2" },
|
|
41
|
+
* ],
|
|
42
|
+
* { id: "INT", name: "VARCHAR" },
|
|
43
|
+
* );
|
|
44
|
+
* // 返回 (VALUES (1::INT,'name1'::VARCHAR),(2,'name2')) AS t1(id,name)
|
|
45
|
+
* t.toSelect("t1(id,name)")
|
|
46
|
+
* ```
|
|
47
|
+
*/
|
|
48
|
+
toSelect(name) {
|
|
49
|
+
return `(VALUES\n${this.text})\nAS ${name}(${this.columns.join(",")})`;
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
export { ExplicitSqlValues };
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import { AssertJsType, ColumnToValueConfig, ObjectToValueKeys } from "./type.ts";
|
|
2
|
+
interface ValueToSqlStr {
|
|
3
|
+
toSqlStr(value: any, assertType?: AssertJsType): string;
|
|
4
|
+
}
|
|
5
|
+
export declare function internalObjectToValues(object: Record<string, any>, keys: readonly string[], type: (ColumnToValueConfig | undefined)[], undefinedDefault: string, v: ValueToSqlStr): {
|
|
6
|
+
values: string[];
|
|
7
|
+
types: string[];
|
|
8
|
+
};
|
|
9
|
+
export type ObjectToValueOption = {
|
|
10
|
+
undefinedDefault?: string;
|
|
11
|
+
};
|
|
12
|
+
export declare class AssertError extends TypeError {
|
|
13
|
+
constructor(assertType: string, actual: string);
|
|
14
|
+
}
|
|
15
|
+
export declare function getObjectValueInfo(object: Record<string | number, any>, keys_types: readonly string[] | Record<string, string | undefined> | undefined): {
|
|
16
|
+
keys: string[];
|
|
17
|
+
type: (ColumnToValueConfig | undefined)[];
|
|
18
|
+
};
|
|
19
|
+
export declare function getColumnInfo(objectList: readonly Record<string, any>[], columns?: ObjectToValueKeys<Record<string, any>>): {
|
|
20
|
+
keys: string[];
|
|
21
|
+
asserts: (ColumnToValueConfig | undefined)[];
|
|
22
|
+
};
|
|
23
|
+
export {};
|
|
24
|
+
//# sourceMappingURL=_to_values.d.ts.map
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { getObjectListKeys } from '../_statement.js';
|
|
2
|
+
|
|
3
|
+
function internalObjectToValues(object, keys, type, undefinedDefault, v) {
|
|
4
|
+
const values = new Array(keys.length);
|
|
5
|
+
const types = new Array(keys.length);
|
|
6
|
+
let i = 0;
|
|
7
|
+
let key;
|
|
8
|
+
let value;
|
|
9
|
+
let assertType;
|
|
10
|
+
try {
|
|
11
|
+
for (; i < keys.length; i++) {
|
|
12
|
+
key = keys[i];
|
|
13
|
+
value = object[key];
|
|
14
|
+
assertType = type[i];
|
|
15
|
+
if (assertType) {
|
|
16
|
+
values[i] =
|
|
17
|
+
value === undefined ? assertType.sqlDefault || undefinedDefault : v.toSqlStr(value, assertType.assertJsType);
|
|
18
|
+
if (assertType.sqlType) {
|
|
19
|
+
types[i] = assertType.sqlType;
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
else {
|
|
23
|
+
values[i] = value === undefined ? undefinedDefault : v.toSqlStr(value);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
catch (error) {
|
|
28
|
+
let message = error instanceof Error ? error.message : String(error);
|
|
29
|
+
throw new Error("字段 '" + key + "' 异常," + message);
|
|
30
|
+
}
|
|
31
|
+
if (values.length === 0)
|
|
32
|
+
throw new Error("object 不能为空");
|
|
33
|
+
return { values, types };
|
|
34
|
+
}
|
|
35
|
+
class AssertError extends TypeError {
|
|
36
|
+
constructor(assertType, actual) {
|
|
37
|
+
super(`Assert ${assertType} type, Actual ${actual} type`);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
function initColumnAssert(keys, keys_types) {
|
|
41
|
+
let key;
|
|
42
|
+
let value;
|
|
43
|
+
let type = new Array(keys.length);
|
|
44
|
+
for (let i = 0; i < keys.length; i++) {
|
|
45
|
+
key = keys[i];
|
|
46
|
+
value = keys_types[key];
|
|
47
|
+
if (typeof value === "string") {
|
|
48
|
+
type[i] = { sqlType: value };
|
|
49
|
+
}
|
|
50
|
+
else {
|
|
51
|
+
type[i] = value;
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
return type;
|
|
55
|
+
}
|
|
56
|
+
function getObjectValueInfo(object, keys_types) {
|
|
57
|
+
let type;
|
|
58
|
+
let keys;
|
|
59
|
+
if (keys_types instanceof Array) {
|
|
60
|
+
keys = [...keys_types];
|
|
61
|
+
type = [];
|
|
62
|
+
}
|
|
63
|
+
else if (keys_types) {
|
|
64
|
+
keys = Object.keys(keys_types);
|
|
65
|
+
type = initColumnAssert(keys, keys_types);
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
keys = Object.keys(object).filter((k) => object[k] !== undefined);
|
|
69
|
+
type = [];
|
|
70
|
+
}
|
|
71
|
+
return { keys, type };
|
|
72
|
+
}
|
|
73
|
+
function getColumnInfo(objectList, columns) {
|
|
74
|
+
let keys;
|
|
75
|
+
let asserts;
|
|
76
|
+
if (!columns) {
|
|
77
|
+
keys = Array.from(getObjectListKeys(objectList));
|
|
78
|
+
asserts = [];
|
|
79
|
+
}
|
|
80
|
+
else if (columns instanceof Array) {
|
|
81
|
+
keys = [...columns];
|
|
82
|
+
asserts = [];
|
|
83
|
+
}
|
|
84
|
+
else {
|
|
85
|
+
keys = Object.keys(columns);
|
|
86
|
+
asserts = initColumnAssert(keys, columns);
|
|
87
|
+
}
|
|
88
|
+
return { keys, asserts };
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
export { AssertError, getColumnInfo, getObjectValueInfo, internalObjectToValues };
|
|
@@ -1,6 +1,8 @@
|
|
|
1
|
+
import { SqlValuesDataset } from "./SqlValuesDataset.ts";
|
|
1
2
|
import { TemplateSqlStatement } from "./ValueSqlTemplate.ts";
|
|
2
3
|
import { AssertJsType, ObjectToValueKeys } from "./type.ts";
|
|
3
|
-
export { TemplateSqlStatement
|
|
4
|
+
export { TemplateSqlStatement } from "./ValueSqlTemplate.ts";
|
|
5
|
+
export type { SqlValuesDataset } from "./SqlValuesDataset.ts";
|
|
4
6
|
/** @public js 对象到编码函数的映射*/
|
|
5
7
|
export type JsObjectMapSql = Map<new (...args: any[]) => any, SqlValueEncoder>;
|
|
6
8
|
/** @public 将 js 值转为 SQl 字符串的函数*/
|
|
@@ -51,19 +53,17 @@ export declare class SqlValuesCreator {
|
|
|
51
53
|
* @example 返回的文本示例: " (...),(...) "
|
|
52
54
|
* @param columns - 选择的键。如果指定了 columns, 值为 undefined 的属性将自动填充为 null; 如果未指定 columns,将选择 objectList 所有不是 undefined 项的键的并集
|
|
53
55
|
*/
|
|
54
|
-
createImplicitValues<T extends object>(objectList: T, columns?: ObjectToValueKeys<T>):
|
|
55
|
-
createImplicitValues<T extends object>(objectList: T[], columns?: ObjectToValueKeys<T>):
|
|
56
|
+
createImplicitValues<T extends object>(objectList: T, columns?: ObjectToValueKeys<T>): SqlValuesDataset;
|
|
57
|
+
createImplicitValues<T extends object>(objectList: T[], columns?: ObjectToValueKeys<T>): SqlValuesDataset;
|
|
56
58
|
/**
|
|
57
59
|
* 将对象列表转为 SQL 的 VALUES。如果 objectList 中有某个对象的属性值为 undefined,则会被转换为 "NULL"
|
|
58
60
|
* @example 返回的文本示例: " (...),(...) "
|
|
59
61
|
* @param columns - 选择的键。
|
|
60
62
|
*/
|
|
61
|
-
createExplicitValues<T extends object>(objectList: T, columns?: ObjectToValueKeys<T>):
|
|
62
|
-
createExplicitValues<T extends object>(objectList: T[], columns?: ObjectToValueKeys<T>):
|
|
63
|
+
createExplicitValues<T extends object>(objectList: T, columns?: ObjectToValueKeys<T>): SqlValuesDataset;
|
|
64
|
+
createExplicitValues<T extends object>(objectList: T[], columns?: ObjectToValueKeys<T>): SqlValuesDataset;
|
|
63
65
|
private _objectListToValues;
|
|
64
66
|
private _objectToValue;
|
|
65
|
-
private _getObjectValueInfo;
|
|
66
|
-
private _internalObjectToValues;
|
|
67
67
|
/**
|
|
68
68
|
* 将数组列表转为 SQL 的一个 value
|
|
69
69
|
* @example
|
|
@@ -73,16 +73,4 @@ export declare class SqlValuesCreator {
|
|
|
73
73
|
*/
|
|
74
74
|
toValues(values: readonly any[]): string;
|
|
75
75
|
}
|
|
76
|
-
/** @public */
|
|
77
|
-
export type SqlValuesTextData = {
|
|
78
|
-
columns: string[];
|
|
79
|
-
text: string;
|
|
80
|
-
};
|
|
81
|
-
/** @public */
|
|
82
|
-
export declare class SqlExplicitValuesStatement {
|
|
83
|
-
columns: readonly string[];
|
|
84
|
-
readonly text: string;
|
|
85
|
-
constructor(columns: readonly string[], text: string);
|
|
86
|
-
toSelect(name: string): string;
|
|
87
|
-
}
|
|
88
76
|
//# sourceMappingURL=sql_value.d.ts.map
|
|
@@ -1,5 +1,6 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { ExplicitSqlValues } from './SqlValuesDataset.js';
|
|
2
2
|
import { TemplateSqlStatement } from './ValueSqlTemplate.js';
|
|
3
|
+
import { AssertError, getColumnInfo, internalObjectToValues, getObjectValueInfo } from './_to_values.js';
|
|
3
4
|
|
|
4
5
|
/**
|
|
5
6
|
* SQL value 生成器
|
|
@@ -122,7 +123,7 @@ class SqlValuesCreator {
|
|
|
122
123
|
else {
|
|
123
124
|
res = this._objectToValue(objectList, columns, { undefinedDefault: "DEFAULT" });
|
|
124
125
|
}
|
|
125
|
-
return
|
|
126
|
+
return res;
|
|
126
127
|
}
|
|
127
128
|
createExplicitValues(objectList, columns) {
|
|
128
129
|
if (objectList instanceof Array) {
|
|
@@ -135,100 +136,39 @@ class SqlValuesCreator {
|
|
|
135
136
|
_objectListToValues(objectList, columns, option = {}) {
|
|
136
137
|
if (objectList.length <= 0)
|
|
137
138
|
throw new Error("objectList 不能是空数组");
|
|
138
|
-
|
|
139
|
-
let asserts;
|
|
140
|
-
if (!columns) {
|
|
141
|
-
keys = Array.from(getObjectListKeys(objectList));
|
|
142
|
-
asserts = [];
|
|
143
|
-
}
|
|
144
|
-
else if (columns instanceof Array) {
|
|
145
|
-
keys = [...columns];
|
|
146
|
-
asserts = [];
|
|
147
|
-
}
|
|
148
|
-
else {
|
|
149
|
-
keys = Object.keys(columns);
|
|
150
|
-
asserts = initColumnAssert(keys, columns);
|
|
151
|
-
}
|
|
139
|
+
const { keys, asserts } = getColumnInfo(objectList, columns);
|
|
152
140
|
const undefinedDefault = option.undefinedDefault || "DEFAULT";
|
|
153
|
-
let
|
|
154
|
-
let i = 1;
|
|
141
|
+
let firstRow = internalObjectToValues(objectList[0], keys, asserts, undefinedDefault, this);
|
|
155
142
|
let j;
|
|
156
143
|
let value;
|
|
157
|
-
|
|
144
|
+
const rows = new Array(objectList.length - 1);
|
|
158
145
|
let assert;
|
|
146
|
+
let i = 1;
|
|
159
147
|
try {
|
|
160
148
|
for (; i < objectList.length; i++) {
|
|
161
149
|
const object = objectList[i];
|
|
162
|
-
|
|
150
|
+
const columns = [];
|
|
163
151
|
j = 0;
|
|
164
152
|
for (; j < keys.length; j++) {
|
|
165
153
|
value = object[keys[j]];
|
|
166
154
|
assert = asserts[j];
|
|
167
|
-
|
|
155
|
+
columns[j] =
|
|
168
156
|
value === undefined ? assert?.sqlDefault || undefinedDefault : this.toSqlStr(value, assert?.assertJsType);
|
|
169
157
|
}
|
|
170
|
-
|
|
158
|
+
rows[i - 1] = "(" + columns.join(",") + ")";
|
|
171
159
|
}
|
|
172
160
|
}
|
|
173
161
|
catch (error) {
|
|
174
162
|
let message = error instanceof Error ? error.message : String(error);
|
|
175
163
|
throw new Error("第 " + i + " 项,字段 '" + keys[j] + "' 异常," + message);
|
|
176
164
|
}
|
|
177
|
-
return new
|
|
165
|
+
return new ExplicitSqlValues(keys, firstRow.types, firstRow.values, rows);
|
|
178
166
|
}
|
|
179
167
|
_objectToValue(object, keys_types, option = {}) {
|
|
180
|
-
const { keys, type } =
|
|
168
|
+
const { keys, type } = getObjectValueInfo(object, keys_types);
|
|
181
169
|
const undefinedDefault = option.undefinedDefault || "DEFAULT";
|
|
182
|
-
const
|
|
183
|
-
return new
|
|
184
|
-
}
|
|
185
|
-
_getObjectValueInfo(object, keys_types) {
|
|
186
|
-
let type;
|
|
187
|
-
let keys;
|
|
188
|
-
if (keys_types instanceof Array) {
|
|
189
|
-
keys = [...keys_types];
|
|
190
|
-
type = [];
|
|
191
|
-
}
|
|
192
|
-
else if (keys_types) {
|
|
193
|
-
keys = Object.keys(keys_types);
|
|
194
|
-
type = initColumnAssert(keys, keys_types);
|
|
195
|
-
}
|
|
196
|
-
else {
|
|
197
|
-
keys = Object.keys(object).filter((k) => object[k] !== undefined);
|
|
198
|
-
type = [];
|
|
199
|
-
}
|
|
200
|
-
return { keys, type };
|
|
201
|
-
}
|
|
202
|
-
_internalObjectToValues(object, keys, type, undefinedDefault) {
|
|
203
|
-
const values = [];
|
|
204
|
-
let i = 0;
|
|
205
|
-
let key;
|
|
206
|
-
let value;
|
|
207
|
-
let assertType;
|
|
208
|
-
try {
|
|
209
|
-
for (; i < keys.length; i++) {
|
|
210
|
-
key = keys[i];
|
|
211
|
-
value = object[key];
|
|
212
|
-
assertType = type[i];
|
|
213
|
-
if (assertType) {
|
|
214
|
-
values[i] =
|
|
215
|
-
value === undefined
|
|
216
|
-
? assertType.sqlDefault || undefinedDefault
|
|
217
|
-
: this.toSqlStr(value, assertType.assertJsType);
|
|
218
|
-
if (assertType.sqlType)
|
|
219
|
-
values[i] += "::" + assertType.sqlType;
|
|
220
|
-
}
|
|
221
|
-
else
|
|
222
|
-
values[i] = value === undefined ? undefinedDefault : this.toSqlStr(value);
|
|
223
|
-
}
|
|
224
|
-
}
|
|
225
|
-
catch (error) {
|
|
226
|
-
let message = error instanceof Error ? error.message : String(error);
|
|
227
|
-
throw new Error("字段 '" + key + "' 异常," + message);
|
|
228
|
-
}
|
|
229
|
-
if (values.length === 0)
|
|
230
|
-
throw new Error("object 不能为空");
|
|
231
|
-
return values.join(",");
|
|
170
|
+
const res = internalObjectToValues(object, keys, type, undefinedDefault, this);
|
|
171
|
+
return new ExplicitSqlValues(keys, res.types, res.values, []);
|
|
232
172
|
}
|
|
233
173
|
/**
|
|
234
174
|
* 将数组列表转为 SQL 的一个 value
|
|
@@ -243,38 +183,5 @@ class SqlValuesCreator {
|
|
|
243
183
|
return values.map((v) => this.toSqlStr(v)).join(",");
|
|
244
184
|
}
|
|
245
185
|
}
|
|
246
|
-
class AssertError extends TypeError {
|
|
247
|
-
constructor(assertType, actual) {
|
|
248
|
-
super(`Assert ${assertType} type, Actual ${actual} type`);
|
|
249
|
-
}
|
|
250
|
-
}
|
|
251
|
-
function initColumnAssert(keys, keys_types) {
|
|
252
|
-
let key;
|
|
253
|
-
let value;
|
|
254
|
-
let type = new Array(keys.length);
|
|
255
|
-
for (let i = 0; i < keys.length; i++) {
|
|
256
|
-
key = keys[i];
|
|
257
|
-
value = keys_types[key];
|
|
258
|
-
if (typeof value === "string") {
|
|
259
|
-
type[i] = { sqlType: value };
|
|
260
|
-
}
|
|
261
|
-
else {
|
|
262
|
-
type[i] = value;
|
|
263
|
-
}
|
|
264
|
-
}
|
|
265
|
-
return type;
|
|
266
|
-
}
|
|
267
|
-
/** @public */
|
|
268
|
-
class SqlExplicitValuesStatement {
|
|
269
|
-
columns;
|
|
270
|
-
text;
|
|
271
|
-
constructor(columns, text) {
|
|
272
|
-
this.columns = columns;
|
|
273
|
-
this.text = text;
|
|
274
|
-
}
|
|
275
|
-
toSelect(name) {
|
|
276
|
-
return `(VALUES\n${this.text})\nAS ${name}(${this.columns.join(",")})`;
|
|
277
|
-
}
|
|
278
|
-
}
|
|
279
186
|
|
|
280
|
-
export {
|
|
187
|
+
export { SqlValuesCreator, TemplateSqlStatement };
|
|
@@ -8,6 +8,14 @@ export interface InsertIntoSqlGenerator {
|
|
|
8
8
|
/** @public */
|
|
9
9
|
export interface ChainAfterConflict {
|
|
10
10
|
doNotThing(): ChainInsertReturning;
|
|
11
|
+
/**
|
|
12
|
+
* @example
|
|
13
|
+
* ```ts
|
|
14
|
+
* doUpdate("SET level= 89,name= 11") // " DO UPDATE SET level= 89,name= 11"
|
|
15
|
+
* doUpdate(["level= 89", "name= 11"]) // " DO UPDATE SET\nlevel= 89,name= 11"
|
|
16
|
+
* doUpdate({level: "89", name: "11"}) // " DO UPDATE SET\nlevel= 89,name= 11"
|
|
17
|
+
* ```
|
|
18
|
+
*/
|
|
11
19
|
doUpdate(set: Constructable<string | readonly string[] | Record<string, string>>): ChainInsertReturning;
|
|
12
20
|
toString(): string;
|
|
13
21
|
}
|