db-crud-api 0.3.19 → 0.3.25
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/CHANGELOG.md +5 -0
- package/README.md +99 -99
- package/lib/api-batch.js +3 -3
- package/lib/api-full.js +11 -4
- package/lib/api-session-store.js +10 -10
- package/lib/db-operations.js +32 -19
- package/lib/db-operations.js.bak +486 -0
- package/lib/mssql.js +89 -29
- package/lib/mysql.js +93 -26
- package/lib/mysql.js.bak +404 -0
- package/lib/schema.js +13 -13
- package/package.json +1 -1
|
@@ -0,0 +1,486 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
// import modules
|
|
4
|
+
import schema from './schema.js'
|
|
5
|
+
import * as mssql from './mssql.js';
|
|
6
|
+
import * as mysql from './mysql.js';
|
|
7
|
+
|
|
8
|
+
// Common
|
|
9
|
+
const defautlFields = ['*'];
|
|
10
|
+
export const serverType = Object.freeze({ mssql: 'ms-sql', mysql: 'my-sql', mongodb: 'mongo-db' });
|
|
11
|
+
export const objectType = Object.freeze({ table: 'T', procedure: 'P' });
|
|
12
|
+
|
|
13
|
+
// Exported functions
|
|
14
|
+
export function idField(tSchema) {
|
|
15
|
+
return tSchema.table?.idField ?? 'id';
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export function autoId(tSchema) {
|
|
19
|
+
return tSchema.table?.autoId;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
export function getProperty(obj, keyToFind) {
|
|
23
|
+
if (typeof obj !== 'object' || obj === null || !keyToFind) {
|
|
24
|
+
return undefined;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
const lowerKeyToFind = keyToFind.toLowerCase();
|
|
28
|
+
|
|
29
|
+
for (const key in obj) {
|
|
30
|
+
// Usa hasOwnProperty per escludere le proprietà ereditate
|
|
31
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
32
|
+
|
|
33
|
+
if (key.toLowerCase() === lowerKeyToFind) {
|
|
34
|
+
return obj[key];
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
return undefined;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function upsertProperty(obj, keyToUpdate, newValue) {
|
|
43
|
+
if (typeof obj !== 'object' || obj === null) {
|
|
44
|
+
// Non è un oggetto valido
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
const lowerKeyToUpdate = keyToUpdate.toLowerCase();
|
|
49
|
+
let propertyFound = false;
|
|
50
|
+
|
|
51
|
+
for (const key in obj) {
|
|
52
|
+
if (Object.prototype.hasOwnProperty.call(obj, key)) {
|
|
53
|
+
if (key.toLowerCase() === lowerKeyToUpdate) {
|
|
54
|
+
obj[key] = newValue;
|
|
55
|
+
propertyFound = true;
|
|
56
|
+
break;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (!propertyFound) {
|
|
62
|
+
obj[keyToUpdate] = newValue;
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
return true;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export async function runQuery(dbOpes) {
|
|
69
|
+
|
|
70
|
+
// all connections must have same id
|
|
71
|
+
const _connection = Array.isArray(dbOpes) ? dbOpes[0].connection : dbOpes.connection;
|
|
72
|
+
if (Array.isArray(dbOpes)) {
|
|
73
|
+
for (let i = 1; i < dbOpes.length; i++) {
|
|
74
|
+
if (dbOpes[i].connection?.id !== _connection.id) throw new TypeError('runQuery: for multiple operations, connection must be the same');
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// MSSQL
|
|
79
|
+
if (_connection.serverType === serverType.mssql) {
|
|
80
|
+
return await mssql.query(_connection, dbOpes);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// MySQL
|
|
84
|
+
else if (_connection.serverType === serverType.mysql) {
|
|
85
|
+
return await mysql.query(_connection, dbOpes);
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// server type not supported
|
|
89
|
+
else throw new TypeError('server type not supported');
|
|
90
|
+
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export function prepareConnection(schema) {
|
|
94
|
+
// MySQL
|
|
95
|
+
if (schema.server.type === serverType.mysql) {
|
|
96
|
+
const _return = mysql.prepareConnection(schema);
|
|
97
|
+
_return.serverType = serverType.mysql; // append 'serverType' to connection
|
|
98
|
+
return _return;
|
|
99
|
+
}
|
|
100
|
+
// MSSQL is also the default
|
|
101
|
+
if (!schema.server.type || schema.server.type === serverType.mssql) {
|
|
102
|
+
const _return = mssql.prepareConnection(schema);
|
|
103
|
+
_return.serverType = serverType.mssql; // append 'serverType' to connection
|
|
104
|
+
return _return;
|
|
105
|
+
}
|
|
106
|
+
throw new TypeError('server type not supported');
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
export function closeConnection(connection) {
|
|
110
|
+
// MSSQL
|
|
111
|
+
if (connection.serverType === serverType.mssql) { return mssql.closeConnection(connection); }
|
|
112
|
+
// MySQL
|
|
113
|
+
if (connection.serverType === serverType.mysql) { return mysql.closeConnection(connection); }
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
export function closeAllConnections() {
|
|
117
|
+
// MSSQL
|
|
118
|
+
mssql.closeAllConnections();
|
|
119
|
+
// MySQL
|
|
120
|
+
mysql.closeAllConnections();
|
|
121
|
+
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export function testConnection() {
|
|
126
|
+
const _connection = prepareConnection(prepareSchema("test", objectType.procedure));
|
|
127
|
+
// MSSQL
|
|
128
|
+
if (_connection.serverType === serverType.mssql) { return mssql.testConnection(_connection); }
|
|
129
|
+
// MySQL
|
|
130
|
+
if (_connection.serverType === serverType.mysql) { return mysql.testConnection(_connection); }
|
|
131
|
+
// server type not supported
|
|
132
|
+
throw new TypeError('server type not supported');
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
export function toStringValue(value) {
|
|
136
|
+
if (!value) return 'null';
|
|
137
|
+
if (value.trimStart().charAt(0) === '\'') return value;
|
|
138
|
+
return `\'${value}\'`;
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export function prepareSchema(obj, objType) {
|
|
142
|
+
// objType = 'objectType.' (Table or StoreProcedure)
|
|
143
|
+
// obj = 'systemName.dbName.objName' or 'dbName.objName' or 'objName' or 'systemNme..objName'
|
|
144
|
+
|
|
145
|
+
if (obj == undefined || typeof obj !== 'string') throw new TypeError('prepareSchema: wrong obj');
|
|
146
|
+
if (objType !== undefined && objType !== objectType.table && objType !== objectType.procedure) throw new TypeError(`prepareSchema: wrong objType, must be ${objectType.join(', ')}`);
|
|
147
|
+
const objPath = obj.trimStart().split(' ')[0];
|
|
148
|
+
|
|
149
|
+
// split objPath to serverName,dbName,objName
|
|
150
|
+
let serverName = undefined;
|
|
151
|
+
let dbName = undefined;
|
|
152
|
+
let objName = undefined;
|
|
153
|
+
const objPathArray = objPath.split('.');
|
|
154
|
+
if (objPathArray.length > 2) {
|
|
155
|
+
serverName = objPathArray[0]
|
|
156
|
+
dbName = objPathArray[1]
|
|
157
|
+
objName = objPathArray[2]
|
|
158
|
+
}
|
|
159
|
+
else if (objPathArray.length > 1) {
|
|
160
|
+
dbName = objPathArray[0]
|
|
161
|
+
objName = objPathArray[1]
|
|
162
|
+
}
|
|
163
|
+
else if (objPathArray.length > 0) {
|
|
164
|
+
objName = objPathArray[0]
|
|
165
|
+
}
|
|
166
|
+
|
|
167
|
+
// server
|
|
168
|
+
if (!serverName || serverName.length == 0) {
|
|
169
|
+
if (!schema.servers || !Object.keys(schema.servers)[0]) throw new TypeError('missing default server in dbSchema');
|
|
170
|
+
serverName = Object.keys(schema.servers)[0];
|
|
171
|
+
}
|
|
172
|
+
else { // add server to schema
|
|
173
|
+
if (!schema.servers) { schema.servers = {} };
|
|
174
|
+
if (!schema.servers[serverName]) { schema.servers[serverName] = {} };
|
|
175
|
+
}
|
|
176
|
+
if (!schema.servers[serverName].realName) { schema.servers[serverName].realName = serverName } // add realName
|
|
177
|
+
|
|
178
|
+
// database
|
|
179
|
+
if (!dbName || dbName.length == 0) {
|
|
180
|
+
if (!schema.servers[serverName].databases || !Object.keys(schema.servers[serverName].databases)[0]) throw new TypeError('missing default database in dbSchema');
|
|
181
|
+
dbName = Object.keys(schema.servers[serverName].databases)[0];
|
|
182
|
+
}
|
|
183
|
+
else { // add db to schema
|
|
184
|
+
if (!schema.servers[serverName].databases) { schema.servers[serverName].databases = {} };
|
|
185
|
+
if (!schema.servers[serverName].databases[dbName]) { schema.servers[serverName].databases[dbName] = {} };
|
|
186
|
+
}
|
|
187
|
+
if (!schema.servers[serverName].databases[dbName].realName) { schema.servers[serverName].databases[dbName].realName = dbName } // add realName
|
|
188
|
+
|
|
189
|
+
// table
|
|
190
|
+
if (objType === objectType.table || objType == undefined) {
|
|
191
|
+
if (!objName || objName.length == 0) {
|
|
192
|
+
if (!schema.servers[serverName].databases[dbName] || !Object.keys(schema.servers[serverName].databases[dbName].tables)[0]) throw new TypeError('missing default table in dbSchema');
|
|
193
|
+
objName = Object.keys(schema.servers[serverName].databases[dbName].tables)[0];
|
|
194
|
+
}
|
|
195
|
+
else { // add table to schema
|
|
196
|
+
if (!schema.servers[serverName].databases[dbName].tables) { schema.servers[serverName].databases[dbName].tables = {} };
|
|
197
|
+
if (!schema.servers[serverName].databases[dbName].tables[objName]) { schema.servers[serverName].databases[dbName].tables[objName] = {} }
|
|
198
|
+
}
|
|
199
|
+
if (!schema.servers[serverName].databases[dbName].tables[objName].realName) { schema.servers[serverName].databases[dbName].tables[objName].realName = objName } // add realName
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
// store procedure
|
|
203
|
+
if (objType === objectType.procedure) {
|
|
204
|
+
if (!objName || objName.length == 0) {
|
|
205
|
+
if (!schema.servers[serverName].databases[dbName] || !Object.keys(schema.servers[serverName].databases[dbName].procedures)[0]) throw new TypeError('missing default procedure in dbSchema');
|
|
206
|
+
objName = Object.keys(schema.servers[serverName].databases[dbName].procedures)[0];
|
|
207
|
+
}
|
|
208
|
+
else { // add storeprocedure to schema
|
|
209
|
+
if (!schema.servers[serverName].databases[dbName].procedures) { schema.servers[serverName].databases[dbName].procedures = {} };
|
|
210
|
+
if (!schema.servers[serverName].databases[dbName].procedures[objName]) { schema.servers[serverName].databases[dbName].procedures[objName] = {command: obj} }
|
|
211
|
+
}
|
|
212
|
+
if (!schema.servers[serverName].databases[dbName].procedures[objName].realName) { schema.servers[serverName].databases[dbName].procedures[objName].realName = objName } // add realName
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// return Schema
|
|
216
|
+
return {
|
|
217
|
+
table: (objType == undefined || objType === objectType.table) ? schema.servers[serverName].databases[dbName].tables[objName] : undefined,
|
|
218
|
+
procedure: (objType === objectType.procedure) ? schema.servers[serverName].databases[dbName].procedures[objName] : undefined,
|
|
219
|
+
database: schema.servers[serverName].databases[dbName],
|
|
220
|
+
server: schema.servers[serverName]
|
|
221
|
+
}
|
|
222
|
+
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
export function prepareRun(tSchema, connection, reqOpe) {
|
|
226
|
+
const _reqOpe = [];
|
|
227
|
+
const _result = [];
|
|
228
|
+
if (Array.isArray(reqOpe)) _reqOpe.push(...reqOpe);
|
|
229
|
+
else _reqOpe.push(reqOpe);
|
|
230
|
+
_reqOpe.forEach(function (_ope) {
|
|
231
|
+
if (_ope?.get) _result.push(prepareGet(tSchema, connection, _ope));
|
|
232
|
+
else if (_ope?.patch) _result.push(preparePatch(tSchema, connection, _ope));
|
|
233
|
+
else if (_ope?.put) _result.push(preparePut(tSchema, connection, _ope));
|
|
234
|
+
else if (_ope?.delete) _result.push(prepareDelete(tSchema, connection, _ope));
|
|
235
|
+
else if (_ope?.execute) _result.push(prepareExecute(connection, _ope));
|
|
236
|
+
else if (_ope?.begin) _result.push(prepareBegin(connection, _ope));
|
|
237
|
+
else if (_ope?.commit) _result.push(prepareCommit(connection, _ope));
|
|
238
|
+
else if (_ope?.rollback) _result.push(prepareRollback(connection, _ope));
|
|
239
|
+
else if (_ope?.passthrough) _result.push(preparePassthrough(connection, _ope));
|
|
240
|
+
else throw new Error('Request sintax error, missing property get/patch/put/delete/...');
|
|
241
|
+
});
|
|
242
|
+
if (_result.length > 1) return _result;
|
|
243
|
+
if (_result.length = 1) return _result[0];
|
|
244
|
+
return undefined;
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
export function prepareRunById(tSchema, connection, reqOpe, idValue) {
|
|
248
|
+
if (reqOpe?.get) return prepareGetById(tSchema, connection, reqOpe, idValue);
|
|
249
|
+
if (reqOpe?.patch) return preparePatchById(tSchema, connection, reqOpe, idValue);
|
|
250
|
+
if (reqOpe?.put) return preparePutById(tSchema, connection, reqOpe, idValue);
|
|
251
|
+
if (reqOpe?.delete) return prepareDeleteById(tSchema, connection, reqOpe, idValue);
|
|
252
|
+
else throw new Error('Request sintax error, missing property get/patch/put/delete...');
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
export function prepareGet(tSchema, connection, reqOpe) {
|
|
256
|
+
const _reqOpe = [];
|
|
257
|
+
const _result = [];
|
|
258
|
+
if (Array.isArray(reqOpe)) _reqOpe.push(...reqOpe);
|
|
259
|
+
else _reqOpe.push(reqOpe);
|
|
260
|
+
_reqOpe.forEach(function (_ope) {
|
|
261
|
+
_result.push({
|
|
262
|
+
get: {
|
|
263
|
+
schema: tSchema,
|
|
264
|
+
options: _ope?.get?.options,
|
|
265
|
+
fields: _ope?.get?.fields ?? defautlFields,
|
|
266
|
+
filters: _ope?.get?.filters,
|
|
267
|
+
groups: _ope?.get?.groups,
|
|
268
|
+
groupsFilters: _ope?.get?.groupsFilters,
|
|
269
|
+
orderBy: _ope?.get?.orderBy,
|
|
270
|
+
params: _ope?.get?.params
|
|
271
|
+
},
|
|
272
|
+
connection: connection,
|
|
273
|
+
appLog: _ope?.hasOwnProperty('appLog') ? _ope.appLog : undefined
|
|
274
|
+
});
|
|
275
|
+
});
|
|
276
|
+
if (_result.length > 1) return _result;
|
|
277
|
+
if (_result.length = 1) return _result[0];
|
|
278
|
+
return undefined;
|
|
279
|
+
};
|
|
280
|
+
|
|
281
|
+
export function prepareGetById(tSchema, connection, reqOpe, idValue) {
|
|
282
|
+
const _filters = [idField(tSchema) + ' = ' + toStringValue(idValue)];
|
|
283
|
+
if (reqOpe?.get?.filters && reqOpe?.get?.filters.length > 0) {
|
|
284
|
+
_filters.push('and');
|
|
285
|
+
Array.isArray(reqOpe.get.filters) ? _filters.push(...reqOpe.get.filters) : _filters.push(reqOpe.get.filters);
|
|
286
|
+
}
|
|
287
|
+
return {
|
|
288
|
+
get: {
|
|
289
|
+
schema: tSchema,
|
|
290
|
+
options: reqOpe?.get?.options,
|
|
291
|
+
fields: reqOpe?.get?.fields ?? defautlFields,
|
|
292
|
+
filters: _filters
|
|
293
|
+
},
|
|
294
|
+
connection: connection,
|
|
295
|
+
appLog: reqOpe?.hasOwnProperty('appLog') ? reqOpe.appLog : undefined
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
export function preparePatch(tSchema, connection, reqOpe) {
|
|
300
|
+
const _reqOpe = [];
|
|
301
|
+
const _result = [];
|
|
302
|
+
if (Array.isArray(reqOpe)) _reqOpe.push(...reqOpe);
|
|
303
|
+
else _reqOpe.push(reqOpe);
|
|
304
|
+
_reqOpe.forEach(function (_ope) {
|
|
305
|
+
if (_ope?.patch) {
|
|
306
|
+
if (!_ope.patch.sets) throw new Error('Request sintax error, missing "patch.sets" property.')
|
|
307
|
+
_result.push({
|
|
308
|
+
patch: {
|
|
309
|
+
schema: tSchema,
|
|
310
|
+
sets: _ope.patch.sets,
|
|
311
|
+
filters: _ope.patch.filters,
|
|
312
|
+
params: _ope.patch.params
|
|
313
|
+
},
|
|
314
|
+
connection: connection,
|
|
315
|
+
appLog: _ope.hasOwnProperty('appLog') ? _ope.appLog : undefined
|
|
316
|
+
});
|
|
317
|
+
}
|
|
318
|
+
else throw new Error('Request sintax error, missing "patch" property.');
|
|
319
|
+
});
|
|
320
|
+
if (_result.length > 1) return _result;
|
|
321
|
+
if (_result.length = 1) return _result[0];
|
|
322
|
+
return undefined;
|
|
323
|
+
};
|
|
324
|
+
|
|
325
|
+
export function preparePatchById(tSchema, connection, reqOpe, idValue) {
|
|
326
|
+
if (!reqOpe?.patch) throw new Error('Request sintax error, missing "patch" property.')
|
|
327
|
+
if (!reqOpe.patch.sets) throw new Error('Missing "patch.sets" in operation.')
|
|
328
|
+
const _filters = [idField(tSchema) + ' = ' + toStringValue(idValue)];
|
|
329
|
+
if (reqOpe?.patch?.filters && reqOpe?.patch?.filters.length > 0) {
|
|
330
|
+
_filters.push('and');
|
|
331
|
+
Array.isArray(reqOpe.patch.filters) ? _filters.push(...reqOpe.patch.filters) : _filters.push(reqOpe.patch.filters);
|
|
332
|
+
}
|
|
333
|
+
return {
|
|
334
|
+
patch: {
|
|
335
|
+
schema: tSchema,
|
|
336
|
+
sets: reqOpe.patch.sets,
|
|
337
|
+
filters: _filters
|
|
338
|
+
},
|
|
339
|
+
connection: connection,
|
|
340
|
+
appLog: reqOpe.hasOwnProperty('appLog') ? reqOpe.appLog : undefined
|
|
341
|
+
}
|
|
342
|
+
};
|
|
343
|
+
|
|
344
|
+
export function preparePut(tSchema, connection, reqOpe) {
|
|
345
|
+
const _reqOpe = [];
|
|
346
|
+
const _result = [];
|
|
347
|
+
if (Array.isArray(reqOpe)) _reqOpe.push(...reqOpe);
|
|
348
|
+
else _reqOpe.push(reqOpe);
|
|
349
|
+
_reqOpe.forEach(function (_ope) {
|
|
350
|
+
if (_ope?.put) {
|
|
351
|
+
if (!_ope.put.sets) throw new Error('Request sintax error, missing "put.sets" property.')
|
|
352
|
+
_result.push({
|
|
353
|
+
put: {
|
|
354
|
+
schema: tSchema,
|
|
355
|
+
sets: _ope.put.sets,
|
|
356
|
+
params: _ope.put.params
|
|
357
|
+
},
|
|
358
|
+
connection: connection,
|
|
359
|
+
appLog: _ope.hasOwnProperty('appLog') ? _ope.appLog : undefined
|
|
360
|
+
});
|
|
361
|
+
}
|
|
362
|
+
else throw new Error('Request sintax error, missing "put" property.');
|
|
363
|
+
});
|
|
364
|
+
if (_result.length > 1) return _result;
|
|
365
|
+
if (_result.length = 1) return _result[0];
|
|
366
|
+
return undefined;
|
|
367
|
+
};
|
|
368
|
+
|
|
369
|
+
export function preparePutById(tSchema, connection, reqOpe, idValue) {
|
|
370
|
+
if (!reqOpe?.put) throw new Error('Request sintax error, missing "put" property.')
|
|
371
|
+
if (!reqOpe.put.sets) throw new Error('Missing "put.sets" in operation.')
|
|
372
|
+
upsertProperty(reqOpe.put.sets, idField(tSchema), idValue);
|
|
373
|
+
return {
|
|
374
|
+
put: {
|
|
375
|
+
schema: tSchema,
|
|
376
|
+
sets: reqOpe.put.sets,
|
|
377
|
+
params: reqOpe.put.params
|
|
378
|
+
},
|
|
379
|
+
connection: connection,
|
|
380
|
+
appLog: reqOpe.hasOwnProperty('appLog') ? reqOpe.appLog : undefined
|
|
381
|
+
}
|
|
382
|
+
};
|
|
383
|
+
|
|
384
|
+
export function prepareDelete(tSchema, connection, reqOpe) {
|
|
385
|
+
const _reqOpe = [];
|
|
386
|
+
const _result = [];
|
|
387
|
+
if (Array.isArray(reqOpe)) _reqOpe.push(...reqOpe);
|
|
388
|
+
else _reqOpe.push(reqOpe);
|
|
389
|
+
_reqOpe.forEach(function (_ope) {
|
|
390
|
+
if (_ope?.delete) {
|
|
391
|
+
_result.push({
|
|
392
|
+
delete: {
|
|
393
|
+
schema: tSchema,
|
|
394
|
+
filters: _ope.delete.filters,
|
|
395
|
+
params: _ope.delete.params
|
|
396
|
+
},
|
|
397
|
+
connection: connection,
|
|
398
|
+
appLog: _ope.hasOwnProperty('appLog') ? _ope.appLog : undefined
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
else throw new Error('Request sintax error, missing "delete" property.');
|
|
402
|
+
});
|
|
403
|
+
if (_result.length > 1) return _result;
|
|
404
|
+
if (_result.length = 1) return _result[0];
|
|
405
|
+
return undefined;
|
|
406
|
+
};
|
|
407
|
+
|
|
408
|
+
export function prepareDeleteById(tSchema, connection, reqOpe, idValue) {
|
|
409
|
+
return {
|
|
410
|
+
delete: {
|
|
411
|
+
schema: tSchema,
|
|
412
|
+
filters: [idField(tSchema) + ' = ' + toStringValue(idValue)]
|
|
413
|
+
},
|
|
414
|
+
connection: connection,
|
|
415
|
+
appLog: reqOpe.hasOwnProperty('appLog') ? reqOpe.appLog : undefined
|
|
416
|
+
}
|
|
417
|
+
};
|
|
418
|
+
|
|
419
|
+
export function prepareExecute(pSchema, connection, reqOpe) {
|
|
420
|
+
const _reqOpe = [];
|
|
421
|
+
const _result = [];
|
|
422
|
+
if (Array.isArray(reqOpe)) _reqOpe.push(...reqOpe);
|
|
423
|
+
else _reqOpe.push(reqOpe);
|
|
424
|
+
_reqOpe.forEach(function (_ope) {
|
|
425
|
+
_result.push({
|
|
426
|
+
execute: {
|
|
427
|
+
schema: pSchema,
|
|
428
|
+
arguments: _ope.execute?.arguments,
|
|
429
|
+
params: _ope.execute?.params
|
|
430
|
+
},
|
|
431
|
+
connection: connection,
|
|
432
|
+
appLog: _ope.hasOwnProperty('appLog') ? _ope.appLog : undefined
|
|
433
|
+
});
|
|
434
|
+
});
|
|
435
|
+
if (_result.length > 1) return _result;
|
|
436
|
+
if (_result.length = 1) return _result[0];
|
|
437
|
+
return undefined;
|
|
438
|
+
};
|
|
439
|
+
|
|
440
|
+
export function preparePassthrough(connection, reqOpe) {
|
|
441
|
+
const _reqOpe = [];
|
|
442
|
+
const _result = [];
|
|
443
|
+
if (Array.isArray(reqOpe)) _reqOpe.push(...reqOpe);
|
|
444
|
+
else _reqOpe.push(reqOpe);
|
|
445
|
+
_reqOpe.forEach(function (_ope) {
|
|
446
|
+
if (_ope?.passthrough) {
|
|
447
|
+
if (!_ope.passthrough.command) throw new Error('Request sintax error, missing "passthrough.command" property.')
|
|
448
|
+
_result.push({
|
|
449
|
+
passthrough: {
|
|
450
|
+
command: _ope.passthrough.command,
|
|
451
|
+
params: _ope.passthrough.params
|
|
452
|
+
},
|
|
453
|
+
connection: connection,
|
|
454
|
+
appLog: _ope.hasOwnProperty('appLog') ? _ope.appLog : undefined
|
|
455
|
+
});
|
|
456
|
+
}
|
|
457
|
+
else throw new Error('Request sintax error, missing "passthrough" property.');
|
|
458
|
+
});
|
|
459
|
+
if (_result.length > 1) return _result;
|
|
460
|
+
if (_result.length = 1) return _result[0];
|
|
461
|
+
return undefined;
|
|
462
|
+
};
|
|
463
|
+
|
|
464
|
+
export function prepareBegin(connection, reqOpe) {
|
|
465
|
+
return {
|
|
466
|
+
begin: {},
|
|
467
|
+
connection: connection,
|
|
468
|
+
appLog: reqOpe.hasOwnProperty('appLog') ? reqOpe.appLog : undefined
|
|
469
|
+
}
|
|
470
|
+
};
|
|
471
|
+
|
|
472
|
+
export function prepareCommit(connection, reqOpe) {
|
|
473
|
+
return {
|
|
474
|
+
commit: {},
|
|
475
|
+
connection: connection,
|
|
476
|
+
appLog: reqOpe.hasOwnProperty('appLog') ? reqOpe.appLog : undefined
|
|
477
|
+
}
|
|
478
|
+
};
|
|
479
|
+
|
|
480
|
+
export function prepareRollback(connection, reqOpe) {
|
|
481
|
+
return {
|
|
482
|
+
rollback: {},
|
|
483
|
+
connection: connection,
|
|
484
|
+
appLog: reqOpe.hasOwnProperty('appLog') ? reqOpe.appLog : undefined
|
|
485
|
+
}
|
|
486
|
+
};
|
package/lib/mssql.js
CHANGED
|
@@ -11,24 +11,49 @@ const pools = {};
|
|
|
11
11
|
|
|
12
12
|
// Common
|
|
13
13
|
function stringifyValue(fieldName, value, tSchema) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
14
|
+
|
|
15
|
+
// null or undefined
|
|
16
|
+
if (value == undefined)
|
|
17
|
+
return 'null';
|
|
18
|
+
|
|
19
|
+
// detect field type from schema
|
|
20
|
+
let _fieldType = undefined;
|
|
21
|
+
if (tSchema.table.fields && tSchema.table.fields[fieldName] && tSchema.table.fields[fieldName].type) {
|
|
22
|
+
_fieldType = tSchema.table.fields[fieldName].type;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// if datetime
|
|
26
|
+
if (_fieldType == 'datetime') {
|
|
27
|
+
// my-sql not accepts 'Z' at end of ISO string
|
|
28
|
+
if (value instanceof Date) return `\'${value.toISOString()}\'`;
|
|
29
|
+
if (typeof value == 'string') {
|
|
30
|
+
const valueDate = new Date(Date.parse(value));
|
|
31
|
+
return `\'${valueDate.toISOString()}\'`;
|
|
25
32
|
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
33
|
+
return value;
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
// if boolean
|
|
37
|
+
if (_fieldType == 'boolean' && typeof value == 'boolean')
|
|
38
|
+
return `\'${value}\'`;
|
|
39
|
+
|
|
40
|
+
// if string or uuid
|
|
41
|
+
if (_fieldType == 'string' || _fieldType == 'uuid') {
|
|
42
|
+
if (value.trimStart().charAt(0) !== '\'' && value.trimStart().charAt(0) !== '\"') {
|
|
43
|
+
return `\'${value}\'`;
|
|
30
44
|
}
|
|
31
45
|
}
|
|
46
|
+
|
|
47
|
+
// field not in schema
|
|
48
|
+
if (_fieldType == undefined) {
|
|
49
|
+
if (value instanceof Date)
|
|
50
|
+
return `\'${value.toISOString()}\'`;
|
|
51
|
+
if (typeof value == 'boolean')
|
|
52
|
+
return `\'${value}\'`;
|
|
53
|
+
if (typeof value == 'string' && value.trimStart().charAt(0) !== '\'' && value.trimStart().charAt(0) !== '\"')
|
|
54
|
+
return `\'${value}\'`;
|
|
55
|
+
}
|
|
56
|
+
|
|
32
57
|
return value;
|
|
33
58
|
}
|
|
34
59
|
|
|
@@ -106,21 +131,34 @@ export async function query(connection, dbOpes) {
|
|
|
106
131
|
// Prepare sql statement
|
|
107
132
|
let sqlString = '';
|
|
108
133
|
let sqlRequest = pool.request();
|
|
134
|
+
let appLog = true;
|
|
109
135
|
// if exists, input params will be added to request
|
|
110
|
-
if (Array.isArray(dbOpes))
|
|
111
|
-
|
|
136
|
+
if (Array.isArray(dbOpes)) {
|
|
137
|
+
dbOpes.forEach((dbOpe, index) => {
|
|
138
|
+
sqlString += ToSql(dbOpe, sqlRequest);
|
|
139
|
+
if (dbOpe.hasOwnProperty('appLog') && dbOpe.appLog === false) appLog = false;
|
|
140
|
+
});
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
sqlString += ToSql(dbOpes, sqlRequest);
|
|
144
|
+
if (dbOpes.hasOwnProperty('appLog') && dbOpes.appLog === false) appLog = false;
|
|
145
|
+
}
|
|
112
146
|
|
|
113
147
|
sqlString = normalizeSpecialName(sqlString);
|
|
114
148
|
|
|
115
149
|
// Log
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
150
|
+
if (appLog) {
|
|
151
|
+
log(sqlString, 50);
|
|
152
|
+
log(JSON.stringify(dbOpes), 60);
|
|
153
|
+
}
|
|
154
|
+
|
|
119
155
|
// Run query
|
|
120
156
|
const sqlresult = await sqlRequest.query(sqlString);
|
|
121
157
|
|
|
122
158
|
// Log
|
|
123
|
-
|
|
159
|
+
if (appLog) {
|
|
160
|
+
log(`Query result: ${sqlresult.recordset ? sqlresult.recordset.length : 0} rows.`, 50);
|
|
161
|
+
}
|
|
124
162
|
|
|
125
163
|
// normalize return object
|
|
126
164
|
if (sqlresult.recordset == undefined) return;
|
|
@@ -129,14 +167,36 @@ export async function query(connection, dbOpes) {
|
|
|
129
167
|
return sqlresult.recordset;
|
|
130
168
|
}
|
|
131
169
|
|
|
132
|
-
// Normalize
|
|
133
|
-
function normalizeSpecialName(
|
|
134
|
-
let
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
170
|
+
// Normalize SQL to replace backticks with square brackets, considering quoted strings
|
|
171
|
+
function normalizeSpecialName(sqlString) {
|
|
172
|
+
let result = "";
|
|
173
|
+
let inSingleQuote = false;
|
|
174
|
+
let inDoubleQuote = false;
|
|
175
|
+
let msSqlOpening = true; // Serve per alternare [ e ] in modalità mssql
|
|
176
|
+
|
|
177
|
+
for (let i = 0; i < sqlString.length; i++) {
|
|
178
|
+
const char = sqlString[i];
|
|
179
|
+
|
|
180
|
+
// Gestione delle stringhe (costanti)
|
|
181
|
+
if (char === "'" && !inDoubleQuote) {
|
|
182
|
+
inSingleQuote = !inSingleQuote;
|
|
183
|
+
} else if (char === '"' && !inSingleQuote) {
|
|
184
|
+
inDoubleQuote = !inDoubleQuote;
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
// Se siamo fuori dalle citazioni, applichiamo la logica di conversione
|
|
188
|
+
if (!inSingleQuote && !inDoubleQuote) {
|
|
189
|
+
if (char === '`') {
|
|
190
|
+
result += msSqlOpening ? '[' : ']';
|
|
191
|
+
msSqlOpening = !msSqlOpening; // Alterna per il prossimo backtick
|
|
192
|
+
continue;
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
result += char;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
return result;
|
|
140
200
|
}
|
|
141
201
|
|
|
142
202
|
// Compose fully qualified table name
|