db-crud-wrapper 1.0.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/CHANGELOG.md +81 -0
- package/README.md +96 -0
- package/index.js +5 -0
- package/lib/builder.js +404 -0
- package/lib/config.js +287 -0
- package/lib/db-operations.js +426 -0
- package/lib/f.js +45 -0
- package/lib/factory.js +89 -0
- package/lib/log.js +21 -0
- package/lib/mssql.js +483 -0
- package/lib/mysql.js +532 -0
- package/lib/session-store.js +196 -0
- package/package.json +31 -0
package/lib/mssql.js
ADDED
|
@@ -0,0 +1,483 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
import sql from 'mssql';
|
|
4
|
+
import log from './log.js'
|
|
5
|
+
|
|
6
|
+
// Regex
|
|
7
|
+
const _match_LIMIT_n = /\bLIMIT\b +\d+/ig
|
|
8
|
+
const _match_LIMIT = /\bLIMIT\b/ig
|
|
9
|
+
|
|
10
|
+
const pools = {};
|
|
11
|
+
|
|
12
|
+
// Common
|
|
13
|
+
function isExpression(str) {
|
|
14
|
+
if (typeof str !== 'string') return false;
|
|
15
|
+
const trimmed = str.trim();
|
|
16
|
+
return (trimmed.startsWith('[') && trimmed.endsWith(']')) ||
|
|
17
|
+
(trimmed.startsWith('`') && trimmed.endsWith('`'));
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
function removeExpressionDelimiters(str) {
|
|
21
|
+
if (typeof str !== 'string') return str;
|
|
22
|
+
const trimmed = str.trim();
|
|
23
|
+
if ((trimmed.startsWith('[') && trimmed.endsWith(']')) ||
|
|
24
|
+
(trimmed.startsWith('`') && trimmed.endsWith('`'))) {
|
|
25
|
+
return trimmed.slice(1, -1);
|
|
26
|
+
}
|
|
27
|
+
return str;
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
function stringifyValue(fieldName, value, tSchema) {
|
|
31
|
+
|
|
32
|
+
// null or undefined
|
|
33
|
+
if (value == undefined)
|
|
34
|
+
return 'null';
|
|
35
|
+
|
|
36
|
+
// if values is an expression than remove delimiters
|
|
37
|
+
if (isExpression(value)) {
|
|
38
|
+
return removeExpressionDelimiters(value);
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
// detect field type from schema
|
|
42
|
+
let _fieldType = undefined;
|
|
43
|
+
if (tSchema.table.fields && tSchema.table.fields[fieldName] && tSchema.table.fields[fieldName].type) {
|
|
44
|
+
_fieldType = tSchema.table.fields[fieldName].type;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// if datetime
|
|
48
|
+
if (_fieldType == 'datetime') {
|
|
49
|
+
if (value instanceof Date) return `\'${value.toISOString()}\'`;
|
|
50
|
+
if (typeof value == 'string') {
|
|
51
|
+
const valueDate = new Date(Date.parse(value));
|
|
52
|
+
return `\'${valueDate.toISOString()}\'`;
|
|
53
|
+
}
|
|
54
|
+
return value;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
// if boolean
|
|
58
|
+
if (_fieldType == 'boolean' && typeof value == 'boolean')
|
|
59
|
+
return `\'${value}\'`;
|
|
60
|
+
|
|
61
|
+
// if string or uuid
|
|
62
|
+
if (_fieldType == 'string' || _fieldType == 'uuid') {
|
|
63
|
+
return `\'${String(value).replace(/'/g, "''")}\'`;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
// field not in schema
|
|
67
|
+
if (_fieldType == undefined) {
|
|
68
|
+
if (value instanceof Date)
|
|
69
|
+
return `\'${value.toISOString()}\'`;
|
|
70
|
+
if (typeof value == 'boolean')
|
|
71
|
+
return `\'${value}\'`;
|
|
72
|
+
if (typeof value == 'string')
|
|
73
|
+
return `\'${value.replace(/'/g, "''")}\'`;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
return value;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
// Create config object for pool
|
|
80
|
+
export function prepareConnection(tSchema) {
|
|
81
|
+
return {
|
|
82
|
+
id: `${tSchema.server.realName}-${tSchema.database.realName}-${tSchema.server.user}`,
|
|
83
|
+
server: ((tSchema.server.instance && tSchema.server.instance != 'DEFAULT') ? (tSchema.server.realName + '\\' + tSchema.server.instance) : tSchema.server.realName) ?? 'localhost',
|
|
84
|
+
port: tSchema.server.port,
|
|
85
|
+
user: tSchema.server.user,
|
|
86
|
+
password: tSchema.server.password,
|
|
87
|
+
options: {
|
|
88
|
+
appName: tSchema.server.options?.appName,
|
|
89
|
+
encrypt: tSchema.server.options?.encrypt ?? false, // true for azure
|
|
90
|
+
trustServerCertificate: tSchema.server.options?.trustServerCertificate ?? true // true for local dev / self-signed certs
|
|
91
|
+
},
|
|
92
|
+
pool: tSchema.server.pool,
|
|
93
|
+
database: tSchema.database.realName
|
|
94
|
+
};
|
|
95
|
+
};
|
|
96
|
+
|
|
97
|
+
// Close connection
|
|
98
|
+
export async function closeConnection(connection) {
|
|
99
|
+
let pool = pools[connection.id];
|
|
100
|
+
if (pool) {
|
|
101
|
+
await pool.close(); // wait pool is closed
|
|
102
|
+
pools[connection.id] = undefined; // remove pool from pools
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
// Close all connections
|
|
107
|
+
export async function closeAllConnections() {
|
|
108
|
+
for (let poolId in pools) {
|
|
109
|
+
if (!pools.hasOwnProperty(poolId)) continue;
|
|
110
|
+
let pool = pools[poolId];
|
|
111
|
+
if (pool) {
|
|
112
|
+
await pool.close(); // wait pool is closed
|
|
113
|
+
pool = undefined; // remove pool from pools
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
// Test connection
|
|
119
|
+
export async function testConnection(connection) {
|
|
120
|
+
|
|
121
|
+
let _connection;
|
|
122
|
+
try {
|
|
123
|
+
_connection = await sql.connect(connection);
|
|
124
|
+
return true;
|
|
125
|
+
}
|
|
126
|
+
catch (error) {
|
|
127
|
+
throw (error);
|
|
128
|
+
}
|
|
129
|
+
finally {
|
|
130
|
+
if (_connection) {
|
|
131
|
+
await _connection.close();
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Query
|
|
138
|
+
export async function query(connection, dbOpes, rawResult = false) {
|
|
139
|
+
|
|
140
|
+
// Prepare pool
|
|
141
|
+
let pool = pools[connection.id]; // Try to get an existing pool
|
|
142
|
+
if (!pool) {
|
|
143
|
+
pool = new sql.ConnectionPool(connection); // Create new pool
|
|
144
|
+
try {
|
|
145
|
+
await pool.connect(); // wait that connection are made
|
|
146
|
+
} catch (err) {
|
|
147
|
+
throw (err); // using original error
|
|
148
|
+
}
|
|
149
|
+
pools[connection.id] = pool; // add new pool to pools
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
// Prepare sql statement
|
|
153
|
+
let sqlString = '';
|
|
154
|
+
let sqlRequest = pool.request();
|
|
155
|
+
let appLog = true;
|
|
156
|
+
// if exists, input params will be added to request
|
|
157
|
+
if (Array.isArray(dbOpes)) {
|
|
158
|
+
dbOpes.forEach((dbOpe, index) => {
|
|
159
|
+
sqlString += ToSql(dbOpe, sqlRequest);
|
|
160
|
+
if (dbOpe.hasOwnProperty('appLog') && dbOpe.appLog === false) appLog = false;
|
|
161
|
+
});
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
sqlString += ToSql(dbOpes, sqlRequest);
|
|
165
|
+
if (dbOpes.hasOwnProperty('appLog') && dbOpes.appLog === false) appLog = false;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
sqlString = normalizeSpecialName(sqlString);
|
|
169
|
+
|
|
170
|
+
// Log
|
|
171
|
+
if (appLog) {
|
|
172
|
+
log(sqlString, 50);
|
|
173
|
+
log(JSON.stringify(dbOpes), 60);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
// Run query
|
|
177
|
+
const sqlresult = await sqlRequest.query(sqlString);
|
|
178
|
+
|
|
179
|
+
// normalize return object
|
|
180
|
+
const _return = normalizeQueryResults(sqlresult);
|
|
181
|
+
|
|
182
|
+
// Log
|
|
183
|
+
if (appLog) {
|
|
184
|
+
if (Array.isArray(dbOpes)) // multiple query
|
|
185
|
+
log(`Batch return ${Number.isInteger(_return) ? _return : Array.isArray(_return) ? _return.length : _return ? 1 : 0} result(s).`, 50)
|
|
186
|
+
else
|
|
187
|
+
log(`Query result: ${Number.isInteger(_return) ? _return : Array.isArray(_return) ? _return.length : _return ? 1 : 0} row(s).`, 50)
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
// return
|
|
191
|
+
return rawResult ? sqlresult : _return;
|
|
192
|
+
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
// Normalize SQL to replace backticks with square brackets, considering quoted strings
|
|
196
|
+
function normalizeSpecialName(sqlString) {
|
|
197
|
+
let result = "";
|
|
198
|
+
let inSingleQuote = false;
|
|
199
|
+
let inDoubleQuote = false;
|
|
200
|
+
let msSqlOpening = true; // Serve per alternare [ e ] in modalità mssql
|
|
201
|
+
|
|
202
|
+
for (let i = 0; i < sqlString.length; i++) {
|
|
203
|
+
const char = sqlString[i];
|
|
204
|
+
|
|
205
|
+
// Gestione delle stringhe (costanti)
|
|
206
|
+
if (char === "'" && !inDoubleQuote) {
|
|
207
|
+
inSingleQuote = !inSingleQuote;
|
|
208
|
+
} else if (char === '"' && !inSingleQuote) {
|
|
209
|
+
inDoubleQuote = !inDoubleQuote;
|
|
210
|
+
}
|
|
211
|
+
|
|
212
|
+
// Se siamo fuori dalle citazioni, applichiamo la logica di conversione
|
|
213
|
+
if (!inSingleQuote && !inDoubleQuote) {
|
|
214
|
+
if (char === '`') {
|
|
215
|
+
result += msSqlOpening ? '[' : ']';
|
|
216
|
+
msSqlOpening = !msSqlOpening; // Alterna per il prossimo backtick
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
result += char;
|
|
222
|
+
}
|
|
223
|
+
|
|
224
|
+
return result;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
// Compose fully qualified table name
|
|
228
|
+
function fullyQualifiedTableName(tSchema) {
|
|
229
|
+
return (tSchema.database.realName + '.' + (tSchema.table.schema ?? '') + '.' + tSchema.table.realName);
|
|
230
|
+
}
|
|
231
|
+
|
|
232
|
+
function containLIMIT(s) {
|
|
233
|
+
const _return = s?.match(_match_LIMIT_n);
|
|
234
|
+
if (_return) return _return[0];
|
|
235
|
+
else return undefined;
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
function replaceLIMITToTOP(s) {
|
|
239
|
+
const _replace = containLIMIT(s);
|
|
240
|
+
if (_replace) { return s.replace(_match_LIMIT_n, _replace.replace(_match_LIMIT, 'TOP')); }
|
|
241
|
+
else return s;
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Normalizza query results mssql.
|
|
246
|
+
* @param {Object} result - L'oggetto restituito da request.query() o request.execute()
|
|
247
|
+
* @returns {Array|number|Array<Array|number>} Risultati normalizzati
|
|
248
|
+
*/
|
|
249
|
+
function normalizeQueryResults(result) {
|
|
250
|
+
// 1. Gestione Batch / Multiple Statements
|
|
251
|
+
// Se ci sono più recordset o più conteggi di righe colpite
|
|
252
|
+
if (result.recordsets && result.recordsets.length > 1) {
|
|
253
|
+
return result.recordsets.map((set, index) => {
|
|
254
|
+
if (set.length > 0) {
|
|
255
|
+
return set; // Restituisce l'array di record per questa specifica query
|
|
256
|
+
}
|
|
257
|
+
// Se il recordset è vuoto, controlliamo se c'è un conteggio di righe per questa posizione
|
|
258
|
+
return result.rowsAffected[index] || 0;
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
|
|
262
|
+
// 2. Query SELECT singola
|
|
263
|
+
// Se recordset esiste ed è popolato, restituiamo i dati
|
|
264
|
+
if (result.recordset && result.recordset.length > 0) {
|
|
265
|
+
return result.recordset;
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
// 3. Query di Modifica singola (INSERT, UPDATE, DELETE)
|
|
269
|
+
// Se non ci sono record, restituiamo il totale delle righe colpite
|
|
270
|
+
if (result.rowsAffected && result.rowsAffected.length === 1) {
|
|
271
|
+
return result.rowsAffected[0];
|
|
272
|
+
}
|
|
273
|
+
|
|
274
|
+
// Fallback: se la SELECT non ha prodotto risultati, restituiamo un array vuoto
|
|
275
|
+
return result.recordset || [];
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// Parse oprations object to sql string
|
|
279
|
+
function ToSql(dbOpe, sqlRequest) {
|
|
280
|
+
if (dbOpe.get) return getToSql(dbOpe, sqlRequest);
|
|
281
|
+
if (dbOpe.post) return postToSql(dbOpe, sqlRequest);
|
|
282
|
+
if (dbOpe.patch) return patchToSql(dbOpe, sqlRequest);
|
|
283
|
+
if (dbOpe.put) return putToSql(dbOpe, sqlRequest);
|
|
284
|
+
if (dbOpe.delete) return deleteToSql(dbOpe, sqlRequest);
|
|
285
|
+
if (dbOpe.command) return commandToSql(dbOpe, sqlRequest);
|
|
286
|
+
if (dbOpe.begin) return beginToSql(dbOpe, sqlRequest);
|
|
287
|
+
if (dbOpe.commit) return commitToSql(dbOpe, sqlRequest);
|
|
288
|
+
if (dbOpe.passthrough) return passthroughToSql(dbOpe, sqlRequest);
|
|
289
|
+
throw new Error('Sintax error, missing property get/post/patch/put/delete/...');
|
|
290
|
+
}
|
|
291
|
+
|
|
292
|
+
// Parse operation object to sql string without any trasformation.
|
|
293
|
+
function passthroughToSql(dbOpe, sqlRequest) {
|
|
294
|
+
|
|
295
|
+
let result = "";
|
|
296
|
+
|
|
297
|
+
if (dbOpe.passthrough.command) {
|
|
298
|
+
result += dbOpe.passthrough.command;
|
|
299
|
+
}
|
|
300
|
+
else { throw new Error('command is missing.'); }
|
|
301
|
+
|
|
302
|
+
if (dbOpe.passthrough.params) addParams(dbOpe.passthrough.params, sqlRequest);
|
|
303
|
+
|
|
304
|
+
return result;
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
// Parse get operation object to sql string
|
|
308
|
+
function getToSql(dbOpe, sqlRequest) {
|
|
309
|
+
let _first = true;
|
|
310
|
+
|
|
311
|
+
let result = 'select'
|
|
312
|
+
|
|
313
|
+
if (dbOpe.get.options && dbOpe.get.options.length > 0) {
|
|
314
|
+
if (Array.isArray(dbOpe.get.options)) { for (const s of dbOpe.get.options) { result += ' ' + replaceLIMITToTOP(s); } }
|
|
315
|
+
else result += ' ' + replaceLIMITToTOP(dbOpe.get.options);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
if (dbOpe.get.fields && dbOpe.get.fields.length > 0) {
|
|
319
|
+
if (Array.isArray(dbOpe.get.fields)) result += ' ' + dbOpe.get.fields.join(',')
|
|
320
|
+
else result += ' ' + dbOpe.get.fields;
|
|
321
|
+
}
|
|
322
|
+
else { throw new Error('fields is missing.'); }
|
|
323
|
+
|
|
324
|
+
result += ' from ' + fullyQualifiedTableName(dbOpe.get.schema);
|
|
325
|
+
|
|
326
|
+
if (dbOpe.get.filters && dbOpe.get.filters.length > 0) {
|
|
327
|
+
if (Array.isArray(dbOpe.get.filters)) result += ' where ' + dbOpe.get.filters.join(' ');
|
|
328
|
+
else result += ' where ' + dbOpe.get.filters;
|
|
329
|
+
}
|
|
330
|
+
|
|
331
|
+
if (dbOpe.get.groupBy && dbOpe.get.groupBy.length > 0) {
|
|
332
|
+
if (Array.isArray(dbOpe.get.groupBy)) result += ' group by ' + dbOpe.get.groupBy.join(', ');
|
|
333
|
+
else result += ' group by ' + dbOpe.get.groupBy;
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
if (dbOpe.get.groupFilters && dbOpe.get.groupFilters.length > 0) {
|
|
337
|
+
if (Array.isArray(dbOpe.get.groupFilters)) result += ' having ' + dbOpe.get.groupFilters.join(' ');
|
|
338
|
+
else result += ' having ' + dbOpe.get.groupFilters;
|
|
339
|
+
}
|
|
340
|
+
|
|
341
|
+
if (dbOpe.get.orderBy && dbOpe.get.orderBy.length > 0) {
|
|
342
|
+
if (Array.isArray(dbOpe.get.orderBy)) result += ' order by ' + dbOpe.get.orderBy.join(', ');
|
|
343
|
+
else result += ' order by ' + dbOpe.get.orderBy;
|
|
344
|
+
}
|
|
345
|
+
|
|
346
|
+
if (dbOpe.get.params) addParams(dbOpe.get.params, sqlRequest);
|
|
347
|
+
|
|
348
|
+
result += ';'
|
|
349
|
+
|
|
350
|
+
return result;
|
|
351
|
+
}
|
|
352
|
+
|
|
353
|
+
// Parse patch operation object to sql string
|
|
354
|
+
function patchToSql(dbOpe, sqlRequest) {
|
|
355
|
+
let result = 'update ' + fullyQualifiedTableName(dbOpe.patch.schema);
|
|
356
|
+
|
|
357
|
+
if (dbOpe.patch.values) {
|
|
358
|
+
result += ' set ' + Object.entries(dbOpe.patch.values).map(e => { return e[0] + '=' + stringifyValue(e[0], e[1], dbOpe.patch.schema) }).join(', ');
|
|
359
|
+
}
|
|
360
|
+
else { throw new Error('values is missing.'); }
|
|
361
|
+
|
|
362
|
+
if (dbOpe.patch.filters && dbOpe.patch.filters.length > 0) {
|
|
363
|
+
if (Array.isArray(dbOpe.patch.filters)) result += ' where ' + dbOpe.patch.filters.join(' ');
|
|
364
|
+
else result += ' where ' + dbOpe.patch.filters;
|
|
365
|
+
}
|
|
366
|
+
|
|
367
|
+
if (dbOpe.patch.params) addParams(dbOpe.patch.params, sqlRequest);
|
|
368
|
+
|
|
369
|
+
result += ';'
|
|
370
|
+
|
|
371
|
+
return result;
|
|
372
|
+
}
|
|
373
|
+
|
|
374
|
+
// Parse post operation object to sql string
|
|
375
|
+
function postToSql(dbOpe, sqlRequest) {
|
|
376
|
+
let result = 'insert into ' + fullyQualifiedTableName(dbOpe.post.schema);
|
|
377
|
+
|
|
378
|
+
if ((dbOpe.post.values) && (Object.keys(dbOpe.post.values).length > 0)) {
|
|
379
|
+
let result_f = ' (';
|
|
380
|
+
let result_v = ' values (';
|
|
381
|
+
let _first = true;
|
|
382
|
+
for (const [key, value] of Object.entries(dbOpe.post.values)) {
|
|
383
|
+
if (!_first) {
|
|
384
|
+
result_f += ', ';
|
|
385
|
+
result_v += ', ';
|
|
386
|
+
} else {
|
|
387
|
+
_first = false
|
|
388
|
+
}
|
|
389
|
+
if (key || value) {
|
|
390
|
+
result_f += key;
|
|
391
|
+
result_v += stringifyValue(key, value, dbOpe.post.schema);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
394
|
+
result_f += ')'; result_v += ')';
|
|
395
|
+
result += result_f + result_v;
|
|
396
|
+
}
|
|
397
|
+
else { throw new Error('values is missing.'); }
|
|
398
|
+
|
|
399
|
+
if (dbOpe.post.params) addParams(dbOpe.post.params, sqlRequest);
|
|
400
|
+
|
|
401
|
+
result += ';'
|
|
402
|
+
|
|
403
|
+
return result;
|
|
404
|
+
}
|
|
405
|
+
|
|
406
|
+
// Parse put operation object to sql string
|
|
407
|
+
function putToSql(dbOpe, sqlRequest) {
|
|
408
|
+
let result = 'update ' + fullyQualifiedTableName(dbOpe.put.schema);
|
|
409
|
+
|
|
410
|
+
if (dbOpe.put.values) {
|
|
411
|
+
result += ' set ' + Object.entries(dbOpe.put.values).map(e => { return e[0] + '=' + stringifyValue(e[0], e[1], dbOpe.put.schema) }).join(', ');
|
|
412
|
+
}
|
|
413
|
+
else { throw new Error('values is missing.'); }
|
|
414
|
+
|
|
415
|
+
if (dbOpe.put.filters && dbOpe.put.filters.length > 0) {
|
|
416
|
+
if (Array.isArray(dbOpe.put.filters)) result += ' where ' + dbOpe.put.filters.join(' ');
|
|
417
|
+
else result += ' where ' + dbOpe.put.filters;
|
|
418
|
+
}
|
|
419
|
+
|
|
420
|
+
if (dbOpe.put.params) addParams(dbOpe.put.params, sqlRequest);
|
|
421
|
+
|
|
422
|
+
result += ';'
|
|
423
|
+
|
|
424
|
+
return result;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
// Parse delete operation object to sql string
|
|
428
|
+
function deleteToSql(dbOpe, sqlRequest) {
|
|
429
|
+
let result = 'delete from ' + fullyQualifiedTableName(dbOpe.delete.schema);
|
|
430
|
+
|
|
431
|
+
if (dbOpe.delete.filters && dbOpe.delete.filters.length > 0) {
|
|
432
|
+
if (Array.isArray(dbOpe.delete.filters)) result += ' where ' + dbOpe.delete.filters.join(' ');
|
|
433
|
+
else result += ' where ' + dbOpe.delete.filters;
|
|
434
|
+
}
|
|
435
|
+
|
|
436
|
+
if (dbOpe.delete.params) addParams(dbOpe.delete.params, sqlRequest);
|
|
437
|
+
|
|
438
|
+
result += ';'
|
|
439
|
+
|
|
440
|
+
return result;
|
|
441
|
+
}
|
|
442
|
+
|
|
443
|
+
// Parse command operation object to sql string
|
|
444
|
+
function commandToSql(dbOpe, sqlRequest) {
|
|
445
|
+
let result = "execute ";
|
|
446
|
+
|
|
447
|
+
if (dbOpe.command.schema.procedure) {
|
|
448
|
+
result += dbOpe.command.schema.procedure.command;
|
|
449
|
+
if (dbOpe.command.arguments) {
|
|
450
|
+
// if argument is string but not param, will be wrap into ''
|
|
451
|
+
result += (' ' + [].concat(dbOpe.command.arguments).map(item => {
|
|
452
|
+
return (typeof item === 'string' && !item.trimStart().startsWith("@")) ? `'${item}'` : item
|
|
453
|
+
}).join(', '));
|
|
454
|
+
}
|
|
455
|
+
}
|
|
456
|
+
else { throw new Error('missing procedure/function name.'); }
|
|
457
|
+
|
|
458
|
+
if (dbOpe.command.params) addParams(dbOpe.command.params, sqlRequest);
|
|
459
|
+
|
|
460
|
+
result += ';'
|
|
461
|
+
|
|
462
|
+
return result;
|
|
463
|
+
}
|
|
464
|
+
|
|
465
|
+
// Parse begin operation object to sql string
|
|
466
|
+
function beginToSql(dbOpe, sqlRequest) {
|
|
467
|
+
return "BEGIN TRANSACTION;";
|
|
468
|
+
}
|
|
469
|
+
|
|
470
|
+
// Parse commit operation object to sql string
|
|
471
|
+
function commitToSql(dbOpe, sqlRequest) {
|
|
472
|
+
return "IF @@TRANCOUNT > 0 COMMIT TRANSACTION;";
|
|
473
|
+
}
|
|
474
|
+
|
|
475
|
+
// Add input parameters to pool.request
|
|
476
|
+
function addParams(params, sqlRequest) {
|
|
477
|
+
if (params) {
|
|
478
|
+
for (const [key, value] of Object.entries(params)) {
|
|
479
|
+
sqlRequest.input(key, value)
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
return;
|
|
483
|
+
}
|