@nattyjs/orm 0.0.1-beta.4 → 0.0.1-beta.40
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/index.cjs +382 -31
- package/dist/index.d.ts +26 -1
- package/dist/index.mjs +380 -32
- package/package.json +6 -5
package/dist/index.cjs
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
const mssql = require('mssql');
|
|
4
|
+
const pg = require('pg');
|
|
4
5
|
const common = require('@nattyjs/common');
|
|
5
6
|
const core = require('@nattyjs/core');
|
|
6
7
|
|
|
@@ -17,6 +18,7 @@ function _interopNamespaceCompat(e) {
|
|
|
17
18
|
}
|
|
18
19
|
|
|
19
20
|
const mssql__namespace = /*#__PURE__*/_interopNamespaceCompat(mssql);
|
|
21
|
+
const pg__namespace = /*#__PURE__*/_interopNamespaceCompat(pg);
|
|
20
22
|
|
|
21
23
|
var EntityState = /* @__PURE__ */ ((EntityState2) => {
|
|
22
24
|
EntityState2[EntityState2["added"] = 0] = "added";
|
|
@@ -58,6 +60,12 @@ var QueryAction = /* @__PURE__ */ ((QueryAction2) => {
|
|
|
58
60
|
return QueryAction2;
|
|
59
61
|
})(QueryAction || {});
|
|
60
62
|
|
|
63
|
+
var DatabaseServerTechnology = /* @__PURE__ */ ((DatabaseServerTechnology2) => {
|
|
64
|
+
DatabaseServerTechnology2[DatabaseServerTechnology2["MSSQL"] = 0] = "MSSQL";
|
|
65
|
+
DatabaseServerTechnology2[DatabaseServerTechnology2["PGSQL"] = 1] = "PGSQL";
|
|
66
|
+
return DatabaseServerTechnology2;
|
|
67
|
+
})(DatabaseServerTechnology || {});
|
|
68
|
+
|
|
61
69
|
function getComparisonOperator(operator) {
|
|
62
70
|
let operatorText = "";
|
|
63
71
|
switch (operator) {
|
|
@@ -87,23 +95,27 @@ function getLogicalOperator(operator) {
|
|
|
87
95
|
function getDeleteQueryText(config) {
|
|
88
96
|
const tableName = config.tableName;
|
|
89
97
|
const params = new Array();
|
|
90
|
-
const whereClause = getWhereClause$1(config.whereClause, params);
|
|
98
|
+
const whereClause = getWhereClause$1(config.whereClause, params, config.databaseServerTechnology);
|
|
91
99
|
return {
|
|
92
100
|
query: `delete from ${tableName} where ${whereClause}`,
|
|
93
101
|
parameters: params
|
|
94
102
|
};
|
|
95
103
|
}
|
|
96
|
-
function getWhereClause$1(whereClause, params) {
|
|
104
|
+
function getWhereClause$1(whereClause, params, dbTechnology) {
|
|
105
|
+
const isMsSql = dbTechnology == DatabaseServerTechnology.MSSQL;
|
|
106
|
+
let paramCharacter = isMsSql ? "@" : "$";
|
|
97
107
|
let sqlQuery = "";
|
|
98
108
|
const paramKeys = {};
|
|
99
109
|
let increment = 1;
|
|
110
|
+
let index = 1;
|
|
100
111
|
for (var i = 0; i < whereClause.length; i++) {
|
|
101
112
|
const expression = whereClause[i];
|
|
102
113
|
let paramKey = expression[0];
|
|
103
114
|
if (paramKeys[paramKey])
|
|
104
115
|
paramKey = `${paramKey}${increment}`;
|
|
105
116
|
paramKeys[paramKey] = paramKey;
|
|
106
|
-
sqlQuery += `${expression[0]} ${getComparisonOperator(expression[1])}
|
|
117
|
+
sqlQuery += `${expression[0]} ${getComparisonOperator(expression[1])} ${paramCharacter}${isMsSql ? paramKey : index} `;
|
|
118
|
+
index++;
|
|
107
119
|
params.push({
|
|
108
120
|
name: paramKey,
|
|
109
121
|
value: expression[2]
|
|
@@ -126,16 +138,28 @@ class Utils {
|
|
|
126
138
|
}
|
|
127
139
|
|
|
128
140
|
function getInsertQueryText(config) {
|
|
141
|
+
const isMsSql = DatabaseServerTechnology.MSSQL == config.databaseServerTechnology;
|
|
142
|
+
const isPgSql = DatabaseServerTechnology.PGSQL == config.databaseServerTechnology;
|
|
129
143
|
const tableName = config.tableName;
|
|
130
144
|
const queryInfo = getColumnNameAndParams$1(config);
|
|
131
145
|
const columnNames = queryInfo.columnNames.join(",");
|
|
132
|
-
const parameters = queryInfo.columnNames.map((name) =>
|
|
146
|
+
const parameters = queryInfo.columnNames.map((name, index) => {
|
|
147
|
+
if (isMsSql)
|
|
148
|
+
return `@${name}`;
|
|
149
|
+
else if (isPgSql)
|
|
150
|
+
return `$${index + 1}`;
|
|
151
|
+
}).join(",");
|
|
133
152
|
const primaryKey = config.primaryKeys[0];
|
|
134
153
|
let output = "";
|
|
135
|
-
|
|
136
|
-
|
|
154
|
+
let returningOutput = "";
|
|
155
|
+
if (primaryKey) {
|
|
156
|
+
if (DatabaseServerTechnology.MSSQL == config.databaseServerTechnology)
|
|
157
|
+
output = `OUTPUT INSERTED.${primaryKey}`;
|
|
158
|
+
else if (DatabaseServerTechnology.PGSQL == config.databaseServerTechnology)
|
|
159
|
+
returningOutput = `RETURNING ${primaryKey}`;
|
|
160
|
+
}
|
|
137
161
|
return {
|
|
138
|
-
query: `insert into ${tableName} (${columnNames}) ${output} values (${parameters})`,
|
|
162
|
+
query: `insert into ${tableName} (${columnNames}) ${output} values (${parameters}) ${returningOutput}`,
|
|
139
163
|
parameters: queryInfo.params,
|
|
140
164
|
relationProps: queryInfo.relationProps
|
|
141
165
|
};
|
|
@@ -167,23 +191,27 @@ function getSelectQueryText(config) {
|
|
|
167
191
|
const tableName = config.tableName;
|
|
168
192
|
const columnNames = config.columns.length == 0 ? "*" : config.columns.join(",");
|
|
169
193
|
const params = new Array();
|
|
170
|
-
const whereClause = getWhereClause(config.whereClause, params);
|
|
194
|
+
const whereClause = getWhereClause(config.whereClause, params, config.databaseServerTechnology);
|
|
171
195
|
return {
|
|
172
196
|
query: `select ${columnNames} from ${tableName} ${whereClause ? `where ${whereClause}` : ""}`,
|
|
173
197
|
parameters: params
|
|
174
198
|
};
|
|
175
199
|
}
|
|
176
|
-
function getWhereClause(whereClause, params) {
|
|
200
|
+
function getWhereClause(whereClause, params, dbTechnology) {
|
|
201
|
+
const isMsSql = dbTechnology == DatabaseServerTechnology.MSSQL;
|
|
202
|
+
let paramCharacter = isMsSql ? "@" : "$";
|
|
177
203
|
let sqlQuery = "";
|
|
178
204
|
const paramKeys = {};
|
|
179
205
|
let increment = 1;
|
|
206
|
+
let index = 1;
|
|
180
207
|
for (var i = 0; i < whereClause.length; i++) {
|
|
181
208
|
const expression = whereClause[i];
|
|
182
209
|
let paramKey = expression[0];
|
|
183
210
|
if (paramKeys[paramKey])
|
|
184
211
|
paramKey = `${paramKey}${increment}`;
|
|
185
212
|
paramKeys[paramKey] = paramKey;
|
|
186
|
-
sqlQuery += `${expression[0]} ${getComparisonOperator(expression[1])}
|
|
213
|
+
sqlQuery += `${expression[0]} ${getComparisonOperator(expression[1])} ${paramCharacter}${isMsSql ? paramKey : index} `;
|
|
214
|
+
index++;
|
|
187
215
|
params.push({
|
|
188
216
|
name: paramKey,
|
|
189
217
|
value: expression[2]
|
|
@@ -206,16 +234,21 @@ function getUpdateQueryText(config) {
|
|
|
206
234
|
};
|
|
207
235
|
}
|
|
208
236
|
function getColumnNameAndParams(config) {
|
|
237
|
+
const isMsSql = config.databaseServerTechnology == DatabaseServerTechnology.MSSQL;
|
|
209
238
|
const sets = [];
|
|
210
239
|
const whereClause = [];
|
|
211
240
|
const params = new Array();
|
|
212
241
|
if (config.entity) {
|
|
242
|
+
let index = 1;
|
|
243
|
+
let parameterCharacter = isMsSql ? "@" : "$";
|
|
213
244
|
for (const [key, value] of Object.entries(config.entity)) {
|
|
245
|
+
const paramProp = isMsSql ? key : index;
|
|
214
246
|
if (!(Utils.isObject(value) || Utils.isArray(value))) {
|
|
215
247
|
if (config.primaryKeys.indexOf(key) === -1)
|
|
216
|
-
sets.push(`${key}
|
|
248
|
+
sets.push(`${key}=${parameterCharacter}${paramProp}`);
|
|
217
249
|
else
|
|
218
|
-
whereClause.push(`${key}
|
|
250
|
+
whereClause.push(`${key}=${parameterCharacter}${paramProp}`);
|
|
251
|
+
index++;
|
|
219
252
|
params.push({
|
|
220
253
|
name: `${key}`,
|
|
221
254
|
value
|
|
@@ -249,6 +282,281 @@ class DbConnection {
|
|
|
249
282
|
constructor(config) {
|
|
250
283
|
this.config = config;
|
|
251
284
|
this.mssql = mssql__namespace;
|
|
285
|
+
this.pg = pg__namespace;
|
|
286
|
+
}
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
const connectionCacheContainer = new class {
|
|
290
|
+
constructor() {
|
|
291
|
+
this.connectionPoolState = {};
|
|
292
|
+
}
|
|
293
|
+
getCacheKey(config) {
|
|
294
|
+
return `${config.server}-${config.database}`;
|
|
295
|
+
}
|
|
296
|
+
async getConnectionPool(mssql, config) {
|
|
297
|
+
return await new Promise((resolve, error) => {
|
|
298
|
+
const cacheKey = this.getCacheKey(config);
|
|
299
|
+
if (this.connectionPoolState[cacheKey])
|
|
300
|
+
return resolve(this.connectionPoolState[cacheKey]);
|
|
301
|
+
const pool = new mssql.ConnectionPool(config);
|
|
302
|
+
const errorHandler = (error2) => {
|
|
303
|
+
};
|
|
304
|
+
pool.on("error", errorHandler);
|
|
305
|
+
const connection = pool.connect((err) => {
|
|
306
|
+
if (err)
|
|
307
|
+
return error(err);
|
|
308
|
+
this.connectionPoolState[cacheKey] = connection;
|
|
309
|
+
resolve(connection);
|
|
310
|
+
});
|
|
311
|
+
});
|
|
312
|
+
}
|
|
313
|
+
async getPgSqlConnectionPool(sql, config) {
|
|
314
|
+
return await new Promise((resolve, error) => {
|
|
315
|
+
const cacheKey = this.getCacheKey(config);
|
|
316
|
+
if (this.connectionPoolState[cacheKey])
|
|
317
|
+
return resolve(this.connectionPoolState[cacheKey]);
|
|
318
|
+
const pool = new sql.Pool(config);
|
|
319
|
+
this.connectionPoolState[cacheKey] = pool;
|
|
320
|
+
resolve(pool);
|
|
321
|
+
});
|
|
322
|
+
}
|
|
323
|
+
}();
|
|
324
|
+
|
|
325
|
+
class PgSqlDbTransaction {
|
|
326
|
+
constructor() {
|
|
327
|
+
this.transactionConnection = null;
|
|
328
|
+
this.isSelfTransaction = true;
|
|
329
|
+
this.dbContexts = null;
|
|
330
|
+
}
|
|
331
|
+
useTransaction(client) {
|
|
332
|
+
this.isSelfTransaction = false;
|
|
333
|
+
this.transactionConnection = client;
|
|
334
|
+
}
|
|
335
|
+
async begin(pool, isolationLevel, dbContexts) {
|
|
336
|
+
if (!this.transactionConnection) {
|
|
337
|
+
this.transactionConnection = await pool.connect();
|
|
338
|
+
this.isSelfTransaction = true;
|
|
339
|
+
const isoSql = this.convertToIsolationLevel(isolationLevel);
|
|
340
|
+
await this.transactionConnection.query(`BEGIN ${isoSql}`);
|
|
341
|
+
}
|
|
342
|
+
this.assignTransaction(dbContexts);
|
|
343
|
+
}
|
|
344
|
+
assignTransaction(dbContexts) {
|
|
345
|
+
if (dbContexts)
|
|
346
|
+
for (const dbContext of dbContexts) {
|
|
347
|
+
dbContext.connection.useTransaction(this.transactionConnection);
|
|
348
|
+
}
|
|
349
|
+
this.dbContexts = dbContexts;
|
|
350
|
+
}
|
|
351
|
+
async commit() {
|
|
352
|
+
if (this.transactionConnection && this.isSelfTransaction) {
|
|
353
|
+
try {
|
|
354
|
+
await this.transactionConnection.query("COMMIT");
|
|
355
|
+
} catch (err) {
|
|
356
|
+
throw err;
|
|
357
|
+
} finally {
|
|
358
|
+
this.transactionRelease();
|
|
359
|
+
this.transactionConnection.release();
|
|
360
|
+
this.transactionConnection = null;
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
async rollback() {
|
|
365
|
+
if (this.transactionConnection && this.isSelfTransaction) {
|
|
366
|
+
try {
|
|
367
|
+
await this.transactionConnection.query("ROLLBACK");
|
|
368
|
+
} catch (err) {
|
|
369
|
+
throw err;
|
|
370
|
+
} finally {
|
|
371
|
+
this.transactionRelease();
|
|
372
|
+
this.transactionConnection.release();
|
|
373
|
+
this.transactionConnection = null;
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
}
|
|
377
|
+
transactionRelease() {
|
|
378
|
+
if (this.dbContexts) {
|
|
379
|
+
for (const dbContext of this.dbContexts) {
|
|
380
|
+
dbContext.connection.releaseTransaction();
|
|
381
|
+
}
|
|
382
|
+
this.dbContexts = null;
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
releaseTransaction() {
|
|
386
|
+
this.transactionConnection = null;
|
|
387
|
+
this.isSelfTransaction = true;
|
|
388
|
+
}
|
|
389
|
+
convertToIsolationLevel(isolation) {
|
|
390
|
+
switch (isolation?.toUpperCase()) {
|
|
391
|
+
case "READ UNCOMMITTED":
|
|
392
|
+
return "ISOLATION LEVEL READ UNCOMMITTED";
|
|
393
|
+
case "REPEATABLE READ":
|
|
394
|
+
return "ISOLATION LEVEL REPEATABLE READ";
|
|
395
|
+
case "SERIALIZABLE":
|
|
396
|
+
return "ISOLATION LEVEL SERIALIZABLE";
|
|
397
|
+
case "READ COMMITTED":
|
|
398
|
+
default:
|
|
399
|
+
return "ISOLATION LEVEL READ COMMITTED";
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
class PgSqlConnection extends DbConnection {
|
|
405
|
+
constructor(config) {
|
|
406
|
+
super(config);
|
|
407
|
+
this.baseTransaction = new PgSqlDbTransaction();
|
|
408
|
+
}
|
|
409
|
+
get transaction() {
|
|
410
|
+
return this.baseTransaction;
|
|
411
|
+
}
|
|
412
|
+
useTransaction(connection) {
|
|
413
|
+
this.baseTransaction.useTransaction(connection);
|
|
414
|
+
}
|
|
415
|
+
useConnection(connection) {
|
|
416
|
+
this.connection = connection;
|
|
417
|
+
}
|
|
418
|
+
async executeQuery(query) {
|
|
419
|
+
try {
|
|
420
|
+
query.databaseServerTechnology = DatabaseServerTechnology.PGSQL;
|
|
421
|
+
const sqlQueryText = getSqlTextAndParams(query);
|
|
422
|
+
const result = await this.query(sqlQueryText);
|
|
423
|
+
let records = new Array();
|
|
424
|
+
const outputInfo = this.getOutput(result, query);
|
|
425
|
+
await this.runNestedObjectQueries(outputInfo, sqlQueryText.relationProps, query);
|
|
426
|
+
if (result["rows"]) {
|
|
427
|
+
records = result.rows;
|
|
428
|
+
}
|
|
429
|
+
return records;
|
|
430
|
+
} catch (ex) {
|
|
431
|
+
throw ex;
|
|
432
|
+
}
|
|
433
|
+
}
|
|
434
|
+
async runNestedObjectQueries(outputInfo, relationProps, config) {
|
|
435
|
+
if (outputInfo) {
|
|
436
|
+
switch (config.queryAction) {
|
|
437
|
+
case QueryAction.add:
|
|
438
|
+
for (const propName of relationProps.keys()) {
|
|
439
|
+
const entries = relationProps.get(propName);
|
|
440
|
+
const queryConfig = config.propsDbConfig.get(propName);
|
|
441
|
+
if (Array.isArray(entries) && queryConfig) {
|
|
442
|
+
for (const entity of entries) {
|
|
443
|
+
if (!entity[queryConfig.foreignKey])
|
|
444
|
+
entity[queryConfig.foreignKey] = outputInfo.value;
|
|
445
|
+
await this.runQuery([{ ...queryConfig, entity }], config.queryAction);
|
|
446
|
+
}
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
break;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
}
|
|
453
|
+
async executeFunc(funcName, params) {
|
|
454
|
+
let records = new Array();
|
|
455
|
+
if (common.isObject(params)) {
|
|
456
|
+
const queryInfo = { parameters: [] };
|
|
457
|
+
let query = `select * from ${funcName}(`;
|
|
458
|
+
let index = 1;
|
|
459
|
+
for (const [key, value] of Object.entries(params)) {
|
|
460
|
+
query += index == 1 ? `$${index}` : `,$${index}`;
|
|
461
|
+
index++;
|
|
462
|
+
queryInfo.parameters.push({ name: key, value });
|
|
463
|
+
}
|
|
464
|
+
query += ")";
|
|
465
|
+
queryInfo.query = query;
|
|
466
|
+
const result = await this.query(queryInfo);
|
|
467
|
+
if (result["rows"]) {
|
|
468
|
+
records = result.rows;
|
|
469
|
+
}
|
|
470
|
+
return records;
|
|
471
|
+
}
|
|
472
|
+
return records;
|
|
473
|
+
}
|
|
474
|
+
async executeSp(spName, params) {
|
|
475
|
+
let records = new Array();
|
|
476
|
+
if (common.isObject(params)) {
|
|
477
|
+
const queryInfo = { parameters: [] };
|
|
478
|
+
let query = `CALL ${spName}(`;
|
|
479
|
+
let index = 1;
|
|
480
|
+
for (const [key, value] of Object.entries(params)) {
|
|
481
|
+
query += index == 1 ? `$${index}` : `,$${index}`;
|
|
482
|
+
index++;
|
|
483
|
+
queryInfo.parameters.push({ name: key, value });
|
|
484
|
+
}
|
|
485
|
+
query += ")";
|
|
486
|
+
queryInfo.query = query;
|
|
487
|
+
const result = await this.query(queryInfo);
|
|
488
|
+
if (result["rows"]) {
|
|
489
|
+
records = result.rows;
|
|
490
|
+
}
|
|
491
|
+
return records;
|
|
492
|
+
}
|
|
493
|
+
return records;
|
|
494
|
+
}
|
|
495
|
+
getOutput(result, config) {
|
|
496
|
+
switch (config.queryAction) {
|
|
497
|
+
case QueryAction.add:
|
|
498
|
+
const primaryKey = config.primaryKeys[0];
|
|
499
|
+
const output = result.rows[0][primaryKey];
|
|
500
|
+
if (output)
|
|
501
|
+
config.entity[primaryKey] = output;
|
|
502
|
+
return { key: primaryKey, value: output };
|
|
503
|
+
}
|
|
504
|
+
}
|
|
505
|
+
async addEntries(dbEntities) {
|
|
506
|
+
await this.runQuery(dbEntities, QueryAction.add);
|
|
507
|
+
}
|
|
508
|
+
async updateEntries(dbEntities) {
|
|
509
|
+
await this.runQuery(dbEntities, QueryAction.update);
|
|
510
|
+
}
|
|
511
|
+
async deleteEntries(dbEntities) {
|
|
512
|
+
await this.runQuery(dbEntities, QueryAction.delete);
|
|
513
|
+
}
|
|
514
|
+
async runQuery(dbEntities, queryAction) {
|
|
515
|
+
for (const dbEntity of dbEntities) {
|
|
516
|
+
const executeQuery = {
|
|
517
|
+
...dbEntity,
|
|
518
|
+
queryAction
|
|
519
|
+
};
|
|
520
|
+
await this.executeQuery(executeQuery);
|
|
521
|
+
}
|
|
522
|
+
}
|
|
523
|
+
async query(queryInfo) {
|
|
524
|
+
const pool = await this.getConnectionPool();
|
|
525
|
+
const request = pool;
|
|
526
|
+
const values = queryInfo.parameters.map((t) => t.value);
|
|
527
|
+
const resolveQuery = (resolve, errorResolver) => (error, raw) => {
|
|
528
|
+
if (error)
|
|
529
|
+
errorResolver(error);
|
|
530
|
+
resolve(raw);
|
|
531
|
+
};
|
|
532
|
+
const catchFn = (ex) => {
|
|
533
|
+
throw ex;
|
|
534
|
+
};
|
|
535
|
+
if (queryInfo.query) {
|
|
536
|
+
const raw = await new Promise((resolve, error) => {
|
|
537
|
+
request.query(queryInfo.query, values, resolveQuery(resolve, error));
|
|
538
|
+
}).catch(catchFn);
|
|
539
|
+
return raw;
|
|
540
|
+
}
|
|
541
|
+
}
|
|
542
|
+
async beginTransaction(isolationLevel, dbContexts) {
|
|
543
|
+
const connection = await this.getConnectionPool();
|
|
544
|
+
await this.baseTransaction.begin(connection, isolationLevel, dbContexts);
|
|
545
|
+
}
|
|
546
|
+
async commitTransaction() {
|
|
547
|
+
await this.baseTransaction.commit();
|
|
548
|
+
}
|
|
549
|
+
async rollbackTransaction() {
|
|
550
|
+
await this.baseTransaction.rollback();
|
|
551
|
+
}
|
|
552
|
+
releaseTransaction() {
|
|
553
|
+
this.baseTransaction.releaseTransaction();
|
|
554
|
+
}
|
|
555
|
+
async getConnectionPool() {
|
|
556
|
+
return this.createPool();
|
|
557
|
+
}
|
|
558
|
+
async createPool() {
|
|
559
|
+
return await connectionCacheContainer.getPgSqlConnectionPool(this.pg, this.config);
|
|
252
560
|
}
|
|
253
561
|
}
|
|
254
562
|
|
|
@@ -360,6 +668,7 @@ class SqlConnection extends DbConnection {
|
|
|
360
668
|
}
|
|
361
669
|
async executeQuery(query) {
|
|
362
670
|
try {
|
|
671
|
+
query.databaseServerTechnology = DatabaseServerTechnology.MSSQL;
|
|
363
672
|
const sqlQueryText = getSqlTextAndParams(query);
|
|
364
673
|
const result = await this.query(sqlQueryText);
|
|
365
674
|
let records = new Array();
|
|
@@ -370,6 +679,7 @@ class SqlConnection extends DbConnection {
|
|
|
370
679
|
}
|
|
371
680
|
return records;
|
|
372
681
|
} catch (ex) {
|
|
682
|
+
throw ex;
|
|
373
683
|
}
|
|
374
684
|
}
|
|
375
685
|
async runNestedObjectQueries(outputInfo, relationProps, config) {
|
|
@@ -391,6 +701,27 @@ class SqlConnection extends DbConnection {
|
|
|
391
701
|
}
|
|
392
702
|
}
|
|
393
703
|
}
|
|
704
|
+
async executeFunc(funcName, params) {
|
|
705
|
+
let records = new Array();
|
|
706
|
+
if (common.isObject(params)) {
|
|
707
|
+
const queryInfo = { parameters: [] };
|
|
708
|
+
let query = `select * from ${funcName}(`;
|
|
709
|
+
let index = 1;
|
|
710
|
+
for (const [key, value] of Object.entries(params)) {
|
|
711
|
+
query += index == 1 ? `@${key}` : `,@${key}`;
|
|
712
|
+
index++;
|
|
713
|
+
queryInfo.parameters.push({ name: key, value });
|
|
714
|
+
}
|
|
715
|
+
query += ")";
|
|
716
|
+
queryInfo.query = query;
|
|
717
|
+
const result = await this.query(queryInfo);
|
|
718
|
+
if (result["recordset"]) {
|
|
719
|
+
records = result.recordset;
|
|
720
|
+
}
|
|
721
|
+
return records;
|
|
722
|
+
}
|
|
723
|
+
return records;
|
|
724
|
+
}
|
|
394
725
|
async executeSp(spName, params) {
|
|
395
726
|
let records = new Array();
|
|
396
727
|
if (common.isObject(params)) {
|
|
@@ -443,20 +774,23 @@ class SqlConnection extends DbConnection {
|
|
|
443
774
|
else
|
|
444
775
|
request.input(param.name, param.value);
|
|
445
776
|
}
|
|
446
|
-
const resolveQuery = (resolve) => (error, raw) => {
|
|
777
|
+
const resolveQuery = (resolve, errorResolver) => (error, raw) => {
|
|
447
778
|
if (error)
|
|
448
|
-
|
|
779
|
+
errorResolver(error);
|
|
449
780
|
resolve(raw);
|
|
450
781
|
};
|
|
782
|
+
const catchFn = (ex) => {
|
|
783
|
+
throw ex;
|
|
784
|
+
};
|
|
451
785
|
if (queryInfo.query) {
|
|
452
786
|
const raw = await new Promise((resolve, error) => {
|
|
453
|
-
request.query(queryInfo.query, resolveQuery(resolve));
|
|
454
|
-
});
|
|
787
|
+
request.query(queryInfo.query, resolveQuery(resolve, error));
|
|
788
|
+
}).catch(catchFn);
|
|
455
789
|
return raw;
|
|
456
790
|
} else if (queryInfo.sp) {
|
|
457
791
|
const raw = await new Promise((resolve, error) => {
|
|
458
|
-
request.execute(queryInfo.sp, resolveQuery(resolve));
|
|
459
|
-
});
|
|
792
|
+
request.execute(queryInfo.sp, resolveQuery(resolve, error));
|
|
793
|
+
}).catch(catchFn);
|
|
460
794
|
return raw;
|
|
461
795
|
}
|
|
462
796
|
}
|
|
@@ -477,19 +811,7 @@ class SqlConnection extends DbConnection {
|
|
|
477
811
|
return this.createPool();
|
|
478
812
|
}
|
|
479
813
|
async createPool() {
|
|
480
|
-
return await
|
|
481
|
-
if (this.baseTransaction.transactionConnection)
|
|
482
|
-
return resolve(this.baseTransaction.transactionConnection);
|
|
483
|
-
const pool = new this.mssql.ConnectionPool(this.config);
|
|
484
|
-
const errorHandler = (error2) => {
|
|
485
|
-
};
|
|
486
|
-
pool.on("error", errorHandler);
|
|
487
|
-
const connection = pool.connect((err) => {
|
|
488
|
-
if (err)
|
|
489
|
-
return error(err);
|
|
490
|
-
resolve(connection);
|
|
491
|
-
});
|
|
492
|
-
});
|
|
814
|
+
return await connectionCacheContainer.getConnectionPool(this.mssql, this.config);
|
|
493
815
|
}
|
|
494
816
|
}
|
|
495
817
|
|
|
@@ -497,6 +819,9 @@ class DbConnectionContext {
|
|
|
497
819
|
useSqlServer(options) {
|
|
498
820
|
this.connection = new SqlConnection(options);
|
|
499
821
|
}
|
|
822
|
+
usePgSqlServer(options) {
|
|
823
|
+
this.connection = new PgSqlConnection(options);
|
|
824
|
+
}
|
|
500
825
|
}
|
|
501
826
|
|
|
502
827
|
class DbSet {
|
|
@@ -603,6 +928,25 @@ class StoreProc {
|
|
|
603
928
|
}
|
|
604
929
|
}
|
|
605
930
|
|
|
931
|
+
class DbFunc {
|
|
932
|
+
constructor(funcName, type, queryConnection) {
|
|
933
|
+
this.funcName = funcName;
|
|
934
|
+
this.type = type;
|
|
935
|
+
this.queryConnection = queryConnection;
|
|
936
|
+
}
|
|
937
|
+
async execute(params) {
|
|
938
|
+
const items = await this.queryConnection.executeFunc(this.funcName, params);
|
|
939
|
+
return new common.List(items, this.type, this.properties);
|
|
940
|
+
}
|
|
941
|
+
get properties() {
|
|
942
|
+
const props = core.entityContainer.getProperties(this.type.name);
|
|
943
|
+
const jProps = {};
|
|
944
|
+
if (props)
|
|
945
|
+
props.forEach((property) => jProps[property.name.toLowerCase()] = property.name);
|
|
946
|
+
return jProps;
|
|
947
|
+
}
|
|
948
|
+
}
|
|
949
|
+
|
|
606
950
|
class DbContext {
|
|
607
951
|
get connection() {
|
|
608
952
|
return this.dbConnectionInfo.connection;
|
|
@@ -630,6 +974,11 @@ class DbContext {
|
|
|
630
974
|
for (const [key, value] of Object.entries(sps))
|
|
631
975
|
this[key] = new StoreProc(value.spName, value.model(), this.queryConnection);
|
|
632
976
|
}
|
|
977
|
+
onDbFuncRegistering(funcs) {
|
|
978
|
+
if (funcs)
|
|
979
|
+
for (const [key, value] of Object.entries(funcs))
|
|
980
|
+
this[key] = new DbFunc(value.funcName, value.model(), this.queryConnection);
|
|
981
|
+
}
|
|
633
982
|
async saveChanges() {
|
|
634
983
|
return new Promise(async (resolve, error) => {
|
|
635
984
|
try {
|
|
@@ -649,6 +998,8 @@ class DbContext {
|
|
|
649
998
|
}
|
|
650
999
|
}
|
|
651
1000
|
|
|
1001
|
+
exports.DbConnectionContext = DbConnectionContext;
|
|
652
1002
|
exports.DbContext = DbContext;
|
|
1003
|
+
exports.DbFunc = DbFunc;
|
|
653
1004
|
exports.DbSet = DbSet;
|
|
654
1005
|
exports.StoreProc = StoreProc;
|
package/dist/index.d.ts
CHANGED
|
@@ -46,6 +46,7 @@ declare class ChangeTracker {
|
|
|
46
46
|
declare class DbConnectionContext {
|
|
47
47
|
connection: any;
|
|
48
48
|
useSqlServer(options: any): void;
|
|
49
|
+
usePgSqlServer(options: any): void;
|
|
49
50
|
}
|
|
50
51
|
|
|
51
52
|
declare abstract class DbContext implements IDbContext {
|
|
@@ -64,12 +65,23 @@ declare abstract class DbContext implements IDbContext {
|
|
|
64
65
|
spName: string;
|
|
65
66
|
};
|
|
66
67
|
}): void;
|
|
68
|
+
protected onDbFuncRegistering(funcs?: {
|
|
69
|
+
[key: string]: {
|
|
70
|
+
model: () => ClassType<any>;
|
|
71
|
+
funcName: string;
|
|
72
|
+
};
|
|
73
|
+
}): void;
|
|
67
74
|
protected abstract onConfiguring(connectionContext: DbConnectionContext): void;
|
|
68
75
|
saveChanges(): Promise<unknown>;
|
|
69
76
|
}
|
|
70
77
|
|
|
71
78
|
type FilterExpression<T> = (t: T) => boolean;
|
|
72
79
|
|
|
80
|
+
declare enum DatabaseServerTechnology {
|
|
81
|
+
MSSQL = 0,
|
|
82
|
+
PGSQL = 1
|
|
83
|
+
}
|
|
84
|
+
|
|
73
85
|
declare enum QueryAction {
|
|
74
86
|
select = 0,
|
|
75
87
|
add = 1,
|
|
@@ -81,6 +93,7 @@ interface ExecuteQueryConfig extends DbEntityInfo {
|
|
|
81
93
|
columns?: string[];
|
|
82
94
|
whereClause?: any;
|
|
83
95
|
queryAction?: QueryAction;
|
|
96
|
+
databaseServerTechnology?: DatabaseServerTechnology;
|
|
84
97
|
}
|
|
85
98
|
|
|
86
99
|
interface DataQueryConnection extends IDbConnection {
|
|
@@ -88,6 +101,9 @@ interface DataQueryConnection extends IDbConnection {
|
|
|
88
101
|
executeSp(spName: string, params: {
|
|
89
102
|
[key: string]: any;
|
|
90
103
|
}): any;
|
|
104
|
+
executeFunc(funcName: string, params: {
|
|
105
|
+
[key: string]: any;
|
|
106
|
+
}): any;
|
|
91
107
|
}
|
|
92
108
|
|
|
93
109
|
declare class DbSet<T> {
|
|
@@ -119,4 +135,13 @@ declare class StoreProc<SpName, Entity, SpParamterModel> {
|
|
|
119
135
|
private get properties();
|
|
120
136
|
}
|
|
121
137
|
|
|
122
|
-
|
|
138
|
+
declare class DbFunc<FuncName, Entity, FuncParamterModel> {
|
|
139
|
+
private funcName;
|
|
140
|
+
private type;
|
|
141
|
+
private queryConnection;
|
|
142
|
+
constructor(funcName: string, type: ClassType<Entity>, queryConnection: DataQueryConnection);
|
|
143
|
+
execute(params: FuncParamterModel): Promise<List<Entity>>;
|
|
144
|
+
private get properties();
|
|
145
|
+
}
|
|
146
|
+
|
|
147
|
+
export { DbConnectionContext, DbContext, DbFunc, DbSet, StoreProc };
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import * as mssql from 'mssql';
|
|
2
|
+
import * as pg from 'pg';
|
|
2
3
|
import { isObject, List } from '@nattyjs/common';
|
|
3
4
|
import { entityContainer } from '@nattyjs/core';
|
|
4
5
|
|
|
@@ -42,6 +43,12 @@ var QueryAction = /* @__PURE__ */ ((QueryAction2) => {
|
|
|
42
43
|
return QueryAction2;
|
|
43
44
|
})(QueryAction || {});
|
|
44
45
|
|
|
46
|
+
var DatabaseServerTechnology = /* @__PURE__ */ ((DatabaseServerTechnology2) => {
|
|
47
|
+
DatabaseServerTechnology2[DatabaseServerTechnology2["MSSQL"] = 0] = "MSSQL";
|
|
48
|
+
DatabaseServerTechnology2[DatabaseServerTechnology2["PGSQL"] = 1] = "PGSQL";
|
|
49
|
+
return DatabaseServerTechnology2;
|
|
50
|
+
})(DatabaseServerTechnology || {});
|
|
51
|
+
|
|
45
52
|
function getComparisonOperator(operator) {
|
|
46
53
|
let operatorText = "";
|
|
47
54
|
switch (operator) {
|
|
@@ -71,23 +78,27 @@ function getLogicalOperator(operator) {
|
|
|
71
78
|
function getDeleteQueryText(config) {
|
|
72
79
|
const tableName = config.tableName;
|
|
73
80
|
const params = new Array();
|
|
74
|
-
const whereClause = getWhereClause$1(config.whereClause, params);
|
|
81
|
+
const whereClause = getWhereClause$1(config.whereClause, params, config.databaseServerTechnology);
|
|
75
82
|
return {
|
|
76
83
|
query: `delete from ${tableName} where ${whereClause}`,
|
|
77
84
|
parameters: params
|
|
78
85
|
};
|
|
79
86
|
}
|
|
80
|
-
function getWhereClause$1(whereClause, params) {
|
|
87
|
+
function getWhereClause$1(whereClause, params, dbTechnology) {
|
|
88
|
+
const isMsSql = dbTechnology == DatabaseServerTechnology.MSSQL;
|
|
89
|
+
let paramCharacter = isMsSql ? "@" : "$";
|
|
81
90
|
let sqlQuery = "";
|
|
82
91
|
const paramKeys = {};
|
|
83
92
|
let increment = 1;
|
|
93
|
+
let index = 1;
|
|
84
94
|
for (var i = 0; i < whereClause.length; i++) {
|
|
85
95
|
const expression = whereClause[i];
|
|
86
96
|
let paramKey = expression[0];
|
|
87
97
|
if (paramKeys[paramKey])
|
|
88
98
|
paramKey = `${paramKey}${increment}`;
|
|
89
99
|
paramKeys[paramKey] = paramKey;
|
|
90
|
-
sqlQuery += `${expression[0]} ${getComparisonOperator(expression[1])}
|
|
100
|
+
sqlQuery += `${expression[0]} ${getComparisonOperator(expression[1])} ${paramCharacter}${isMsSql ? paramKey : index} `;
|
|
101
|
+
index++;
|
|
91
102
|
params.push({
|
|
92
103
|
name: paramKey,
|
|
93
104
|
value: expression[2]
|
|
@@ -110,16 +121,28 @@ class Utils {
|
|
|
110
121
|
}
|
|
111
122
|
|
|
112
123
|
function getInsertQueryText(config) {
|
|
124
|
+
const isMsSql = DatabaseServerTechnology.MSSQL == config.databaseServerTechnology;
|
|
125
|
+
const isPgSql = DatabaseServerTechnology.PGSQL == config.databaseServerTechnology;
|
|
113
126
|
const tableName = config.tableName;
|
|
114
127
|
const queryInfo = getColumnNameAndParams$1(config);
|
|
115
128
|
const columnNames = queryInfo.columnNames.join(",");
|
|
116
|
-
const parameters = queryInfo.columnNames.map((name) =>
|
|
129
|
+
const parameters = queryInfo.columnNames.map((name, index) => {
|
|
130
|
+
if (isMsSql)
|
|
131
|
+
return `@${name}`;
|
|
132
|
+
else if (isPgSql)
|
|
133
|
+
return `$${index + 1}`;
|
|
134
|
+
}).join(",");
|
|
117
135
|
const primaryKey = config.primaryKeys[0];
|
|
118
136
|
let output = "";
|
|
119
|
-
|
|
120
|
-
|
|
137
|
+
let returningOutput = "";
|
|
138
|
+
if (primaryKey) {
|
|
139
|
+
if (DatabaseServerTechnology.MSSQL == config.databaseServerTechnology)
|
|
140
|
+
output = `OUTPUT INSERTED.${primaryKey}`;
|
|
141
|
+
else if (DatabaseServerTechnology.PGSQL == config.databaseServerTechnology)
|
|
142
|
+
returningOutput = `RETURNING ${primaryKey}`;
|
|
143
|
+
}
|
|
121
144
|
return {
|
|
122
|
-
query: `insert into ${tableName} (${columnNames}) ${output} values (${parameters})`,
|
|
145
|
+
query: `insert into ${tableName} (${columnNames}) ${output} values (${parameters}) ${returningOutput}`,
|
|
123
146
|
parameters: queryInfo.params,
|
|
124
147
|
relationProps: queryInfo.relationProps
|
|
125
148
|
};
|
|
@@ -151,23 +174,27 @@ function getSelectQueryText(config) {
|
|
|
151
174
|
const tableName = config.tableName;
|
|
152
175
|
const columnNames = config.columns.length == 0 ? "*" : config.columns.join(",");
|
|
153
176
|
const params = new Array();
|
|
154
|
-
const whereClause = getWhereClause(config.whereClause, params);
|
|
177
|
+
const whereClause = getWhereClause(config.whereClause, params, config.databaseServerTechnology);
|
|
155
178
|
return {
|
|
156
179
|
query: `select ${columnNames} from ${tableName} ${whereClause ? `where ${whereClause}` : ""}`,
|
|
157
180
|
parameters: params
|
|
158
181
|
};
|
|
159
182
|
}
|
|
160
|
-
function getWhereClause(whereClause, params) {
|
|
183
|
+
function getWhereClause(whereClause, params, dbTechnology) {
|
|
184
|
+
const isMsSql = dbTechnology == DatabaseServerTechnology.MSSQL;
|
|
185
|
+
let paramCharacter = isMsSql ? "@" : "$";
|
|
161
186
|
let sqlQuery = "";
|
|
162
187
|
const paramKeys = {};
|
|
163
188
|
let increment = 1;
|
|
189
|
+
let index = 1;
|
|
164
190
|
for (var i = 0; i < whereClause.length; i++) {
|
|
165
191
|
const expression = whereClause[i];
|
|
166
192
|
let paramKey = expression[0];
|
|
167
193
|
if (paramKeys[paramKey])
|
|
168
194
|
paramKey = `${paramKey}${increment}`;
|
|
169
195
|
paramKeys[paramKey] = paramKey;
|
|
170
|
-
sqlQuery += `${expression[0]} ${getComparisonOperator(expression[1])}
|
|
196
|
+
sqlQuery += `${expression[0]} ${getComparisonOperator(expression[1])} ${paramCharacter}${isMsSql ? paramKey : index} `;
|
|
197
|
+
index++;
|
|
171
198
|
params.push({
|
|
172
199
|
name: paramKey,
|
|
173
200
|
value: expression[2]
|
|
@@ -190,16 +217,21 @@ function getUpdateQueryText(config) {
|
|
|
190
217
|
};
|
|
191
218
|
}
|
|
192
219
|
function getColumnNameAndParams(config) {
|
|
220
|
+
const isMsSql = config.databaseServerTechnology == DatabaseServerTechnology.MSSQL;
|
|
193
221
|
const sets = [];
|
|
194
222
|
const whereClause = [];
|
|
195
223
|
const params = new Array();
|
|
196
224
|
if (config.entity) {
|
|
225
|
+
let index = 1;
|
|
226
|
+
let parameterCharacter = isMsSql ? "@" : "$";
|
|
197
227
|
for (const [key, value] of Object.entries(config.entity)) {
|
|
228
|
+
const paramProp = isMsSql ? key : index;
|
|
198
229
|
if (!(Utils.isObject(value) || Utils.isArray(value))) {
|
|
199
230
|
if (config.primaryKeys.indexOf(key) === -1)
|
|
200
|
-
sets.push(`${key}
|
|
231
|
+
sets.push(`${key}=${parameterCharacter}${paramProp}`);
|
|
201
232
|
else
|
|
202
|
-
whereClause.push(`${key}
|
|
233
|
+
whereClause.push(`${key}=${parameterCharacter}${paramProp}`);
|
|
234
|
+
index++;
|
|
203
235
|
params.push({
|
|
204
236
|
name: `${key}`,
|
|
205
237
|
value
|
|
@@ -233,6 +265,281 @@ class DbConnection {
|
|
|
233
265
|
constructor(config) {
|
|
234
266
|
this.config = config;
|
|
235
267
|
this.mssql = mssql;
|
|
268
|
+
this.pg = pg;
|
|
269
|
+
}
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
const connectionCacheContainer = new class {
|
|
273
|
+
constructor() {
|
|
274
|
+
this.connectionPoolState = {};
|
|
275
|
+
}
|
|
276
|
+
getCacheKey(config) {
|
|
277
|
+
return `${config.server}-${config.database}`;
|
|
278
|
+
}
|
|
279
|
+
async getConnectionPool(mssql, config) {
|
|
280
|
+
return await new Promise((resolve, error) => {
|
|
281
|
+
const cacheKey = this.getCacheKey(config);
|
|
282
|
+
if (this.connectionPoolState[cacheKey])
|
|
283
|
+
return resolve(this.connectionPoolState[cacheKey]);
|
|
284
|
+
const pool = new mssql.ConnectionPool(config);
|
|
285
|
+
const errorHandler = (error2) => {
|
|
286
|
+
};
|
|
287
|
+
pool.on("error", errorHandler);
|
|
288
|
+
const connection = pool.connect((err) => {
|
|
289
|
+
if (err)
|
|
290
|
+
return error(err);
|
|
291
|
+
this.connectionPoolState[cacheKey] = connection;
|
|
292
|
+
resolve(connection);
|
|
293
|
+
});
|
|
294
|
+
});
|
|
295
|
+
}
|
|
296
|
+
async getPgSqlConnectionPool(sql, config) {
|
|
297
|
+
return await new Promise((resolve, error) => {
|
|
298
|
+
const cacheKey = this.getCacheKey(config);
|
|
299
|
+
if (this.connectionPoolState[cacheKey])
|
|
300
|
+
return resolve(this.connectionPoolState[cacheKey]);
|
|
301
|
+
const pool = new sql.Pool(config);
|
|
302
|
+
this.connectionPoolState[cacheKey] = pool;
|
|
303
|
+
resolve(pool);
|
|
304
|
+
});
|
|
305
|
+
}
|
|
306
|
+
}();
|
|
307
|
+
|
|
308
|
+
class PgSqlDbTransaction {
|
|
309
|
+
constructor() {
|
|
310
|
+
this.transactionConnection = null;
|
|
311
|
+
this.isSelfTransaction = true;
|
|
312
|
+
this.dbContexts = null;
|
|
313
|
+
}
|
|
314
|
+
useTransaction(client) {
|
|
315
|
+
this.isSelfTransaction = false;
|
|
316
|
+
this.transactionConnection = client;
|
|
317
|
+
}
|
|
318
|
+
async begin(pool, isolationLevel, dbContexts) {
|
|
319
|
+
if (!this.transactionConnection) {
|
|
320
|
+
this.transactionConnection = await pool.connect();
|
|
321
|
+
this.isSelfTransaction = true;
|
|
322
|
+
const isoSql = this.convertToIsolationLevel(isolationLevel);
|
|
323
|
+
await this.transactionConnection.query(`BEGIN ${isoSql}`);
|
|
324
|
+
}
|
|
325
|
+
this.assignTransaction(dbContexts);
|
|
326
|
+
}
|
|
327
|
+
assignTransaction(dbContexts) {
|
|
328
|
+
if (dbContexts)
|
|
329
|
+
for (const dbContext of dbContexts) {
|
|
330
|
+
dbContext.connection.useTransaction(this.transactionConnection);
|
|
331
|
+
}
|
|
332
|
+
this.dbContexts = dbContexts;
|
|
333
|
+
}
|
|
334
|
+
async commit() {
|
|
335
|
+
if (this.transactionConnection && this.isSelfTransaction) {
|
|
336
|
+
try {
|
|
337
|
+
await this.transactionConnection.query("COMMIT");
|
|
338
|
+
} catch (err) {
|
|
339
|
+
throw err;
|
|
340
|
+
} finally {
|
|
341
|
+
this.transactionRelease();
|
|
342
|
+
this.transactionConnection.release();
|
|
343
|
+
this.transactionConnection = null;
|
|
344
|
+
}
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
async rollback() {
|
|
348
|
+
if (this.transactionConnection && this.isSelfTransaction) {
|
|
349
|
+
try {
|
|
350
|
+
await this.transactionConnection.query("ROLLBACK");
|
|
351
|
+
} catch (err) {
|
|
352
|
+
throw err;
|
|
353
|
+
} finally {
|
|
354
|
+
this.transactionRelease();
|
|
355
|
+
this.transactionConnection.release();
|
|
356
|
+
this.transactionConnection = null;
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
transactionRelease() {
|
|
361
|
+
if (this.dbContexts) {
|
|
362
|
+
for (const dbContext of this.dbContexts) {
|
|
363
|
+
dbContext.connection.releaseTransaction();
|
|
364
|
+
}
|
|
365
|
+
this.dbContexts = null;
|
|
366
|
+
}
|
|
367
|
+
}
|
|
368
|
+
releaseTransaction() {
|
|
369
|
+
this.transactionConnection = null;
|
|
370
|
+
this.isSelfTransaction = true;
|
|
371
|
+
}
|
|
372
|
+
convertToIsolationLevel(isolation) {
|
|
373
|
+
switch (isolation?.toUpperCase()) {
|
|
374
|
+
case "READ UNCOMMITTED":
|
|
375
|
+
return "ISOLATION LEVEL READ UNCOMMITTED";
|
|
376
|
+
case "REPEATABLE READ":
|
|
377
|
+
return "ISOLATION LEVEL REPEATABLE READ";
|
|
378
|
+
case "SERIALIZABLE":
|
|
379
|
+
return "ISOLATION LEVEL SERIALIZABLE";
|
|
380
|
+
case "READ COMMITTED":
|
|
381
|
+
default:
|
|
382
|
+
return "ISOLATION LEVEL READ COMMITTED";
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
}
|
|
386
|
+
|
|
387
|
+
class PgSqlConnection extends DbConnection {
|
|
388
|
+
constructor(config) {
|
|
389
|
+
super(config);
|
|
390
|
+
this.baseTransaction = new PgSqlDbTransaction();
|
|
391
|
+
}
|
|
392
|
+
get transaction() {
|
|
393
|
+
return this.baseTransaction;
|
|
394
|
+
}
|
|
395
|
+
useTransaction(connection) {
|
|
396
|
+
this.baseTransaction.useTransaction(connection);
|
|
397
|
+
}
|
|
398
|
+
useConnection(connection) {
|
|
399
|
+
this.connection = connection;
|
|
400
|
+
}
|
|
401
|
+
async executeQuery(query) {
|
|
402
|
+
try {
|
|
403
|
+
query.databaseServerTechnology = DatabaseServerTechnology.PGSQL;
|
|
404
|
+
const sqlQueryText = getSqlTextAndParams(query);
|
|
405
|
+
const result = await this.query(sqlQueryText);
|
|
406
|
+
let records = new Array();
|
|
407
|
+
const outputInfo = this.getOutput(result, query);
|
|
408
|
+
await this.runNestedObjectQueries(outputInfo, sqlQueryText.relationProps, query);
|
|
409
|
+
if (result["rows"]) {
|
|
410
|
+
records = result.rows;
|
|
411
|
+
}
|
|
412
|
+
return records;
|
|
413
|
+
} catch (ex) {
|
|
414
|
+
throw ex;
|
|
415
|
+
}
|
|
416
|
+
}
|
|
417
|
+
async runNestedObjectQueries(outputInfo, relationProps, config) {
|
|
418
|
+
if (outputInfo) {
|
|
419
|
+
switch (config.queryAction) {
|
|
420
|
+
case QueryAction.add:
|
|
421
|
+
for (const propName of relationProps.keys()) {
|
|
422
|
+
const entries = relationProps.get(propName);
|
|
423
|
+
const queryConfig = config.propsDbConfig.get(propName);
|
|
424
|
+
if (Array.isArray(entries) && queryConfig) {
|
|
425
|
+
for (const entity of entries) {
|
|
426
|
+
if (!entity[queryConfig.foreignKey])
|
|
427
|
+
entity[queryConfig.foreignKey] = outputInfo.value;
|
|
428
|
+
await this.runQuery([{ ...queryConfig, entity }], config.queryAction);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
break;
|
|
433
|
+
}
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
async executeFunc(funcName, params) {
|
|
437
|
+
let records = new Array();
|
|
438
|
+
if (isObject(params)) {
|
|
439
|
+
const queryInfo = { parameters: [] };
|
|
440
|
+
let query = `select * from ${funcName}(`;
|
|
441
|
+
let index = 1;
|
|
442
|
+
for (const [key, value] of Object.entries(params)) {
|
|
443
|
+
query += index == 1 ? `$${index}` : `,$${index}`;
|
|
444
|
+
index++;
|
|
445
|
+
queryInfo.parameters.push({ name: key, value });
|
|
446
|
+
}
|
|
447
|
+
query += ")";
|
|
448
|
+
queryInfo.query = query;
|
|
449
|
+
const result = await this.query(queryInfo);
|
|
450
|
+
if (result["rows"]) {
|
|
451
|
+
records = result.rows;
|
|
452
|
+
}
|
|
453
|
+
return records;
|
|
454
|
+
}
|
|
455
|
+
return records;
|
|
456
|
+
}
|
|
457
|
+
async executeSp(spName, params) {
|
|
458
|
+
let records = new Array();
|
|
459
|
+
if (isObject(params)) {
|
|
460
|
+
const queryInfo = { parameters: [] };
|
|
461
|
+
let query = `CALL ${spName}(`;
|
|
462
|
+
let index = 1;
|
|
463
|
+
for (const [key, value] of Object.entries(params)) {
|
|
464
|
+
query += index == 1 ? `$${index}` : `,$${index}`;
|
|
465
|
+
index++;
|
|
466
|
+
queryInfo.parameters.push({ name: key, value });
|
|
467
|
+
}
|
|
468
|
+
query += ")";
|
|
469
|
+
queryInfo.query = query;
|
|
470
|
+
const result = await this.query(queryInfo);
|
|
471
|
+
if (result["rows"]) {
|
|
472
|
+
records = result.rows;
|
|
473
|
+
}
|
|
474
|
+
return records;
|
|
475
|
+
}
|
|
476
|
+
return records;
|
|
477
|
+
}
|
|
478
|
+
getOutput(result, config) {
|
|
479
|
+
switch (config.queryAction) {
|
|
480
|
+
case QueryAction.add:
|
|
481
|
+
const primaryKey = config.primaryKeys[0];
|
|
482
|
+
const output = result.rows[0][primaryKey];
|
|
483
|
+
if (output)
|
|
484
|
+
config.entity[primaryKey] = output;
|
|
485
|
+
return { key: primaryKey, value: output };
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
async addEntries(dbEntities) {
|
|
489
|
+
await this.runQuery(dbEntities, QueryAction.add);
|
|
490
|
+
}
|
|
491
|
+
async updateEntries(dbEntities) {
|
|
492
|
+
await this.runQuery(dbEntities, QueryAction.update);
|
|
493
|
+
}
|
|
494
|
+
async deleteEntries(dbEntities) {
|
|
495
|
+
await this.runQuery(dbEntities, QueryAction.delete);
|
|
496
|
+
}
|
|
497
|
+
async runQuery(dbEntities, queryAction) {
|
|
498
|
+
for (const dbEntity of dbEntities) {
|
|
499
|
+
const executeQuery = {
|
|
500
|
+
...dbEntity,
|
|
501
|
+
queryAction
|
|
502
|
+
};
|
|
503
|
+
await this.executeQuery(executeQuery);
|
|
504
|
+
}
|
|
505
|
+
}
|
|
506
|
+
async query(queryInfo) {
|
|
507
|
+
const pool = await this.getConnectionPool();
|
|
508
|
+
const request = pool;
|
|
509
|
+
const values = queryInfo.parameters.map((t) => t.value);
|
|
510
|
+
const resolveQuery = (resolve, errorResolver) => (error, raw) => {
|
|
511
|
+
if (error)
|
|
512
|
+
errorResolver(error);
|
|
513
|
+
resolve(raw);
|
|
514
|
+
};
|
|
515
|
+
const catchFn = (ex) => {
|
|
516
|
+
throw ex;
|
|
517
|
+
};
|
|
518
|
+
if (queryInfo.query) {
|
|
519
|
+
const raw = await new Promise((resolve, error) => {
|
|
520
|
+
request.query(queryInfo.query, values, resolveQuery(resolve, error));
|
|
521
|
+
}).catch(catchFn);
|
|
522
|
+
return raw;
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
async beginTransaction(isolationLevel, dbContexts) {
|
|
526
|
+
const connection = await this.getConnectionPool();
|
|
527
|
+
await this.baseTransaction.begin(connection, isolationLevel, dbContexts);
|
|
528
|
+
}
|
|
529
|
+
async commitTransaction() {
|
|
530
|
+
await this.baseTransaction.commit();
|
|
531
|
+
}
|
|
532
|
+
async rollbackTransaction() {
|
|
533
|
+
await this.baseTransaction.rollback();
|
|
534
|
+
}
|
|
535
|
+
releaseTransaction() {
|
|
536
|
+
this.baseTransaction.releaseTransaction();
|
|
537
|
+
}
|
|
538
|
+
async getConnectionPool() {
|
|
539
|
+
return this.createPool();
|
|
540
|
+
}
|
|
541
|
+
async createPool() {
|
|
542
|
+
return await connectionCacheContainer.getPgSqlConnectionPool(this.pg, this.config);
|
|
236
543
|
}
|
|
237
544
|
}
|
|
238
545
|
|
|
@@ -344,6 +651,7 @@ class SqlConnection extends DbConnection {
|
|
|
344
651
|
}
|
|
345
652
|
async executeQuery(query) {
|
|
346
653
|
try {
|
|
654
|
+
query.databaseServerTechnology = DatabaseServerTechnology.MSSQL;
|
|
347
655
|
const sqlQueryText = getSqlTextAndParams(query);
|
|
348
656
|
const result = await this.query(sqlQueryText);
|
|
349
657
|
let records = new Array();
|
|
@@ -354,6 +662,7 @@ class SqlConnection extends DbConnection {
|
|
|
354
662
|
}
|
|
355
663
|
return records;
|
|
356
664
|
} catch (ex) {
|
|
665
|
+
throw ex;
|
|
357
666
|
}
|
|
358
667
|
}
|
|
359
668
|
async runNestedObjectQueries(outputInfo, relationProps, config) {
|
|
@@ -375,6 +684,27 @@ class SqlConnection extends DbConnection {
|
|
|
375
684
|
}
|
|
376
685
|
}
|
|
377
686
|
}
|
|
687
|
+
async executeFunc(funcName, params) {
|
|
688
|
+
let records = new Array();
|
|
689
|
+
if (isObject(params)) {
|
|
690
|
+
const queryInfo = { parameters: [] };
|
|
691
|
+
let query = `select * from ${funcName}(`;
|
|
692
|
+
let index = 1;
|
|
693
|
+
for (const [key, value] of Object.entries(params)) {
|
|
694
|
+
query += index == 1 ? `@${key}` : `,@${key}`;
|
|
695
|
+
index++;
|
|
696
|
+
queryInfo.parameters.push({ name: key, value });
|
|
697
|
+
}
|
|
698
|
+
query += ")";
|
|
699
|
+
queryInfo.query = query;
|
|
700
|
+
const result = await this.query(queryInfo);
|
|
701
|
+
if (result["recordset"]) {
|
|
702
|
+
records = result.recordset;
|
|
703
|
+
}
|
|
704
|
+
return records;
|
|
705
|
+
}
|
|
706
|
+
return records;
|
|
707
|
+
}
|
|
378
708
|
async executeSp(spName, params) {
|
|
379
709
|
let records = new Array();
|
|
380
710
|
if (isObject(params)) {
|
|
@@ -427,20 +757,23 @@ class SqlConnection extends DbConnection {
|
|
|
427
757
|
else
|
|
428
758
|
request.input(param.name, param.value);
|
|
429
759
|
}
|
|
430
|
-
const resolveQuery = (resolve) => (error, raw) => {
|
|
760
|
+
const resolveQuery = (resolve, errorResolver) => (error, raw) => {
|
|
431
761
|
if (error)
|
|
432
|
-
|
|
762
|
+
errorResolver(error);
|
|
433
763
|
resolve(raw);
|
|
434
764
|
};
|
|
765
|
+
const catchFn = (ex) => {
|
|
766
|
+
throw ex;
|
|
767
|
+
};
|
|
435
768
|
if (queryInfo.query) {
|
|
436
769
|
const raw = await new Promise((resolve, error) => {
|
|
437
|
-
request.query(queryInfo.query, resolveQuery(resolve));
|
|
438
|
-
});
|
|
770
|
+
request.query(queryInfo.query, resolveQuery(resolve, error));
|
|
771
|
+
}).catch(catchFn);
|
|
439
772
|
return raw;
|
|
440
773
|
} else if (queryInfo.sp) {
|
|
441
774
|
const raw = await new Promise((resolve, error) => {
|
|
442
|
-
request.execute(queryInfo.sp, resolveQuery(resolve));
|
|
443
|
-
});
|
|
775
|
+
request.execute(queryInfo.sp, resolveQuery(resolve, error));
|
|
776
|
+
}).catch(catchFn);
|
|
444
777
|
return raw;
|
|
445
778
|
}
|
|
446
779
|
}
|
|
@@ -461,19 +794,7 @@ class SqlConnection extends DbConnection {
|
|
|
461
794
|
return this.createPool();
|
|
462
795
|
}
|
|
463
796
|
async createPool() {
|
|
464
|
-
return await
|
|
465
|
-
if (this.baseTransaction.transactionConnection)
|
|
466
|
-
return resolve(this.baseTransaction.transactionConnection);
|
|
467
|
-
const pool = new this.mssql.ConnectionPool(this.config);
|
|
468
|
-
const errorHandler = (error2) => {
|
|
469
|
-
};
|
|
470
|
-
pool.on("error", errorHandler);
|
|
471
|
-
const connection = pool.connect((err) => {
|
|
472
|
-
if (err)
|
|
473
|
-
return error(err);
|
|
474
|
-
resolve(connection);
|
|
475
|
-
});
|
|
476
|
-
});
|
|
797
|
+
return await connectionCacheContainer.getConnectionPool(this.mssql, this.config);
|
|
477
798
|
}
|
|
478
799
|
}
|
|
479
800
|
|
|
@@ -481,6 +802,9 @@ class DbConnectionContext {
|
|
|
481
802
|
useSqlServer(options) {
|
|
482
803
|
this.connection = new SqlConnection(options);
|
|
483
804
|
}
|
|
805
|
+
usePgSqlServer(options) {
|
|
806
|
+
this.connection = new PgSqlConnection(options);
|
|
807
|
+
}
|
|
484
808
|
}
|
|
485
809
|
|
|
486
810
|
class DbSet {
|
|
@@ -587,6 +911,25 @@ class StoreProc {
|
|
|
587
911
|
}
|
|
588
912
|
}
|
|
589
913
|
|
|
914
|
+
class DbFunc {
|
|
915
|
+
constructor(funcName, type, queryConnection) {
|
|
916
|
+
this.funcName = funcName;
|
|
917
|
+
this.type = type;
|
|
918
|
+
this.queryConnection = queryConnection;
|
|
919
|
+
}
|
|
920
|
+
async execute(params) {
|
|
921
|
+
const items = await this.queryConnection.executeFunc(this.funcName, params);
|
|
922
|
+
return new List(items, this.type, this.properties);
|
|
923
|
+
}
|
|
924
|
+
get properties() {
|
|
925
|
+
const props = entityContainer.getProperties(this.type.name);
|
|
926
|
+
const jProps = {};
|
|
927
|
+
if (props)
|
|
928
|
+
props.forEach((property) => jProps[property.name.toLowerCase()] = property.name);
|
|
929
|
+
return jProps;
|
|
930
|
+
}
|
|
931
|
+
}
|
|
932
|
+
|
|
590
933
|
class DbContext {
|
|
591
934
|
get connection() {
|
|
592
935
|
return this.dbConnectionInfo.connection;
|
|
@@ -614,6 +957,11 @@ class DbContext {
|
|
|
614
957
|
for (const [key, value] of Object.entries(sps))
|
|
615
958
|
this[key] = new StoreProc(value.spName, value.model(), this.queryConnection);
|
|
616
959
|
}
|
|
960
|
+
onDbFuncRegistering(funcs) {
|
|
961
|
+
if (funcs)
|
|
962
|
+
for (const [key, value] of Object.entries(funcs))
|
|
963
|
+
this[key] = new DbFunc(value.funcName, value.model(), this.queryConnection);
|
|
964
|
+
}
|
|
617
965
|
async saveChanges() {
|
|
618
966
|
return new Promise(async (resolve, error) => {
|
|
619
967
|
try {
|
|
@@ -633,4 +981,4 @@ class DbContext {
|
|
|
633
981
|
}
|
|
634
982
|
}
|
|
635
983
|
|
|
636
|
-
export { DbContext, DbSet, StoreProc };
|
|
984
|
+
export { DbConnectionContext, DbContext, DbFunc, DbSet, StoreProc };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nattyjs/orm",
|
|
3
|
-
"version": "0.0.1-beta.
|
|
3
|
+
"version": "0.0.1-beta.40",
|
|
4
4
|
"description": "",
|
|
5
5
|
"module": "./dist/index.mjs",
|
|
6
6
|
"main": "./dist/index.cjs",
|
|
@@ -17,10 +17,11 @@
|
|
|
17
17
|
"unbuild": "1.2.1"
|
|
18
18
|
},
|
|
19
19
|
"dependencies": {
|
|
20
|
+
"pg": "8.16.0",
|
|
20
21
|
"mssql": "^9.1.1",
|
|
21
|
-
"@nattyjs/core": "0.0.1-beta.
|
|
22
|
-
"@nattyjs/common": "0.0.1-beta.
|
|
23
|
-
"@nattyjs/entity": "0.0.1-beta.
|
|
24
|
-
"@nattyjs/types": "0.0.1-beta.
|
|
22
|
+
"@nattyjs/core": "0.0.1-beta.40",
|
|
23
|
+
"@nattyjs/common": "0.0.1-beta.40",
|
|
24
|
+
"@nattyjs/entity": "0.0.1-beta.40",
|
|
25
|
+
"@nattyjs/types": "0.0.1-beta.40"
|
|
25
26
|
}
|
|
26
27
|
}
|