wok-server 0.6.0 → 0.7.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.
Files changed (44) hide show
  1. package/README.en.md +1 -1
  2. package/dist/http-client/index.js +2 -1
  3. package/dist/mysql/config.js +1 -1
  4. package/dist/mysql/manager/base.js +39 -0
  5. package/dist/mysql/manager/ops/criteria.js +25 -0
  6. package/dist/mysql/manager/ops/delete.js +4 -10
  7. package/dist/mysql/manager/ops/find.js +10 -30
  8. package/dist/mysql/manager/ops/index.js +2 -0
  9. package/dist/mysql/manager/ops/insert.js +39 -13
  10. package/dist/mysql/manager/ops/order-by.js +28 -0
  11. package/dist/mysql/manager/ops/paginate.js +26 -1
  12. package/dist/mysql/manager/ops/update.js +43 -37
  13. package/dist/mysql/manager/ops/upsert.js +178 -0
  14. package/dist/mysql/manager/ops/utils.js +4 -0
  15. package/documentation/en/mysql.md +135 -5
  16. package/documentation/zh-cn/mysql.md +146 -17
  17. package/package.json +2 -1
  18. package/skills/wok-server-code-navigation/SKILL.md +153 -0
  19. package/skills/wok-server-mysql/SKILL.md +76 -3
  20. package/src/http-client/index.ts +8 -3
  21. package/src/mysql/config.ts +2 -2
  22. package/src/mysql/manager/base.ts +51 -4
  23. package/src/mysql/manager/ops/criteria.ts +34 -0
  24. package/src/mysql/manager/ops/delete.ts +5 -10
  25. package/src/mysql/manager/ops/find.ts +12 -29
  26. package/src/mysql/manager/ops/index.ts +2 -0
  27. package/src/mysql/manager/ops/insert.ts +53 -15
  28. package/src/mysql/manager/ops/order-by.ts +58 -0
  29. package/src/mysql/manager/ops/paginate.ts +42 -2
  30. package/src/mysql/manager/ops/update.ts +66 -42
  31. package/src/mysql/manager/ops/upsert.ts +224 -0
  32. package/src/mysql/manager/ops/utils.ts +4 -0
  33. package/types/http-client/index.d.ts +7 -1
  34. package/types/mysql/config.d.ts +1 -1
  35. package/types/mysql/manager/base.d.ts +35 -4
  36. package/types/mysql/manager/ops/criteria.d.ts +10 -0
  37. package/types/mysql/manager/ops/delete.d.ts +2 -1
  38. package/types/mysql/manager/ops/find.d.ts +3 -2
  39. package/types/mysql/manager/ops/index.d.ts +2 -0
  40. package/types/mysql/manager/ops/insert.d.ts +16 -2
  41. package/types/mysql/manager/ops/order-by.d.ts +38 -0
  42. package/types/mysql/manager/ops/paginate.d.ts +18 -1
  43. package/types/mysql/manager/ops/update.d.ts +26 -3
  44. package/types/mysql/manager/ops/upsert.d.ts +36 -0
