mm_sql 1.4.1 → 1.4.2

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/index.js CHANGED
@@ -1,298 +1,307 @@
1
- /**
2
- * @fileOverview SQL通用类
3
- * @author <a href="http://qww.elins.cn">qww</a>
4
- * @version 1.0
5
- */
6
-
7
- /**
8
- * @class 数据库SQL类
9
- */
10
- class Sql {
11
- /**
12
- * @constructor
13
- * @param {Object} config - 配置对象
14
- */
15
- constructor(config) {
16
- /**
17
- * 配置信息
18
- */
19
- this.config = Object.assign({
20
- scope: 'sys',
21
- db_type: 'mysql',
22
- dir: '/db/',
23
- host: 'localhost',
24
- port: 3306,
25
- database: ''
26
- }, config || {});
27
-
28
- /**
29
- * SQL适配器
30
- */
31
- this._adapter = null;
32
-
33
- // 初始化
34
- this._init();
35
- }
36
- }
37
-
38
- /**
39
- * 初始化
40
- * @private
41
- */
42
- Sql.prototype._init = function () {
43
- this._createSqlAdapter();
44
- };
45
-
46
- /**
47
- * 创建SQL适配器
48
- * @private
49
- */
50
- Sql.prototype._createSqlAdapter = function () {
51
- const adapterModule = `mm_${this.config.db_type}`;
52
- const adapter = require(adapterModule);
53
-
54
- // 根据数据库类型选择不同的初始化方式
55
- if (this.config.db_type === 'mysql') {
56
- // 创建MySQL实例
57
- const admin = adapter.mysqlAdmin;
58
- this._adapter = admin(this.config.scope, this.config);
59
- } else if (this.config.db_type === 'sqlite') {
60
- // SQLite应该有类似的结构
61
- const admin = adapter.sqliteAdmin;
62
- this._adapter = admin(this.config.scope, this.config);
63
- } else {
64
- // 其他数据库类型直接使用Sql类(如果存在)
65
- const AdapterClass = adapter.Sql;
66
- if (AdapterClass) {
67
- this._adapter = new AdapterClass(this.config);
68
- } else {
69
- throw new Error(`不支持的数据库类型: ${this.config.db_type}`);
70
- }
71
- }
72
- };
73
-
74
- /**
75
- * 执行查询操作
76
- * @param {String|Object} sql - SQL语句或选项对象
77
- * @param {Array} params - 参数数组
78
- * @param {Number} timeout - 超时时间(毫秒)
79
- * @returns {Promise} 查询结果
80
- * @throws {TypeError} 当sql参数无效时
81
- */
82
- Sql.prototype.run = function (sql, params = [], timeout = null) {
83
- // 参数校验
84
- if (typeof sql !== 'string' && typeof sql !== 'object') {
85
- throw new TypeError('sql must be string or object');
86
- }
87
- if (!Array.isArray(params)) {
88
- throw new TypeError('params must be array');
89
- }
90
- if (timeout !== null && typeof timeout !== 'number') {
91
- throw new TypeError('timeout must be number or null');
92
- }
93
-
94
- try {
95
- // 支持两种调用方式:run(sql, params, timeout) 或 run({sql: '', params: []})
96
- if (typeof sql === 'object') {
97
- params = sql.params || [];
98
- timeout = sql.timeout || null;
99
- sql = sql.sql || '';
100
- }
101
- return this._adapter.run(sql, params, timeout);
102
- } catch (error) {
103
- this.logger('error', 'SQL查询执行失败', error);
104
- throw error;
105
- }
106
- };
107
-
108
- /**
109
- * 执行修改操作
110
- * @param {String|Object} sql - SQL语句或选项对象
111
- * @param {Array} params - 参数数组
112
- * @param {Number} timeout - 超时时间(毫秒)
113
- * @returns {Promise} 修改结果
114
- * @throws {TypeError} 当sql参数无效时
115
- */
116
- Sql.prototype.exec = function (sql, params = [], timeout = null) {
117
- // 参数校验
118
- if (typeof sql !== 'string' && typeof sql !== 'object') {
119
- throw new TypeError('sql must be string or object');
120
- }
121
- if (!Array.isArray(params)) {
122
- throw new TypeError('params must be array');
123
- }
124
- if (timeout !== null && typeof timeout !== 'number') {
125
- throw new TypeError('timeout must be number or null');
126
- }
127
-
128
- try {
129
- // 支持两种调用方式:exec(sql, params, timeout) 或 exec({sql: '', params: []})
130
- if (typeof sql === 'object') {
131
- params = sql.params || [];
132
- timeout = sql.timeout || null;
133
- sql = sql.sql || '';
134
- }
135
- return this._adapter.exec(sql, params, timeout);
136
- } catch (error) {
137
- this.logger('error', 'SQL修改执行失败', error);
138
- return 0;
139
- }
140
- };
141
-
142
- /**
143
- * 打开数据库连接
144
- * @returns {Promise} 连接结果
145
- */
146
- Sql.prototype.open = function () {
147
- try {
148
- return this._adapter.open();
149
- } catch (error) {
150
- this.logger('error', '数据库连接打开失败', error);
151
- return null;
152
- }
153
- };
154
-
155
- /**
156
- * 关闭数据库连接
157
- * @returns {Promise} 关闭结果
158
- */
159
- Sql.prototype.close = function () {
160
- try {
161
- return this._adapter.close();
162
- } catch (error) {
163
- this.logger('error', '数据库连接关闭失败', error);
164
- }
165
- };
166
-
167
- /**
168
- * 设置配置
169
- * @param {Object} config - 配置对象
170
- * @throws {TypeError} 当config参数无效时
171
- */
172
- Sql.prototype.setConfig = function (config) {
173
- // 参数校验
174
- if (!config || typeof config !== 'object') {
175
- throw new TypeError('config must be object');
176
- }
177
-
178
- try {
179
- this.config = Object.assign(this.config, config);
180
- this._init();
181
- } catch (error) {
182
- this.logger('error', '配置设置失败', error);
183
- }
184
- };
185
-
186
- /**
187
- * 执行模板查询
188
- * @param {Object} paramDt - 参数对象
189
- * @param {Object} sqlDt - SQL模板对象
190
- * @returns {Object} 查询结果对象
191
- * @throws {TypeError} 当参数对象无效时
192
- */
193
- Sql.prototype.tplQuery = function (paramDt, sqlDt) {
194
- // 参数校验
195
- if (!paramDt || typeof paramDt !== 'object') {
196
- throw new TypeError('paramDt must be object');
197
- }
198
- if (!sqlDt || typeof sqlDt !== 'object') {
199
- throw new TypeError('sqlDt must be object');
200
- }
201
-
202
- try {
203
- let sql = '';
204
-
205
- for (const key in paramDt) {
206
- if (sqlDt[key]) {
207
- // 替换占位符{0}为参数值
208
- const sqlSegment = sqlDt[key].replace(/\{0\}/g, paramDt[key]);
209
- sql += 'AND ' + sqlSegment + ' ';
210
- }
211
- else {
212
- sql += 'AND `' + key + "` = '" + paramDt[key] + "'";
213
- }
214
- }
215
-
216
- return sql.replace('AND ', '');
217
- } catch (error) {
218
- this.logger('error', '模板查询生成失败', error);
219
- return '';
220
- }
221
- };
222
-
223
- /**
224
- * 执行模板查询(仅返回数据部分)
225
- * @param {Object} paramDt - 参数对象
226
- * @param {Object} sqlDt - SQL模板对象
227
- * @returns {Object} 查询结果对象
228
- * @throws {TypeError} 当参数对象无效时
229
- */
230
- Sql.prototype.tplBody = function (paramDt, sqlDt) {
231
- // 参数校验
232
- if (!paramDt || typeof paramDt !== 'object') {
233
- throw new TypeError('paramDt must be object');
234
- }
235
- if (!sqlDt || typeof sqlDt !== 'object') {
236
- throw new TypeError('sqlDt must be object');
237
- }
238
-
239
- try {
240
- let sql = '';
241
-
242
- for (const key in paramDt) {
243
- if (sqlDt[key]) {
244
- // 替换占位符{0}为参数值
245
- const sqlSegment = sqlDt[key].replace(/\{0\}/g, paramDt[key]);
246
- sql += ', ' + sqlSegment + ' ';
247
- }
248
- else {
249
- sql += ', `' + key + "` = '" + paramDt[key] + "'";
250
- }
251
- }
252
-
253
- return sql.replace(', ', '');
254
- } catch (error) {
255
- this.logger('error', '模板数据生成失败', error);
256
- return '';
257
- }
258
- };
259
-
260
- /**
261
- * 过滤参数对象中的指定键
262
- * @param {Object} paramDt - 参数对象
263
- * @param {Array} arr - 过滤数组
264
- * @returns {Object} 过滤后的参数对象
265
- * @throws {TypeError} 当参数对象无效时
266
- */
267
- Sql.prototype.filter = function (paramDt, arr) {
268
- // 参数校验
269
- if (!paramDt || typeof paramDt !== 'object') {
270
- throw new TypeError('paramDt must be object');
271
- }
272
- if (!Array.isArray(arr)) {
273
- throw new TypeError('arr must be array');
274
- }
275
-
276
- try {
277
- for (const key in paramDt) {
278
- if (arr.includes(key)) {
279
- delete paramDt[key];
280
- }
281
- }
282
- return paramDt;
283
- } catch (error) {
284
- this.logger('error', '参数过滤失败', error);
285
- return {};
286
- }
287
- };
288
-
289
- /**
290
- * 获取新数据库管理器
291
- * @returns {Object} 新数据库管理器
292
- */
293
- Sql.prototype.db = function () {
294
- return this._adapter.db();
295
- };
296
-
297
- // 导出模块
1
+ /**
2
+ * SQL通用类
3
+ * @author <a href="http://qww.elins.cn">qww</a>
4
+ * @version 1.0
5
+ */
6
+
7
+ /**
8
+ * 数据库SQL类
9
+ * @class
10
+ * @description 提供统一的SQL操作接口,支持多种数据库类型
11
+ */
12
+ class Sql {
13
+ /**
14
+ * 构造函数
15
+ * @class
16
+ * @param {object} config - 配置对象
17
+ */
18
+ constructor(config) {
19
+ /**
20
+ * 配置信息
21
+ */
22
+ this.config = {scope: 'sys',
23
+ db_type: 'mysql',
24
+ dir: '/db/',
25
+ host: 'localhost',
26
+ port: 3306,
27
+ database: '', ...config || {}};
28
+
29
+ /**
30
+ * SQL适配器
31
+ */
32
+ this._adapter = null;
33
+
34
+ // 初始化
35
+ this._init();
36
+ }
37
+ }
38
+
39
+ /**
40
+ * 初始化
41
+ * @private
42
+ */
43
+ Sql.prototype._init = function () {
44
+ this._createSqlAdapter();
45
+ };
46
+
47
+ /**
48
+ * 创建SQL适配器
49
+ * @private
50
+ */
51
+ Sql.prototype._createSqlAdapter = function () {
52
+ const adapter_mod = `mm_${this.config.db_type}`;
53
+ const adapter = require(adapter_mod);
54
+
55
+ // 根据数据库类型选择不同的初始化方式
56
+ if (this.config.db_type === 'mysql') {
57
+ // 创建MySQL实例
58
+ const admin = adapter.mysqlAdmin;
59
+ this._adapter = admin(this.config.scope, this.config);
60
+ } else if (this.config.db_type === 'sqlite') {
61
+ // SQLite应该有类似的结构
62
+ const admin = adapter.sqliteAdmin;
63
+ this._adapter = admin(this.config.scope, this.config);
64
+ } else {
65
+ // 其他数据库类型直接使用Sql类(如果存在)
66
+ const adapter_cls = adapter.Sql;
67
+ if (adapter_cls) {
68
+ this._adapter = new adapter_cls(this.config);
69
+ } else {
70
+ throw new Error(`不支持的数据库类型: ${this.config.db_type}`);
71
+ }
72
+ }
73
+ };
74
+
75
+ /**
76
+ * 验证SQL参数
77
+ * @param {string | object} sql - SQL语句或选项对象
78
+ * @param {Array} param - 参数数组
79
+ * @param {number} timeout - 超时时间(毫秒)
80
+ * @private
81
+ */
82
+ Sql.prototype._validateSqlParams = function (sql, param, timeout) {
83
+ if (typeof sql !== 'string' && typeof sql !== 'object') {
84
+ throw new TypeError('sql must be string or object');
85
+ }
86
+ if (!Array.isArray(param)) {
87
+ throw new TypeError('param must be array');
88
+ }
89
+ if (timeout !== null && typeof timeout !== 'number') {
90
+ throw new TypeError('timeout must be number or null');
91
+ }
92
+ };
93
+
94
+ /**
95
+ * 执行查询操作
96
+ * @param {string | object} sql - SQL语句或选项对象
97
+ * @param {Array} param - 参数数组
98
+ * @param {number} timeout - 超时时间(毫秒)
99
+ * @returns {Promise} 查询结果
100
+ * @throws {TypeError} 当sql参数无效时
101
+ */
102
+ Sql.prototype.run = function (sql, param = [], timeout = null) {
103
+ this._validateSqlParams(sql, param, timeout);
104
+
105
+ try {
106
+ // 支持两种调用方式:run(sql, param, timeout) 或 run({sql: '', param: []})
107
+ let final_sql = sql;
108
+ let final_param = param;
109
+ let final_timeout = timeout;
110
+ if (typeof sql === 'object') {
111
+ final_param = sql.param || [];
112
+ final_timeout = sql.timeout || null;
113
+ final_sql = sql.sql || '';
114
+ }
115
+ return this._adapter.run(final_sql, final_param, final_timeout);
116
+ } catch (error) {
117
+ this.log('error', 'SQL查询执行失败', error);
118
+ throw error;
119
+ }
120
+ };
121
+
122
+ /**
123
+ * 执行修改操作
124
+ * @param {string | object} sql - SQL语句或选项对象
125
+ * @param {Array} param - 参数数组
126
+ * @param {number} timeout - 超时时间(毫秒)
127
+ * @returns {Promise} 修改结果
128
+ * @throws {TypeError} 当sql参数无效时
129
+ */
130
+ Sql.prototype.exec = function (sql, param = [], timeout = null) {
131
+ this._validateSqlParams(sql, param, timeout);
132
+
133
+ try {
134
+ // 支持两种调用方式:exec(sql, param, timeout) 或 exec({sql: '', param: []})
135
+ let final_sql = sql;
136
+ let final_param = param;
137
+ let final_timeout = timeout;
138
+ if (typeof sql === 'object') {
139
+ final_param = sql.param || [];
140
+ final_timeout = sql.timeout || null;
141
+ final_sql = sql.sql || '';
142
+ }
143
+ return this._adapter.exec(final_sql, final_param, final_timeout);
144
+ } catch (error) {
145
+ this.log('error', 'SQL修改执行失败', error);
146
+ return 0;
147
+ }
148
+ };
149
+
150
+ /**
151
+ * 打开数据库连接
152
+ * @returns {Promise|null} 连接结果
153
+ */
154
+ Sql.prototype.open = function () {
155
+ try {
156
+ return this._adapter.open();
157
+ } catch (error) {
158
+ this.log('error', '数据库连接打开失败', error);
159
+ return null;
160
+ }
161
+ };
162
+
163
+ /**
164
+ * 关闭数据库连接
165
+ * @returns {Promise|undefined} 关闭结果
166
+ */
167
+ Sql.prototype.close = function () {
168
+ try {
169
+ return this._adapter.close();
170
+ } catch (error) {
171
+ this.log('error', '数据库连接关闭失败', error);
172
+ }
173
+ };
174
+
175
+ /**
176
+ * 设置配置
177
+ * @param {object} config - 配置对象
178
+ * @throws {TypeError} 当config参数无效时
179
+ */
180
+ Sql.prototype.setConfig = function (config) {
181
+ // 参数校验
182
+ if (!config || typeof config !== 'object') {
183
+ throw new TypeError('config must be object');
184
+ }
185
+
186
+ try {
187
+ this.config = Object.assign(this.config, config);
188
+ this._init();
189
+ } catch (error) {
190
+ this.log('error', '配置设置失败', error);
191
+ }
192
+ };
193
+
194
+ /**
195
+ * 执行模板查询
196
+ * @param {object} param - 参数对象
197
+ * @param {object} sql_tpl - SQL模板对象
198
+ * @returns {string} 查询条件字符串
199
+ * @throws {TypeError} 当参数对象无效时
200
+ */
201
+ Sql.prototype.tplQuery = function (param, sql_tpl) {
202
+ // 参数校验
203
+ if (!param || typeof param !== 'object') {
204
+ throw new TypeError('param must be object');
205
+ }
206
+
207
+ // 如果sql_tpl为null或undefined,使用空对象
208
+ const template = sql_tpl || {};
209
+
210
+ try {
211
+ const segments = [];
212
+
213
+ for (const key in param) {
214
+ if (template[key]) {
215
+ // 替换占位符{0}为参数值
216
+ const seg = template[key].replace(/\{0\}/g, param[key]);
217
+ segments.push(seg);
218
+ }
219
+ else {
220
+ segments.push('`' + key + "` = '" + param[key] + "'");
221
+ }
222
+ }
223
+
224
+ return segments.join(' AND ');
225
+ } catch (error) {
226
+ this.log('error', '模板查询生成失败', error);
227
+ return '';
228
+ }
229
+ };
230
+
231
+ /**
232
+ * 执行模板查询(仅返回数据部分)
233
+ * @param {object} param - 参数对象
234
+ * @param {object} sql_tpl - SQL模板对象
235
+ * @returns {string} 数据部分字符串
236
+ * @throws {TypeError} 当参数对象无效时
237
+ */
238
+ Sql.prototype.tplBody = function (param, sql_tpl) {
239
+ // 参数校验
240
+ if (!param || typeof param !== 'object') {
241
+ throw new TypeError('param must be object');
242
+ }
243
+
244
+ // 如果sql_tpl为null或undefined,使用空对象
245
+ const template = sql_tpl || {};
246
+
247
+ try {
248
+ const segments = [];
249
+
250
+ for (const key in param) {
251
+ if (template[key]) {
252
+ // 替换占位符{0}为参数值
253
+ const seg = template[key].replace(/\{0\}/g, param[key]);
254
+ segments.push(seg);
255
+ }
256
+ else {
257
+ segments.push('`' + key + "` = '" + param[key] + "'");
258
+ }
259
+ }
260
+
261
+ return segments.join(' , ');
262
+ } catch (error) {
263
+ this.log('error', '模板数据生成失败', error);
264
+ return '';
265
+ }
266
+ };
267
+
268
+ /**
269
+ * 过滤参数对象中的指定键
270
+ * @param {object} param - 参数对象
271
+ * @param {Array} arr - 过滤数组
272
+ * @returns {object} 过滤后的参数对象
273
+ * @throws {TypeError} 当参数对象无效时
274
+ */
275
+ Sql.prototype.filter = function (param, arr) {
276
+ // 参数校验
277
+ if (!param || typeof param !== 'object') {
278
+ throw new TypeError('param must be object');
279
+ }
280
+ if (!Array.isArray(arr)) {
281
+ throw new TypeError('arr must be array');
282
+ }
283
+
284
+ try {
285
+ const result = {};
286
+ for (const key of arr) {
287
+ if (param[key] !== undefined) {
288
+ result[key] = param[key];
289
+ }
290
+ }
291
+ return result;
292
+ } catch (error) {
293
+ this.log('error', '参数过滤失败', error);
294
+ return {};
295
+ }
296
+ };
297
+
298
+ /**
299
+ * 获取新数据库管理器
300
+ * @returns {object} 新数据库管理器
301
+ */
302
+ Sql.prototype.db = function () {
303
+ return this._adapter.db();
304
+ };
305
+
306
+ // 导出模块
298
307
  exports.Sql = Sql;