@asla/yoursql 0.13.0 → 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/sql_value.d.ts +3 -24
- package/dist/sql_gen/sql_value/sql_value.js +4 -55
- 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 { SqlValuesDataset } 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 };
|
|
@@ -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 字符串的函数*/
|
|
@@ -71,27 +73,4 @@ export declare class SqlValuesCreator {
|
|
|
71
73
|
*/
|
|
72
74
|
toValues(values: readonly any[]): string;
|
|
73
75
|
}
|
|
74
|
-
/** @public */
|
|
75
|
-
export declare class SqlValuesDataset {
|
|
76
|
-
#private;
|
|
77
|
-
columns: readonly string[];
|
|
78
|
-
readonly columnsSqlType: readonly string[];
|
|
79
|
-
constructor(columns: readonly string[], columnsSqlType: readonly string[], firstValues: string[], nextRows: string[]);
|
|
80
|
-
get text(): string;
|
|
81
|
-
/**
|
|
82
|
-
* @example
|
|
83
|
-
* ```ts
|
|
84
|
-
* const t = v.createImplicitValues(
|
|
85
|
-
* [
|
|
86
|
-
* { id: 1, name: "name1" },
|
|
87
|
-
* { id: 2, name: "name2" },
|
|
88
|
-
* ],
|
|
89
|
-
* { id: "INT", name: "VARCHAR" },
|
|
90
|
-
* );
|
|
91
|
-
* // 返回 (VALUES (1::INT,'name1'::VARCHAR),(2,'name2')) AS t1(id,name)
|
|
92
|
-
* t.toSelect("t1(id,name)")
|
|
93
|
-
* ```
|
|
94
|
-
*/
|
|
95
|
-
toSelect(name: string): string;
|
|
96
|
-
}
|
|
97
76
|
//# sourceMappingURL=sql_value.d.ts.map
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { ExplicitSqlValues } from './SqlValuesDataset.js';
|
|
1
2
|
import { TemplateSqlStatement } from './ValueSqlTemplate.js';
|
|
2
3
|
import { AssertError, getColumnInfo, internalObjectToValues, getObjectValueInfo } from './_to_values.js';
|
|
3
4
|
|
|
@@ -161,13 +162,13 @@ class SqlValuesCreator {
|
|
|
161
162
|
let message = error instanceof Error ? error.message : String(error);
|
|
162
163
|
throw new Error("第 " + i + " 项,字段 '" + keys[j] + "' 异常," + message);
|
|
163
164
|
}
|
|
164
|
-
return new
|
|
165
|
+
return new ExplicitSqlValues(keys, firstRow.types, firstRow.values, rows);
|
|
165
166
|
}
|
|
166
167
|
_objectToValue(object, keys_types, option = {}) {
|
|
167
168
|
const { keys, type } = getObjectValueInfo(object, keys_types);
|
|
168
169
|
const undefinedDefault = option.undefinedDefault || "DEFAULT";
|
|
169
170
|
const res = internalObjectToValues(object, keys, type, undefinedDefault, this);
|
|
170
|
-
return new
|
|
171
|
+
return new ExplicitSqlValues(keys, res.types, res.values, []);
|
|
171
172
|
}
|
|
172
173
|
/**
|
|
173
174
|
* 将数组列表转为 SQL 的一个 value
|
|
@@ -182,57 +183,5 @@ class SqlValuesCreator {
|
|
|
182
183
|
return values.map((v) => this.toSqlStr(v)).join(",");
|
|
183
184
|
}
|
|
184
185
|
}
|
|
185
|
-
/** @public */
|
|
186
|
-
class SqlValuesDataset {
|
|
187
|
-
columns;
|
|
188
|
-
columnsSqlType;
|
|
189
|
-
constructor(columns, columnsSqlType, firstValues, nextRows) {
|
|
190
|
-
this.columns = columns;
|
|
191
|
-
this.columnsSqlType = columnsSqlType;
|
|
192
|
-
this.#firstValues = firstValues;
|
|
193
|
-
this.#rows = nextRows;
|
|
194
|
-
}
|
|
195
|
-
#rows;
|
|
196
|
-
#firstValues;
|
|
197
|
-
#text;
|
|
198
|
-
get text() {
|
|
199
|
-
if (!this.#text) {
|
|
200
|
-
this.#text = this.#genText();
|
|
201
|
-
}
|
|
202
|
-
return this.#text;
|
|
203
|
-
}
|
|
204
|
-
#genText() {
|
|
205
|
-
const { columnsSqlType } = this;
|
|
206
|
-
const firstValues = this.#firstValues;
|
|
207
|
-
let firstRow = new Array(firstValues.length);
|
|
208
|
-
for (let i = 0; i < firstValues.length; i++) {
|
|
209
|
-
firstRow[i] = firstValues[i];
|
|
210
|
-
if (columnsSqlType[i])
|
|
211
|
-
firstRow[i] += "::" + columnsSqlType[i];
|
|
212
|
-
}
|
|
213
|
-
const base = "(" + firstRow.join(",") + ")";
|
|
214
|
-
if (this.#rows.length === 0) {
|
|
215
|
-
return base;
|
|
216
|
-
}
|
|
217
|
-
return "(" + firstRow.join(",") + "),\n" + this.#rows.join(",\n");
|
|
218
|
-
}
|
|
219
|
-
/**
|
|
220
|
-
* @example
|
|
221
|
-
* ```ts
|
|
222
|
-
* const t = v.createImplicitValues(
|
|
223
|
-
* [
|
|
224
|
-
* { id: 1, name: "name1" },
|
|
225
|
-
* { id: 2, name: "name2" },
|
|
226
|
-
* ],
|
|
227
|
-
* { id: "INT", name: "VARCHAR" },
|
|
228
|
-
* );
|
|
229
|
-
* // 返回 (VALUES (1::INT,'name1'::VARCHAR),(2,'name2')) AS t1(id,name)
|
|
230
|
-
* t.toSelect("t1(id,name)")
|
|
231
|
-
* ```
|
|
232
|
-
*/
|
|
233
|
-
toSelect(name) {
|
|
234
|
-
return `(VALUES\n${this.text})\nAS ${name}(${this.columns.join(",")})`;
|
|
235
|
-
}
|
|
236
|
-
}
|
|
237
186
|
|
|
238
|
-
export { SqlValuesCreator,
|
|
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
|
}
|