@asla/yoursql 0.0.2 → 0.0.3

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/mod.js CHANGED
@@ -101,46 +101,61 @@ class SqlValuesCreator {
101
101
  throw new Error("不支持转换 " + type + " 类型");
102
102
  }
103
103
  }
104
- /**
105
- * 将对象列表转为 SQL 的 VALUES
106
- * @example 返回示例: " (...),(...) "
107
- */
108
- objectListToValuesList(objectList, keys = Object.keys(objectList[0])) {
109
- let i = 0;
104
+ objectListToValuesList(objectList, keys_types) {
105
+ if (objectList.length <= 0)
106
+ throw new Error("objectList 不能是空数组");
107
+ let keys;
108
+ if (!keys_types) {
109
+ keys = getKeys(objectList);
110
+ }
111
+ else if (keys_types instanceof Array) {
112
+ keys = keys_types;
113
+ }
114
+ else {
115
+ keys = Object.keys(keys_types);
116
+ }
117
+ let str = "(" + this.objectToValues(objectList[0], keys_types ?? keys) + ")";
118
+ let i = 1;
110
119
  let j;
111
120
  let value;
112
- const rowValues = new Array(objectList.length);
121
+ let rows;
113
122
  try {
114
123
  for (; i < objectList.length; i++) {
115
124
  const object = objectList[i];
116
- const values = [];
125
+ rows = [];
117
126
  j = 0;
118
127
  for (; j < keys.length; j++) {
119
- value = object[keys[j]];
120
- values[j] = this.toSqlStr(value);
128
+ value = object[keys[j]] ?? null;
129
+ rows[j] = this.toSqlStr(value);
121
130
  }
122
- rowValues[i] = "\n(" + values.join(",") + ")";
131
+ str += ",\n(" + rows.join(",") + ")";
123
132
  }
124
133
  }
125
134
  catch (error) {
126
135
  let message = error instanceof Error ? error.message : String(error);
127
136
  throw new Error("第 " + i + " 项,字段 '" + keys[j] + "' 异常," + message);
128
137
  }
129
- return rowValues.join(",");
138
+ return str;
130
139
  }
131
- objectToValues(object, keys) {
140
+ objectToValues(object, keys_types) {
141
+ const { keys, type } = toKeyType(object, keys_types);
132
142
  const values = [];
133
143
  let i = 0;
144
+ let key;
134
145
  let value;
135
146
  try {
136
147
  for (; i < keys.length; i++) {
137
- value = object[keys[i]];
138
- values[i] = this.toSqlStr(value);
148
+ key = keys[i];
149
+ value = object[key] ?? null;
150
+ if (type[key])
151
+ values[i] = this.toSqlStr(value) + "::" + type[key];
152
+ else
153
+ values[i] = this.toSqlStr(value);
139
154
  }
140
155
  }
141
156
  catch (error) {
142
157
  let message = error instanceof Error ? error.message : String(error);
143
- throw new Error("字段 '" + keys[i] + "' 异常," + message);
158
+ throw new Error("字段 '" + key + "' 异常," + message);
144
159
  }
145
160
  return values.join(",");
146
161
  }
@@ -152,6 +167,36 @@ class SqlValuesCreator {
152
167
  return values.map(this.toSqlStr.bind(this)).join(",");
153
168
  }
154
169
  }
170
+ function toKeyType(object, keys_types) {
171
+ let type = {};
172
+ let keys;
173
+ if (keys_types instanceof Array) {
174
+ keys = keys_types;
175
+ type = {};
176
+ }
177
+ else if (keys_types) {
178
+ keys = Object.keys(keys_types);
179
+ type = keys_types;
180
+ }
181
+ else {
182
+ keys = Object.keys(object).filter((key) => typeof key === "string" && object[key] !== undefined);
183
+ }
184
+ return { type, keys };
185
+ }
186
+ function getKeys(objectList) {
187
+ let keys = new Set();
188
+ for (let i = 0; i < objectList.length; i++) {
189
+ let obj = objectList[i];
190
+ let hasKeys = Object.keys(obj);
191
+ let k;
192
+ for (let j = 0; j < hasKeys.length; j++) {
193
+ k = hasKeys[j];
194
+ if (obj[k] !== undefined && typeof k === "string")
195
+ keys.add(k);
196
+ }
197
+ }
198
+ return Array.from(keys);
199
+ }
155
200
 
156
201
  /**
157
202
  * @public
@@ -172,18 +217,53 @@ class PgSqlValue extends SqlValuesCreator {
172
217
  }
173
218
  }
174
219
 
175
- /** @public */
220
+ /**
221
+ * 可选择项。可以是 table、查询结果等,它能被 select 语句选择
222
+ * @example
223
+ * ```ts
224
+ * declare const item: SqlSelectable<any>
225
+ * await query(`select * from ${item.toSelect()}`)
226
+ *
227
+ * ```
228
+ * @public
229
+ */
176
230
  class SqlSelectable {
231
+ constructor(columns) {
232
+ // Reflect.set(this, SQL_SELECTABLE, undefined);
233
+ let readonlyColumns;
234
+ if (typeof columns[Symbol.iterator] === "function") {
235
+ let iterable = columns;
236
+ readonlyColumns = [];
237
+ let iter = iterable[Symbol.iterator]();
238
+ let i = 0;
239
+ let item = iter.next();
240
+ while (!item.done) {
241
+ readonlyColumns[i++] = item.value;
242
+ item = iter.next();
243
+ }
244
+ // readonlyColumns.length = i;
245
+ }
246
+ else {
247
+ let arrayLike = columns;
248
+ readonlyColumns = new Array(arrayLike.length);
249
+ // readonlyColumns.length = arrayLike.length;
250
+ for (let i = 0; i < arrayLike.length; i++) {
251
+ readonlyColumns[i] = arrayLike[i];
252
+ }
253
+ }
254
+ this.columns = readonlyColumns;
255
+ }
177
256
  }
178
- /** @public */
257
+ /**
258
+ * 数据库表
259
+ * @public
260
+ */
179
261
  class DbTable extends SqlSelectable {
180
262
  constructor(name, columns) {
181
- super();
263
+ if (!(columns instanceof Array))
264
+ columns = Object.keys(columns);
265
+ super(columns);
182
266
  this.name = name;
183
- if (columns instanceof Array)
184
- this.columns = [...columns];
185
- else
186
- this.columns = Object.keys(columns);
187
267
  }
188
268
  toSelect() {
189
269
  return this.name;
@@ -193,14 +273,13 @@ class DbTable extends SqlSelectable {
193
273
  }
194
274
  }
195
275
  /**
196
- * SELECTUPDATE、DELETE、INSERT INTO 带结果的返回值
276
+ * SELECT 以及 UPDATE、DELETE、INSERT INTO 带结果的 SQL 语句
197
277
  * @public
198
278
  */
199
279
  class SqlQueryStatement extends SqlSelectable {
200
280
  constructor(sql, columns) {
201
- super();
281
+ super(columns);
202
282
  this.sql = sql;
203
- this.columns = columns;
204
283
  }
205
284
  toString() {
206
285
  return this.sql;
@@ -324,18 +403,14 @@ const createSelect = function createSelect(tb, columns, option) {
324
403
  let select = createSelectMap(tb, columns, option).selects;
325
404
  return new SelectImpl(select);
326
405
  };
406
+ function* mergeColumns(a, b) {
407
+ for (const { columns } of a)
408
+ yield* columns.keys();
409
+ yield* b;
410
+ }
327
411
  class SelectImpl extends SqlSelectable {
328
- get columns() {
329
- return this.getColumns();
330
- }
331
- *getColumns() {
332
- for (const { columns } of this.tableList.values()) {
333
- yield* columns.keys();
334
- }
335
- yield* this.addedColumns.keys();
336
- }
337
- constructor(tableList, addedColumns = new Map()) {
338
- super();
412
+ constructor(tableList, addedColumns) {
413
+ super(addedColumns ? mergeColumns(tableList.values(), addedColumns.keys()) : tableList.keys());
339
414
  _SelectImpl_instances.add(this);
340
415
  this.tableList = tableList;
341
416
  this.addedColumns = addedColumns;
@@ -375,11 +450,13 @@ class SelectImpl extends SqlSelectable {
375
450
  }
376
451
  }
377
452
  }
378
- for (const [asName, columnStr] of this.addedColumns) {
379
- if (asName === columnStr)
380
- selectColumns.push(asName);
381
- else
382
- selectColumns.push(columnStr + " AS " + asName);
453
+ if (this.addedColumns) {
454
+ for (const [asName, columnStr] of this.addedColumns) {
455
+ if (asName === columnStr)
456
+ selectColumns.push(asName);
457
+ else
458
+ selectColumns.push(columnStr + " AS " + asName);
459
+ }
383
460
  }
384
461
  if (selectColumns.length === 0)
385
462
  throw new Error("Columns 为空");
@@ -410,12 +487,13 @@ class SelectImpl extends SqlSelectable {
410
487
  return obj;
411
488
  }
412
489
  addColumns(add) {
490
+ let addedColumns = this.addedColumns ? new Map(this.addedColumns) : new Map();
413
491
  for (const [asNewName, columnStr] of Object.entries(add)) {
414
- if (this.addedColumns.has(asNewName))
415
- throw new Error();
416
- this.addedColumns.set(asNewName, columnStr);
492
+ if (addedColumns.has(asNewName))
493
+ throw new Error(`The column ${asNewName} already exists`);
494
+ addedColumns.set(asNewName, columnStr);
417
495
  }
418
- return this;
496
+ return new _a(this.tableList, addedColumns);
419
497
  }
420
498
  toQuery(option = {}) {
421
499
  const { where, orderNullRule } = option;
@@ -505,7 +583,7 @@ class DbTableQuery extends DbTable {
505
583
  if (values.length === 0)
506
584
  throw new Error("值不能为空");
507
585
  insertCol = Object.keys(values[0]);
508
- valuesStr = `VALUES ${this.statement.objectListToValuesList(values, insertCol)}`;
586
+ valuesStr = `VALUES\n${this.statement.objectListToValuesList(values, insertCol)}`;
509
587
  }
510
588
  else if (values instanceof SqlQueryStatement) {
511
589
  // todo 验证 values.columns 和 this.columns 是否匹配
@@ -1,29 +1,46 @@
1
1
  import { TableType } from "./type.ts";
2
2
  declare const SQL_SELECTABLE: unique symbol;
3
- /** @public */
3
+ /**
4
+ * 可选择项。可以是 table、查询结果等,它能被 select 语句选择
5
+ * @example
6
+ * ```ts
7
+ * declare const item: SqlSelectable<any>
8
+ * await query(`select * from ${item.toSelect()}`)
9
+ *
10
+ * ```
11
+ * @public
12
+ */
4
13
  export declare abstract class SqlSelectable<T extends TableType> {
5
- abstract readonly columns: Iterable<string>;
6
- /** select from xxx 中的 xxx */
14
+ constructor(columns: ArrayLike<string> | Iterable<string>);
15
+ /** 结果列 */
16
+ readonly columns: readonly string[];
17
+ /**
18
+ * 转成子选择语句, 你可以使用 select form xxx 选择
19
+ * 如果是 table 则是 table name
20
+ * 如果是 选择语句,则是 (xxx)
21
+ */
7
22
  abstract toSelect(): string;
23
+ /** 获取 SQL 语句 */
8
24
  abstract toString(): string;
9
25
  /** 保留以推断类型 */
10
26
  [SQL_SELECTABLE]: T;
11
27
  }
12
- /** @public */
28
+ /**
29
+ * 数据库表
30
+ * @public
31
+ */
13
32
  export declare class DbTable<T extends TableType> extends SqlSelectable<T> {
14
33
  readonly name: string;
15
- readonly columns: readonly string[];
16
34
  constructor(name: string, columns: readonly (keyof T)[]);
17
35
  toSelect(): string;
18
36
  toString(): string;
19
37
  }
20
38
  /**
21
- * SELECTUPDATE、DELETE、INSERT INTO 带结果的返回值
39
+ * SELECT 以及 UPDATE、DELETE、INSERT INTO 带结果的 SQL 语句
22
40
  * @public
23
41
  */
24
42
  export declare class SqlQueryStatement<T extends TableType = TableType> extends SqlSelectable<T> {
25
43
  private sql;
26
- readonly columns: readonly string[];
27
44
  constructor(sql: string, columns: readonly string[]);
28
45
  toString(): string;
29
46
  toSelect(): string;
@@ -34,13 +34,19 @@ export declare class SqlValuesCreator {
34
34
  /**
35
35
  * 将对象列表转为 SQL 的 VALUES
36
36
  * @example 返回示例: " (...),(...) "
37
+ * @param keys - 选择的键。如果指定了 keys, 值为 undefined 的属性将自动填充为 null; 如果未指定 keys,将选择 objectList 所有不是 undefined 项的键的并集
37
38
  */
38
- objectListToValuesList<T extends object>(objectList: T[], keys?: (keyof T)[]): string;
39
+ objectListToValuesList<T extends object>(objectList: T[], keys?: readonly (keyof T)[] | {
40
+ [key in keyof T]?: string | undefined;
41
+ }): string;
39
42
  /**
40
43
  * 将对象转为 SQL 的 value
41
44
  * @example 返回示例: " 'abc', '6', 'now()' "
45
+ * @param keys - 如果指定了key, object undefined 的属性值将填充为 null,如果不指定,将自获取 object 所有非 undefined 的属性的key
42
46
  */
43
- objectToValues(object: object, keys: readonly string[]): string;
47
+ objectToValues<T extends object>(object: T, keys?: readonly (keyof T)[] | {
48
+ [key in keyof T]?: string | undefined;
49
+ }): string;
44
50
  /**
45
51
  * 将数组列表转为 SQL 的一个 value
46
52
  * @example 返回示例: " 'abc', '6', 'now()' "
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@asla/yoursql",
3
- "version": "0.0.2",
3
+ "version": "0.0.3",
4
4
  "description": "",
5
5
  "type": "module",
6
6
  "types": "./dist/mod.d.ts",
@@ -17,6 +17,7 @@
17
17
  "@rollup/plugin-typescript": "^12.1.0",
18
18
  "rollup": "^4.22.4",
19
19
  "tslib": "^2.7.0",
20
+ "typescript": "^5.6.2",
20
21
  "typescritp": "^1.0.0",
21
22
  "vitest": "^2.1.1"
22
23
  },