@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 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.objectToValue()
73
+ #### v.createExplicitValues() 和 v.createImplicitValues()
74
74
 
75
- 转换对象为 values 的单个值
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
- 转换对象数组为 values
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.objectListToValues(values); // "(1,2,null),(null,null,3)"
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.objectListToValues(values, ["c", "b"]); // "(null,2),(3,3)"
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
- #### v.createValues()
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.createValues("customName", objectList, {
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
- query<T = any>(sql: StringLike): Promise<QueryRowsResult<T>> {
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 DbQuery implements DbQuery {
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
- ```
@@ -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 as ValueSqlTemplate } from './sql_value/ValueSqlTemplate.js';
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 as ValueSqlTemplate } from "./ValueSqlTemplate.ts";
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 SqlValuesDataset(keys, firstRow.types, firstRow.values, rows);
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 SqlValuesDataset(keys, res.types, res.values, []);
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, SqlValuesDataset, TemplateSqlStatement as ValueSqlTemplate };
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
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@asla/yoursql",
3
- "version": "0.13.0",
3
+ "version": "0.13.1",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "types": "./dist/mod.d.ts",