package/README.en.md CHANGED
@@ -44,7 +44,7 @@ startWebServer({
44
44
 
45
45
  Visit `http://localhost:8080` to see the output.
46
46
 
47
- For more configuration via environment variables, see the [full documentation](https://gitee.com/tai/wok-server/blob/master/documentation/zh-cn/index.md).
47
+ For more configuration via environment variables, see the [full documentation](https://gitee.com/tai/wok-server/blob/master/documentation/en/index.md).
48
48
 
49
49
  ### Install AI Skills
50
50
 
@@ -36,7 +36,8 @@ function doRequest(opts) {
36
36
  method: opts.method,
37
37
  headers: opts.headers,
38
38
  timeout: opts.timeout && opts.timeout > 0 ? opts.timeout : 5000,
39
- rejectUnauthorized: false
39
+ rejectUnauthorized: false,
40
+ agent: opts.agent
40
41
  }, res => {
41
42
  const chunks = [];
42
43
  res.on('error', reject);
@@ -44,7 +44,7 @@ exports.configValidation = {
44
44
  maxIdle: [(0, validation_1.notNull)(), (0, validation_1.min)(1), (0, validation_1.max)(999)],
45
45
  idleTimeout: [(0, validation_1.notNull)(), (0, validation_1.min)(1000), (0, validation_1.max)(60000)],
46
46
  slowSqlWarn: [(0, validation_1.notNull)()],
47
- slowSqlMs: [(0, validation_1.notNull)(), (0, validation_1.min)(1), (0, validation_1.max)(3600000)],
47
+ slowSqlMs: [(0, validation_1.notNull)(), (0, validation_1.min)(0), (0, validation_1.max)(3600000)],
48
48
  transactionTimeout: [(0, validation_1.notNull)(), (0, validation_1.min)(0), (0, validation_1.max)(60000)],
49
49
  transactionStrict: [(0, validation_1.notNull)()],
50
50
  maxOpsInStrictTx: [(0, validation_1.notNull)(), (0, validation_1.min)(1)]
@@ -147,6 +147,37 @@ class BaseMysqlManager {
147
147
  insertMany(table, list) {
148
148
  return this.queryWithConnection(conn => (0, ops_1.insertMany)(this.opts.config, conn, table, list));
149
149
  }
150
+ /**
151
+ * Upsert 单条数据
152
+ * 如果主键冲突则更新,否则插入
153
+ * @param table 表信息
154
+ * @param data 数据
155
+ * @returns
156
+ */
157
+ upsert(table, data) {
158
+ return this.queryWithConnection(conn => (0, ops_1.upsert)(this.opts.config, conn, table, data));
159
+ }
160
+ /**
161
+ * Upsert 多条数据
162
+ * 如果主键冲突则更新,否则插入
163
+ * @param table 表
164
+ * @param list 要插入的数据列表
165
+ * @returns 影响的行数
166
+ */
167
+ upsertMany(table, list) {
168
+ return this.queryWithConnection(conn => (0, ops_1.upsertMany)(this.opts.config, conn, table, list));
169
+ }
170
+ /**
171
+ * Upsert 单条数据(支持自定义更新器)
172
+ * 如果主键冲突则按自定义逻辑更新,否则插入
173
+ * @param table 表信息
174
+ * @param data 插入的数据
175
+ * @param updater 冲突时的更新器
176
+ * @returns
177
+ */
178
+ upsertWithUpdater(table, data, updater) {
179
+ return this.queryWithConnection(conn => (0, ops_1.upsertWithUpdater)(this.opts.config, conn, table, data, updater));
180
+ }
150
181
  /**
151
182
  * 更新
152
183
  * @param table 表信息
@@ -217,6 +248,14 @@ class BaseMysqlManager {
217
248
  paginate(opts) {
218
249
  return this.queryWithConnection(conn => (0, ops_1.paginate)(this.opts.config, conn, opts));
219
250
  }
251
+ /**
252
+ * 指定字段分页查询
253
+ * @param opts
254
+ * @returns
255
+ */
256
+ paginateSelect(opts) {
257
+ return this.queryWithConnection(conn => (0, ops_1.paginateSelect)(this.opts.config, conn, opts));
258
+ }
220
259
  /**
221
260
  * 自定义查询,指定 sql 、参数和返回值类型
222
261
  * @param sql 预编译 sql ,参数使用 ”?“(英文问号) 占位,注意查询的字段名称会与返回值类型的字段映射,如果 sql 中的字段名称很特殊(比如纯数字等),需要设置别名,避免产生映射错误
@@ -164,6 +164,19 @@ class MysqlCriteria {
164
164
  this.criteria.push({ type: 'isNotNull', key: field });
165
165
  return this;
166
166
  }
167
+ /**
168
+ * 自定义表达式查询
169
+ * 如 .expr('?? * ? > ?', ['balance', 2, 50])
170
+ * 如 .expr('MATCH(??, ??) AGAINST(? IN BOOLEAN MODE)', ['title', 'content', keyword])
171
+ * 如 .expr('VECTOR_DISTANCE(??, STRING_TO_VECTOR(?)) < ?', ['content_vec', embedding, threshold])
172
+ * @param sql SQL 片段,使用 ?? 引用列名,? 引用参数值
173
+ * @param values 参数值数组,按 SQL 中占位符顺序传入
174
+ * @returns
175
+ */
176
+ expr(sql, values) {
177
+ this.criteria.push({ type: 'expr', exprSql: sql, exprValues: values || [] });
178
+ return this;
179
+ }
167
180
  /**
168
181
  * 判定是否空,未设置条件.
169
182
  * @returns
@@ -176,6 +189,12 @@ class MysqlCriteria {
176
189
  */
177
190
  check() {
178
191
  for (const criterion of this.criteria) {
192
+ if (criterion.type === 'expr') {
193
+ if (!criterion.exprSql) {
194
+ throw new exception_1.MysqlException('expr clause exprSql cannot be empty');
195
+ }
196
+ continue;
197
+ }
179
198
  if (criterion.type === 'or' || criterion.type === 'and') {
180
199
  if (!criterion.criteria) {
181
200
  throw new exception_1.MysqlException(`${criterion.type} clause cannot be empty`);
@@ -303,6 +322,12 @@ class MysqlCriteria {
303
322
  continue;
304
323
  }
305
324
  }
325
+ // 自定义表达式
326
+ else if (criterion.type === 'expr' && criterion.exprSql) {
327
+ sqlFragments.push(`and ${criterion.exprSql} `);
328
+ values.push(...(criterion.exprValues || []));
329
+ continue;
330
+ }
306
331
  }
307
332
  if (!sqlFragments.length) {
308
333
  throw new exception_1.MysqlException('No valid query criteria have been set.');
@@ -4,6 +4,7 @@ exports.deleteMany = exports.deleteById = void 0;
4
4
  const exception_1 = require("../../exception");
5
5
  const utils_1 = require("../utils");
6
6
  const criteria_1 = require("./criteria");
7
+ const order_by_1 = require("./order-by");
7
8
  /**
8
9
  * 按 id 删除.
9
10
  *
@@ -44,16 +45,9 @@ async function deleteMany(config, connection, opts) {
44
45
  }
45
46
  // 排序
46
47
  if (opts.orderBy && opts.orderBy.length) {
47
- opts.orderBy.forEach((orderBy, idx) => {
48
- const [field, sort] = orderBy;
49
- if (idx == 0) {
50
- sql += ` order by ?? ${sort} `;
51
- }
52
- else {
53
- sql += ` , ?? ${sort} `;
54
- }
55
- values.push(field);
56
- });
48
+ const ob = (0, order_by_1.buildOrderBy)(opts.orderBy);
49
+ sql += ob.sql;
50
+ values.push(...ob.values);
57
51
  }
58
52
  // 数量限制
59
53
  if (opts.limit) {
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.findFirst = exports.findByIdIn = exports.findSelect = exports.find = exports.findAll = exports.findById = void 0;
4
4
  const criteria_1 = require("./criteria");
5
5
  const utils_1 = require("../utils");
6
+ const order_by_1 = require("./order-by");
6
7
  /**
7
8
  * 按 id 查询
8
9
  * @param connection
@@ -51,16 +52,9 @@ async function find(config, conn, opts) {
51
52
  }
52
53
  // 排序
53
54
  if (opts.orderBy && opts.orderBy.length) {
54
- opts.orderBy.forEach((orderBy, idx) => {
55
- const [field, sort] = orderBy;
56
- if (idx == 0) {
57
- sql += ` order by ?? ${sort} `;
58
- }
59
- else {
60
- sql += ` , ?? ${sort} `;
61
- }
62
- values.push(field);
63
- });
55
+ const ob = (0, order_by_1.buildOrderBy)(opts.orderBy);
56
+ sql += ob.sql;
57
+ values.push(...ob.values);
64
58
  }
65
59
  // 数量限制
66
60
  if (opts.limit) {
@@ -90,16 +84,9 @@ async function findSelect(config, conn, opts) {
90
84
  }
91
85
  // 排序
92
86
  if (opts.orderBy && opts.orderBy.length) {
93
- opts.orderBy.forEach((orderBy, idx) => {
94
- const [field, sort] = orderBy;
95
- if (idx == 0) {
96
- sql += ` order by ?? ${sort} `;
97
- }
98
- else {
99
- sql += ` , ?? ${sort} `;
100
- }
101
- values.push(field);
102
- });
87
+ const ob = (0, order_by_1.buildOrderBy)(opts.orderBy);
88
+ sql += ob.sql;
89
+ values.push(...ob.values);
103
90
  }
104
91
  // 数量限制
105
92
  if (opts.limit) {
@@ -150,16 +137,9 @@ orderBy) {
150
137
  }
151
138
  // 排序
152
139
  if (orderBy && orderBy.length) {
153
- orderBy.forEach((orderBy, idx) => {
154
- const [field, sort] = orderBy;
155
- if (idx == 0) {
156
- sql += ` order by ?? ${sort} `;
157
- }
158
- else {
159
- sql += ` , ?? ${sort} `;
160
- }
161
- values.push(field);
162
- });
140
+ const ob = (0, order_by_1.buildOrderBy)(orderBy);
141
+ sql += ob.sql;
142
+ values.push(...ob.values);
163
143
  }
164
144
  sql += ' limit 1';
165
145
  const res = await (0, utils_1.promiseQuery)(config, conn, sql, values);
@@ -9,6 +9,8 @@ tslib_1.__exportStar(require("./exist"), exports);
9
9
  tslib_1.__exportStar(require("./find"), exports);
10
10
  tslib_1.__exportStar(require("./insert"), exports);
11
11
  tslib_1.__exportStar(require("./modify"), exports);
12
+ tslib_1.__exportStar(require("./order-by"), exports);
13
+ tslib_1.__exportStar(require("./upsert"), exports);
12
14
  tslib_1.__exportStar(require("./paginate"), exports);
13
15
  tslib_1.__exportStar(require("./query"), exports);
14
16
  tslib_1.__exportStar(require("./update"), exports);
@@ -1,9 +1,28 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.insertMany = exports.insert = void 0;
3
+ exports.insertMany = exports.insert = exports.processInsertValue = void 0;
4
4
  const exception_1 = require("../../exception");
5
5
  const utils_1 = require("../utils");
6
6
  const utils_2 = require("./utils");
7
+ /**
8
+ * 处理 insert value,支持表达式
9
+ * @returns { frag: SQL 片段, values: 参数值数组 }
10
+ */
11
+ function processInsertValue(value) {
12
+ if (Array.isArray(value)) {
13
+ if (value[0] === 'now') {
14
+ return { frag: 'NOW()', values: [] };
15
+ }
16
+ if (value[0] === 'set') {
17
+ return { frag: '?', values: [(0, utils_2.processColumnValue)(value[1])] };
18
+ }
19
+ if (value[0] === 'expr') {
20
+ return { frag: value[1], values: value[2] || [] };
21
+ }
22
+ }
23
+ return { frag: '?', values: [(0, utils_2.processColumnValue)(value)] };
24
+ }
25
+ exports.processInsertValue = processInsertValue;
7
26
  /**
8
27
  * 为表插入数据
9
28
  * @param connection
@@ -12,7 +31,6 @@ const utils_2 = require("./utils");
12
31
  * @returns
13
32
  */
14
33
  async function insert(config, connection, table, data) {
15
- // 插入后的新数据
16
34
  // 列信息,使用 set 防止 columns 中重复配置 id 和更新创建时间列
17
35
  let columnsSet = new Set();
18
36
  // 判定下 id ,如果有值,才在 insert 语句中出现 id 列,否则不出现
@@ -31,15 +49,16 @@ async function insert(config, connection, table, data) {
31
49
  columnsSet.add(table.updatedDate.column);
32
50
  }
33
51
  const columns = Array.from(columnsSet);
34
- // 构建 sql
35
- const sql = `insert into ??(${columns.map(() => '??').join(',')}) values(${columns
36
- .map(() => '?')
37
- .join(',')})`;
38
- const values = [
39
- table.tableName,
40
- ...columns,
41
- ...columns.map(col => (0, utils_2.processColumnValue)(data[col]))
42
- ];
52
+ // 构建 sql,逐列处理以支持表达式
53
+ const fragList = [];
54
+ const insertValues = [];
55
+ for (const col of columns) {
56
+ const { frag, values: vs } = processInsertValue(data[col]);
57
+ fragList.push(frag);
58
+ insertValues.push(...vs);
59
+ }
60
+ const sql = `insert into ??(${columns.map(() => '??').join(',')}) values(${fragList.join(',')})`;
61
+ const values = [table.tableName, ...columns, ...insertValues];
43
62
  const res = await (0, utils_1.promiseQuery)(config, connection, sql, values);
44
63
  const packet = res;
45
64
  if (packet.affectedRows !== 1) {
@@ -87,14 +106,21 @@ async function insertMany(config, connection, table, list) {
87
106
  if (idx > 0) {
88
107
  sql += ',';
89
108
  }
90
- sql += `(${columns.map(() => '?').join(',')})`;
109
+ const fragList = [];
110
+ const rowValues = [];
91
111
  if (table.createdDate) {
92
112
  data[table.createdDate.column] = createdData;
93
113
  }
94
114
  if (table.updatedDate) {
95
115
  data[table.updatedDate.column] = updatedDate;
96
116
  }
97
- values.push(...columns.map(col => (0, utils_2.processColumnValue)(data[col])));
117
+ for (const col of columns) {
118
+ const { frag, values: vs } = processInsertValue(data[col]);
119
+ fragList.push(frag);
120
+ rowValues.push(...vs);
121
+ }
122
+ sql += `(${fragList.join(',')})`;
123
+ values.push(...rowValues);
98
124
  });
99
125
  const res = await (0, utils_1.promiseQuery)(config, connection, sql, values);
100
126
  const rsh = res;
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.buildOrderBy = void 0;
4
+ /**
5
+ * 构建 ORDER BY 子句.
6
+ *
7
+ * @param orderBy 排序规则
8
+ * @returns { sql: SQL 片段, values: 参数值数组 }
9
+ */
10
+ function buildOrderBy(orderBy) {
11
+ const fragments = [];
12
+ const values = [];
13
+ orderBy.forEach((item, idx) => {
14
+ const prefix = idx === 0 ? ' order by ' : ' , ';
15
+ if (item.length === 4 && item[0] === 'expr') {
16
+ const [, exprSql, exprValues, sort] = item;
17
+ fragments.push(`${prefix}${exprSql} ${sort}`);
18
+ values.push(...exprValues);
19
+ }
20
+ else {
21
+ const [field, sort] = item;
22
+ fragments.push(`${prefix}?? ${sort}`);
23
+ values.push(field);
24
+ }
25
+ });
26
+ return { sql: fragments.join(''), values };
27
+ }
28
+ exports.buildOrderBy = buildOrderBy;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.paginate = void 0;
3
+ exports.paginateSelect = exports.paginate = void 0;
4
4
  const count_1 = require("./count");
5
5
  const find_1 = require("./find");
6
6
  async function paginate(config, conn, opts) {
@@ -21,3 +21,28 @@ async function paginate(config, conn, opts) {
21
21
  };
22
22
  }
23
23
  exports.paginate = paginate;
24
+ /**
25
+ * 指定字段分页查询
26
+ * @param config
27
+ * @param conn
28
+ * @param opts
29
+ */
30
+ async function paginateSelect(config, conn, opts) {
31
+ const pn = opts.pn && opts.pn >= 1 ? opts.pn : 1;
32
+ const limit = opts.pz && opts.pz >= 1 && opts.pz <= 1000 ? opts.pz : 20;
33
+ const offset = (pn - 1) * limit;
34
+ const list = await (0, find_1.findSelect)(config, conn, {
35
+ table: opts.table,
36
+ criteria: opts.criteria,
37
+ offset,
38
+ limit,
39
+ orderBy: opts.orderBy,
40
+ select: opts.select
41
+ });
42
+ const total = await (0, count_1.count)(config, conn, opts.table, opts.criteria);
43
+ return {
44
+ total,
45
+ list
46
+ };
47
+ }
48
+ exports.paginateSelect = paginateSelect;
@@ -1,10 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.updateMany = exports.updateOne = exports.partialUpdate = exports.update = void 0;
3
+ exports.updateMany = exports.updateOne = exports.partialUpdate = exports.updatorToSql = exports.update = void 0;
4
4
  const exception_1 = require("../../exception");
5
5
  const criteria_1 = require("./criteria");
6
6
  const utils_1 = require("../utils");
7
7
  const utils_2 = require("./utils");
8
+ const order_by_1 = require("./order-by");
8
9
  /**
9
10
  * 更新
10
11
  * @param config
@@ -47,44 +48,47 @@ exports.update = update;
47
48
  * 转换更新器
48
49
  * @param table
49
50
  * @param updater
51
+ * @param autoUpdateTime 是否自动添加更新时间
50
52
  * @returns
51
53
  */
52
54
  function updatorToSql(table, updater) {
53
55
  const values = [];
54
- // 更新操作
55
56
  const updateFragList = [];
56
- // 更新时间
57
- if (table.updatedDate) {
58
- const updatedDate = table.updatedDate.type === 'date' ? new Date() : new Date().getTime();
59
- updateFragList.push(' ?? = ?');
60
- values.push(table.updatedDate.column, updatedDate);
61
- }
62
57
  for (const column in updater) {
63
- // 过滤掉id
58
+ // 过滤掉 id
64
59
  if (column === table.id) {
65
60
  continue;
66
61
  }
62
+ // 过滤掉 createdDate / updatedDate(自动处理)
63
+ if ((table.createdDate && column === table.createdDate.column)
64
+ || (table.updatedDate && column === table.updatedDate.column)) {
65
+ continue;
66
+ }
67
67
  const val = updater[column];
68
- // undefined 表示不参与更新,作用是方便编写一些特殊的逻辑,比如特定情况下不更新
68
+ // undefined 表示不参与更新
69
69
  if (val === undefined) {
70
70
  continue;
71
71
  }
72
- // 兼容将值设置成 null 的情况,和 ['setNull’] 等同
72
+ // 0.7.0 版本开始,null undefined 一样被忽略更新
73
+ // 如需设置字段为 NULL,请使用 ['setNull']
73
74
  if (val === null) {
74
- updateFragList.push(' ?? = NULL ');
75
- values.push(column);
76
75
  continue;
77
76
  }
78
77
  if (Array.isArray(val)) {
79
- // set null
80
78
  if (val[0] === 'setNull') {
81
79
  updateFragList.push(' ?? = NULL ');
82
80
  values.push(column);
83
81
  continue;
84
82
  }
85
83
  if (val[0] === 'inc') {
84
+ const incBy = val.length === 1 ? 1 : val[1];
86
85
  updateFragList.push(' ?? = ?? + ? ');
87
- values.push(column, column, val[1]);
86
+ values.push(column, column, incBy);
87
+ continue;
88
+ }
89
+ if (val[0] === 'now') {
90
+ updateFragList.push(' ?? = NOW() ');
91
+ values.push(column);
88
92
  continue;
89
93
  }
90
94
  if (val[0] === 'set') {
@@ -92,12 +96,33 @@ function updatorToSql(table, updater) {
92
96
  values.push(column, (0, utils_2.processColumnValue)(val[1]));
93
97
  continue;
94
98
  }
99
+ if (val[0] === 'concat') {
100
+ updateFragList.push(' ?? = CONCAT(IFNULL(??, \'\'), ?) ');
101
+ values.push(column, column, val[1]);
102
+ continue;
103
+ }
104
+ if (val[0] === 'expr') {
105
+ updateFragList.push(' ?? = ' + val[1] + ' ');
106
+ values.push(column, ...(val[2] || []));
107
+ continue;
108
+ }
95
109
  }
96
110
  updateFragList.push(' ?? = ? ');
97
111
  values.push(column, (0, utils_2.processColumnValue)(val));
98
112
  }
113
+ // 如果没有有效更新字段,抛出异常
114
+ if (updateFragList.length === 0) {
115
+ throw new exception_1.MysqlException(`No effective fields to update (null values are ignored since v0.7.0), table: ${table.tableName}, updater: ${JSON.stringify(updater)}`);
116
+ }
117
+ // 自动添加更新时间
118
+ if (table.updatedDate) {
119
+ const updatedDate = table.updatedDate.type === 'date' ? new Date() : new Date().getTime();
120
+ updateFragList.push(' ?? = ?');
121
+ values.push(table.updatedDate.column, updatedDate);
122
+ }
99
123
  return { sql: updateFragList.join(','), values };
100
124
  }
125
+ exports.updatorToSql = updatorToSql;
101
126
  /**
102
127
  * 部分更新
103
128
  * @param connection
@@ -113,9 +138,6 @@ async function partialUpdate(config, connection, table, data) {
113
138
  if (typeof id !== 'string' && typeof id !== 'number') {
114
139
  throw new exception_1.MysqlException('Primary key can only be of string or number type');
115
140
  }
116
- if (Object.keys(data).length < 2) {
117
- throw new exception_1.MysqlException(`Can't do a partial update, data must contain at least one column outside of the primary key,table: ${table.tableName},column:${JSON.stringify(data)}`);
118
- }
119
141
  const fieldNames = Object.keys(data);
120
142
  for (const name of fieldNames) {
121
143
  if (name !== table.id && !table.columns.some(col => col === name)) {
@@ -126,9 +148,6 @@ async function partialUpdate(config, connection, table, data) {
126
148
  const values = [table.tableName];
127
149
  // 更新操作
128
150
  const convertRes = updatorToSql(table, data);
129
- if (!convertRes.sql) {
130
- throw new exception_1.MysqlException('No fields were specified to be updated!');
131
- }
132
151
  values.push(...convertRes.values);
133
152
  sql += ` set ${convertRes.sql} where ?? = ?`;
134
153
  values.push(table.id, id);
@@ -155,9 +174,6 @@ async function updateOne(config, connection, table, query, updater) {
155
174
  values.push(table.tableName);
156
175
  // 更新操作
157
176
  const convertRes = updatorToSql(table, updater);
158
- if (!convertRes.sql) {
159
- throw new exception_1.MysqlException('No fields were specified to be updated!');
160
- }
161
177
  sql += ` set ${convertRes.sql} `;
162
178
  values.push(...convertRes.values);
163
179
  sql += ` where ${mysqlQuery.sql} limit 1`;
@@ -185,25 +201,15 @@ async function updateMany(config, connection, opts) {
185
201
  values.push(opts.table.tableName);
186
202
  // 更新操作
187
203
  const convertRes = updatorToSql(opts.table, opts.updater);
188
- if (!convertRes.sql) {
189
- throw new exception_1.MysqlException('No fields were specified to be updated!');
190
- }
191
204
  sql += ` set ${convertRes.sql} `;
192
205
  values.push(...convertRes.values);
193
206
  sql += ` where ${mysqlQuery.sql} `;
194
207
  values.push(...mysqlQuery.values);
195
208
  // 排序
196
209
  if (opts.orderBy && opts.orderBy.length) {
197
- opts.orderBy.forEach((orderBy, idx) => {
198
- const [field, sort] = orderBy;
199
- if (idx == 0) {
200
- sql += ` order by ?? ${sort} `;
201
- }
202
- else {
203
- sql += ` , ?? ${sort} `;
204
- }
205
- values.push(field);
206
- });
210
+ const ob = (0, order_by_1.buildOrderBy)(opts.orderBy);
211
+ sql += ob.sql;
212
+ values.push(...ob.values);
207
213
  }
208
214
  // 数量限制
209
215
  if (opts.limit) {