orange-orm 4.7.17 → 4.8.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (53) hide show
  1. package/dist/index.browser.mjs +4365 -3540
  2. package/dist/index.mjs +5204 -3601
  3. package/docs/changelog.md +5 -1
  4. package/package.json +1 -1
  5. package/src/applyPatch.js +67 -45
  6. package/src/bunPg/newTransaction.js +18 -0
  7. package/src/bunPg/wrapCommand.js +148 -0
  8. package/src/bunSqlite/newTransaction.js +18 -0
  9. package/src/bunSqlite/wrapCommand.js +30 -0
  10. package/src/bunSqlite/wrapQuery.js +1 -1
  11. package/src/client/index.js +3 -2
  12. package/src/client/netAdapter.js +2 -0
  13. package/src/d1/newTransaction.js +18 -0
  14. package/src/d1/wrapCommand.js +34 -0
  15. package/src/map2.d.ts +3 -3
  16. package/src/mssql/newTransaction.js +19 -0
  17. package/src/mssql/wrapCommand.js +129 -0
  18. package/src/mySql/newTransaction.js +18 -0
  19. package/src/mySql/wrapCommand.js +22 -0
  20. package/src/nodeSqlite/newTransaction.js +18 -0
  21. package/src/nodeSqlite/wrapCommand.js +34 -0
  22. package/src/oracle/newTransaction.js +18 -0
  23. package/src/oracle/wrapCommand.js +37 -0
  24. package/src/patchTable.js +107 -17
  25. package/src/pg/newTransaction.js +18 -0
  26. package/src/pg/wrapCommand.js +31 -0
  27. package/src/pglite/newTransaction.js +18 -0
  28. package/src/pglite/wrapCommand.js +30 -0
  29. package/src/sap/newTransaction.js +18 -0
  30. package/src/sqlite3/newTransaction.js +18 -0
  31. package/src/sqlite3/wrapCommand.js +23 -0
  32. package/src/table/commands/delete/newSingleCommand.js +3 -3
  33. package/src/table/commands/delete/singleCommand/newSingleCommandCore.js +112 -3
  34. package/src/table/commands/newDeleteCommand.js +3 -3
  35. package/src/table/commands/newRow.js +2 -2
  36. package/src/table/commands/newUpdateCommand.js +52 -2
  37. package/src/table/commands/newUpdateCommandCore.js +307 -4
  38. package/src/table/executeQueries/executeChanges.js +3 -3
  39. package/src/table/executeQueries/executeCommand.js +8 -0
  40. package/src/table/executeQueries/negotiateNullParams.js +26 -0
  41. package/src/table/executeQueries/resolveExecuteCommand.js +28 -0
  42. package/src/table/executeQueries/resolveExecuteQuery.js +1 -23
  43. package/src/table/isJsonUpdateSupported.js +5 -0
  44. package/src/table/resultToRows/decodeDbRow.js +13 -7
  45. package/src/table/resultToRows/delete.js +43 -2
  46. package/src/table/resultToRows/newDecodeDbRow.js +1 -7
  47. package/src/table.js +62 -0
  48. package/src/tedious/newTransaction.js +18 -0
  49. package/src/tedious/wrapCommand.js +121 -0
  50. package/src/validateDeleteAllowed.js +27 -10
  51. package/src/patchRow.js +0 -13
  52. package/src/table/insertDefault.js +0 -88
  53. package/src/validateDeleteConflict.js +0 -98
@@ -0,0 +1,129 @@
1
+ var log = require('../table/log');
2
+ var getSessionSingleton = require('../table/getSessionSingleton');
3
+
4
+ function wrapCommand(_context, connection) {
5
+ var runOriginalQuery = connection.query;
6
+ return runQuery;
7
+
8
+ function runQuery(query, onCompleted) {
9
+ var params = query.parameters;
10
+ var sql = query.sql();
11
+ log.emitQuery({ sql, parameters: params });
12
+
13
+ const replacements = [];
14
+ const parametersToRemove = [];
15
+ const engine = getSessionSingleton(_context, 'engine');
16
+
17
+ if (engine === 'sap') {
18
+ const sap = connection.msnodesqlv8;
19
+
20
+ const isStoredProcCall = /EXECUTE\s+/i.test(sql) || /EXEC\s+/i.test(sql);
21
+ let hexVariables = [];
22
+
23
+ for (let i = 0; i < params.length; i++) {
24
+ const parameter = params[i];
25
+
26
+ if (typeof parameter === 'string') {
27
+ const byteLength = Buffer.from(parameter, 'utf8').length;
28
+
29
+ if (hasNonAsciiCharacters(parameter)) {
30
+ const hexValue = stringToHex(parameter);
31
+
32
+ if (isStoredProcCall) {
33
+ const varName = `@hex_param_${i}`;
34
+ const convertClause = `CONVERT(VARCHAR(${byteLength}), CONVERT(VARBINARY(${byteLength}), 0x${hexValue}))`;
35
+
36
+ hexVariables.push({
37
+ declaration: `DECLARE ${varName} VARCHAR(${byteLength})`,
38
+ assignment: `SET ${varName} = ${convertClause}`
39
+ });
40
+
41
+ replacements.push({
42
+ index: i,
43
+ replacement: varName
44
+ });
45
+ } else {
46
+ const convertClause = `CONVERT(VARCHAR(${byteLength}), CONVERT(VARBINARY(${byteLength}), 0x${hexValue}))`;
47
+ replacements.push({
48
+ index: i,
49
+ replacement: convertClause
50
+ });
51
+ }
52
+ parametersToRemove.push(i);
53
+ } else {
54
+ params[i] = sap.VarChar(parameter, byteLength);
55
+ }
56
+ }
57
+ }
58
+
59
+ if (replacements.length > 0) {
60
+ let questionMarkIndex = 0;
61
+ sql = sql.replace(/\?/g, (match) => {
62
+ const replacement = replacements.find(r => r.index === questionMarkIndex);
63
+ questionMarkIndex++;
64
+
65
+ if (replacement) {
66
+ return replacement.replacement;
67
+ }
68
+ return match;
69
+ });
70
+
71
+ if (isStoredProcCall && hexVariables.length > 0) {
72
+ const lines = sql.split('\n');
73
+ let insertIndex = 0;
74
+
75
+ for (let i = 0; i < lines.length; i++) {
76
+ if (/^\s*DECLARE\s+/i.test(lines[i])) {
77
+ insertIndex = i + 1;
78
+ }
79
+ }
80
+
81
+ const hexDeclarations = hexVariables.map(v => v.declaration);
82
+ const hexAssignments = hexVariables.map(v => v.assignment);
83
+
84
+ lines.splice(insertIndex, 0, ...hexDeclarations, ...hexAssignments);
85
+ sql = lines.join('\n');
86
+ }
87
+ }
88
+
89
+ parametersToRemove.reverse().forEach(index => {
90
+ params.splice(index, 1);
91
+ });
92
+ }
93
+
94
+ let affectedRows = 0;
95
+
96
+ const q = runOriginalQuery.call(connection, sql, params, onInnerCompleted);
97
+
98
+ if (q && typeof q.on === 'function') {
99
+ q.on('rowcount', (count) => {
100
+ if (typeof count === 'number') {
101
+ affectedRows += count;
102
+ }
103
+ });
104
+ }
105
+
106
+ function onInnerCompleted(err, _rows, hasMore) {
107
+ if (err) {
108
+ if (err.code && err.code !== 3604) {
109
+ onCompleted(err, { rowsAffected: 0 });
110
+ return;
111
+ }
112
+ }
113
+
114
+ if (!hasMore) {
115
+ onCompleted(null, { rowsAffected: affectedRows });
116
+ }
117
+ }
118
+ }
119
+ }
120
+
121
+ function hasNonAsciiCharacters(str) {
122
+ return /[\u0080-\uFFFF]/.test(str);
123
+ }
124
+
125
+ function stringToHex(str) {
126
+ return Buffer.from(str, 'utf8').toString('hex');
127
+ }
128
+
129
+ module.exports = wrapCommand;
@@ -1,4 +1,5 @@
1
1
  const wrapQuery = require('./wrapQuery');
2
+ const wrapCommand = require('./wrapCommand');
2
3
  const encodeBoolean = require('./encodeBoolean');
3
4
  const deleteFromSql = require('./deleteFromSql');
4
5
  const selectForUpdateSql = require('./selectForUpdateSql');
@@ -51,6 +52,22 @@ function newResolveTransaction(domain, pool, { readonly = false } = {}) {
51
52
  callback(e);
52
53
  }
53
54
  });
55
+ },
56
+ executeCommand: function(query, callback) {
57
+ pool.connect((err, client, done) => {
58
+ if (err) {
59
+ return callback(err);
60
+ }
61
+ try {
62
+ wrapCommand(domain, client)(query, (err, res) => {
63
+ done();
64
+ callback(err, res);
65
+ });
66
+ } catch (e) {
67
+ done();
68
+ callback(e);
69
+ }
70
+ });
54
71
  }
55
72
  };
56
73
  domain.rdb = rdb;
@@ -67,6 +84,7 @@ function newResolveTransaction(domain, pool, { readonly = false } = {}) {
67
84
  return;
68
85
  }
69
86
  client.executeQuery = wrapQuery(domain, client);
87
+ client.executeCommand = wrapCommand(domain, client);
70
88
  rdb.dbClient = client;
71
89
  rdb.dbClientDone = done;
72
90
  domain.rdb = rdb;
@@ -0,0 +1,22 @@
1
+ var log = require('../table/log');
2
+
3
+ function wrapCommand(_context, connection) {
4
+ var runOriginalQuery = connection.query;
5
+ return runQuery;
6
+
7
+ function runQuery(query, onCompleted) {
8
+ var params = query.parameters;
9
+ var sql = query.sql();
10
+ log.emitQuery({sql, parameters: params});
11
+ return runOriginalQuery.call(connection, sql, params, _onCompleted);
12
+
13
+ function _onCompleted(e, _result) {
14
+ const result = {rowsAffected: _result?.affectedRows, ..._result};
15
+ onCompleted(e, result);
16
+
17
+ }
18
+ }
19
+
20
+ }
21
+
22
+ module.exports = wrapCommand;
@@ -1,4 +1,5 @@
1
1
  const wrapQuery = require('./wrapQuery');
2
+ const wrapCommand = require('./wrapCommand');
2
3
  const encodeBoolean = require('../sqlite/encodeBoolean');
3
4
  const encodeBinary = require('./encodeBinary');
4
5
  const decodeBinary = require('./decodeBinary');
@@ -56,6 +57,22 @@ function newResolveTransaction(domain, pool, { readonly = false } = {}) {
56
57
  callback(e);
57
58
  }
58
59
  });
60
+ },
61
+ executeCommand: function(query, callback) {
62
+ pool.connect((err, client, done) => {
63
+ if (err) {
64
+ return callback(err);
65
+ }
66
+ try {
67
+ wrapCommand(domain, client)(query, (err, res) => {
68
+ done();
69
+ callback(err, res);
70
+ });
71
+ } catch (e) {
72
+ done();
73
+ callback(e);
74
+ }
75
+ });
59
76
  }
60
77
  };
61
78
  domain.rdb = rdb;
@@ -72,6 +89,7 @@ function newResolveTransaction(domain, pool, { readonly = false } = {}) {
72
89
  return;
73
90
  }
74
91
  client.executeQuery = wrapQuery(domain, client);
92
+ client.executeCommand = wrapCommand(domain, client);
75
93
  rdb.dbClient = client;
76
94
  rdb.dbClientDone = done;
77
95
  domain.rdb = rdb;
@@ -0,0 +1,34 @@
1
+ const log = require('../table/log');
2
+ const connectionCache = new WeakMap();
3
+
4
+ function wrapCommand(_context, connection) {
5
+ let statementCache = connectionCache.get(connection);
6
+ if (!statementCache) {
7
+ statementCache = new Map();
8
+ connectionCache.set(connection, statementCache);
9
+ }
10
+
11
+ return runCommand;
12
+
13
+ function runCommand(query, onCompleted) {
14
+ try {
15
+ var params = query.parameters;
16
+ var sql = query.sql();
17
+ log.emitQuery({ sql, parameters: params });
18
+
19
+ let statement = statementCache.get(sql);
20
+ if (!statement) {
21
+ statement = connection.prepare(sql);
22
+ statementCache.set(sql, statement);
23
+ }
24
+ const info = statement.run.apply(statement, params);
25
+ onCompleted(null, { rowsAffected: info.changes, lastInsertRowid: info.lastInsertRowid });
26
+ }
27
+ catch (e) {
28
+ onCompleted(e);
29
+ }
30
+ }
31
+
32
+ }
33
+
34
+ module.exports = wrapCommand;
@@ -1,4 +1,5 @@
1
1
  const wrapQuery = require('./wrapQuery');
2
+ const wrapCommand = require('./wrapCommand');
2
3
  const encodeBoolean = require('./encodeBoolean');
3
4
  const deleteFromSql = require('./deleteFromSql');
4
5
  const selectForUpdateSql = require('./selectForUpdateSql');
@@ -58,6 +59,22 @@ function newResolveTransaction(domain, pool, { readonly = false } = {}) {
58
59
  callback(e);
59
60
  }
60
61
  });
62
+ },
63
+ executeCommand: function(query, callback) {
64
+ pool.connect((err, client, done) => {
65
+ if (err) {
66
+ return callback(err);
67
+ }
68
+ try {
69
+ wrapCommand(domain, client)(query, (err, res) => {
70
+ done();
71
+ callback(err, res);
72
+ });
73
+ } catch (e) {
74
+ done();
75
+ callback(e);
76
+ }
77
+ });
61
78
  }
62
79
  };
63
80
  domain.rdb = rdb;
@@ -75,6 +92,7 @@ function newResolveTransaction(domain, pool, { readonly = false } = {}) {
75
92
  return;
76
93
  }
77
94
  client.executeQuery = wrapQuery(domain, client);
95
+ client.executeCommand = wrapCommand(domain, client);
78
96
  rdb.dbClient = client;
79
97
  rdb.dbClientDone = done;
80
98
  domain.rdb = rdb;
@@ -0,0 +1,37 @@
1
+ var log = require('../table/log');
2
+ var replaceParamChar = require('./replaceParamChar');
3
+
4
+ function wrapCommand(_context, connection) {
5
+ var runOriginalQuery = connection.execute;
6
+ return runQuery;
7
+
8
+ function runQuery(query, onCompleted) {
9
+ var params = query.parameters;
10
+ log.emitQuery({ sql: query.sql(), parameters: params });
11
+
12
+ var sql = replaceParamChar(query, params);
13
+
14
+ runOriginalQuery.call(
15
+ connection,
16
+ sql,
17
+ params,
18
+ {
19
+ fetchTypeHandler: function(metaData) {
20
+ metaData.name = metaData.name.toLowerCase();
21
+ },
22
+ },
23
+ onInnerCompleted
24
+ );
25
+
26
+ function onInnerCompleted(err, result) {
27
+ if (err) return onCompleted(err);
28
+
29
+ var affectedRows =
30
+ typeof result.rowsAffected === 'number' ? result.rowsAffected : 0;
31
+
32
+ return onCompleted(null, { rowsAffected: affectedRows });
33
+ }
34
+ }
35
+ }
36
+
37
+ module.exports = wrapCommand;
package/src/patchTable.js CHANGED
@@ -1,21 +1,23 @@
1
1
  /* eslint-disable require-atomic-updates */
2
2
  let applyPatch = require('./applyPatch');
3
3
  let fromCompareObject = require('./fromCompareObject');
4
- let validateDeleteConflict = require('./validateDeleteConflict');
5
4
  let validateDeleteAllowed = require('./validateDeleteAllowed');
6
5
  let clearCache = require('./table/clearCache');
6
+ const getSessionSingleton = require('./table/getSessionSingleton');
7
+
7
8
 
8
9
  async function patchTable() {
9
10
  // const dryrun = true;
10
11
  //traverse all rows you want to update before updatinng or inserting anything.
11
12
  //this is to avoid page locks in ms sql
12
13
  // await patchTableCore.apply(null, [...arguments, dryrun]);
13
- const result = await patchTableCore.apply(null, arguments);
14
+ const result = await patchTableCore.apply(null, arguments);
14
15
  clearCache(arguments[0]);
15
16
  return result;
16
17
  }
17
18
 
18
19
  async function patchTableCore(context, table, patches, { strategy = undefined, deduceStrategy = false, ...options } = {}, dryrun) {
20
+ const engine = getSessionSingleton(context, 'engine');
19
21
  options = cleanOptions(options);
20
22
  strategy = JSON.parse(JSON.stringify(strategy || {}));
21
23
  let changed = new Set();
@@ -59,10 +61,11 @@ async function patchTableCore(context, table, patches, { strategy = undefined, d
59
61
  let property = path[0];
60
62
  path = path.slice(1);
61
63
  if (!row && path.length > 0) {
62
- const key = toKey(property);
63
- row = await table.tryGetById.apply(null, [context, ...key, strategy]);
64
- if (!row)
65
- throw new Error(`Row ${table._dbName} with id ${key} was not found.`);
64
+ row = await getOrCreateRow({
65
+ table,
66
+ strategy,
67
+ property
68
+ });
66
69
  }
67
70
 
68
71
  if (path.length === 0 && value === null) {
@@ -114,10 +117,22 @@ async function patchTableCore(context, table, patches, { strategy = undefined, d
114
117
  if (isColumn(property, table)) {
115
118
  if (dryrun)
116
119
  return { updated: row };
120
+ const column = table[property];
121
+ const oldColumnValue = row[property];
117
122
  let dto = {};
118
- dto[property] = row[property];
119
- let result = applyPatch({ options }, dto, [{ path: '/' + path.join('/'), op, value, oldValue }], table[property]);
120
- row[property] = result[property];
123
+ dto[property] = oldColumnValue;
124
+ const _oldValue = fromCompareObject(oldValue);
125
+ const _value = fromCompareObject(value);
126
+ let result = applyPatch({ options, context }, dto, [{ path: '/' + path.join('/'), op, value, oldValue }], table[property]);
127
+
128
+ const patchInfo = column.tsType === 'JSONColumn' ? {
129
+ path,
130
+ op,
131
+ value: _value,
132
+ oldValue : _oldValue,
133
+ fullOldValue: oldColumnValue
134
+ } : undefined;
135
+ await table.updateWithConcurrency(context, options, row, property, result[property], _oldValue, patchInfo);
121
136
  return { updated: row };
122
137
  }
123
138
  else if (isOneRelation(property, table)) {
@@ -216,19 +231,34 @@ async function patchTableCore(context, table, patches, { strategy = undefined, d
216
231
  async function remove({ path, op, oldValue, options }, table, row) {
217
232
  let property = path[0];
218
233
  path = path.slice(1);
219
- row = row || await table.getById.apply(null, [context, ...toKey(property)]);
234
+ if (!row)
235
+ row = await getOrCreateRow({ table, strategy: {}, property });
220
236
  if (path.length === 0) {
221
237
  await validateDeleteAllowed({ row, options, table });
222
- if (await validateDeleteConflict({ row, oldValue, options, table }))
223
- await row.deleteCascade();
238
+ applyDeleteConcurrencyState(row, oldValue, options, table);
239
+ await row.deleteCascade();
224
240
  }
225
241
  property = path[0];
226
242
  if (isColumn(property, table)) {
243
+ const column = table[property];
244
+ const oldColumnValue = row[property];
227
245
  let dto = {};
228
- dto[property] = row[property];
229
- let result = applyPatch({ options }, dto, [{ path: '/' + path.join('/'), op, oldValue }], table[property]);
246
+ dto[property] = oldColumnValue;
247
+ const _oldValue = fromCompareObject(oldValue);
230
248
 
231
- row[property] = result[property];
249
+ let result = applyPatch({ options, context }, dto, [{ path: '/' + path.join('/'), op, oldValue }], table[property]);
250
+ if (column.tsType === 'JSONColumn') {
251
+ const patchInfo = {
252
+ path,
253
+ op,
254
+ value: undefined,
255
+ oldValue: _oldValue,
256
+ fullOldValue: oldColumnValue
257
+ };
258
+ await table.updateWithConcurrency(context, options, row, property, result[property], _oldValue, patchInfo);
259
+ }
260
+ else
261
+ row[property] = result[property];
232
262
  return { updated: row };
233
263
  }
234
264
  else if (isJoinRelation(property, table) && path.length === 1) {
@@ -290,6 +320,40 @@ async function patchTableCore(context, table, patches, { strategy = undefined, d
290
320
  return table[name] && table[name].equal;
291
321
  }
292
322
 
323
+ function shouldFetchFromDb(table) {
324
+ return engine === 'sap'
325
+ && table._columns.some(x => x.tsType === 'JSONColumn');
326
+ }
327
+
328
+
329
+ function getOrCreateRow({ table, strategy, property }) {
330
+ const key = toKey(property);
331
+
332
+ if (shouldFetchFromDb(table))
333
+ return fetchFromDb({context, table, strategy, key});
334
+ return createRowInCache({ context, table, key });
335
+ }
336
+
337
+ async function fetchFromDb({context, table, strategy, key}) {
338
+ const row = await table.tryGetById.apply(null, [context, ...key, strategy]);
339
+ if (!row)
340
+ throw new Error(`Row ${table._dbName} with id ${key} was not found.`);
341
+ return row;
342
+
343
+ }
344
+
345
+
346
+
347
+ function createRowInCache({ context, table, key }) {
348
+ const newRow = getOrCreateRow.cachedNewRow || (getOrCreateRow.cachedNewRow = require('./table/commands/newRow'));
349
+ const pkDto = {};
350
+ for (let i = 0; i < key.length && i < table._primaryColumns.length; i++) {
351
+ pkDto[table._primaryColumns[i].alias] = key[i];
352
+ }
353
+ let row = newRow(context, { table, shouldValidate: false }, pkDto);
354
+ return table._cache.tryAdd(context, row);
355
+ }
356
+
293
357
  function isManyRelation(name, table) {
294
358
  return table[name] && table[name]._relation.isMany;
295
359
  }
@@ -303,6 +367,32 @@ async function patchTableCore(context, table, patches, { strategy = undefined, d
303
367
  return table[name] && table[name]._relation.columns;
304
368
  }
305
369
 
370
+ function applyDeleteConcurrencyState(row, oldValue, options, table) {
371
+ const state = { columns: {} };
372
+ if (oldValue && oldValue === Object(oldValue)) {
373
+ for (let p in oldValue) {
374
+ if (!isColumn(p, table))
375
+ continue;
376
+ const columnOptions = inferOptions(options, p);
377
+ const concurrency = columnOptions.concurrency || 'optimistic';
378
+ if (concurrency === 'overwrite')
379
+ continue;
380
+ state.columns[p] = { oldValue: fromCompareObject(oldValue[p]), concurrency };
381
+ }
382
+ }
383
+ if (Object.keys(state.columns).length === 0) {
384
+ const concurrency = options.concurrency || 'optimistic';
385
+ if (concurrency !== 'overwrite') {
386
+ for (let i = 0; i < table._primaryColumns.length; i++) {
387
+ const pkName = table._primaryColumns[i].alias;
388
+ state.columns[pkName] = { oldValue: row[pkName], concurrency };
389
+ }
390
+ }
391
+ }
392
+ if (Object.keys(state.columns).length > 0)
393
+ row._concurrencyState = state;
394
+ }
395
+
306
396
  function inferOptions(defaults, property) {
307
397
  const parent = {};
308
398
  if ('readonly' in defaults)
@@ -313,9 +403,9 @@ async function patchTableCore(context, table, patches, { strategy = undefined, d
313
403
  }
314
404
 
315
405
  function cleanOptions(options) {
316
- const { table, transaction, db, ..._options } = options;
406
+ const { table, transaction, db, client, ..._options } = options;
317
407
  return _options;
318
408
  }
319
409
  }
320
410
 
321
- module.exports = patchTable;
411
+ module.exports = patchTable;
@@ -1,4 +1,5 @@
1
1
  var wrapQuery = require('./wrapQuery');
2
+ var wrapCommand = require('./wrapCommand');
2
3
  var encodeDate = require('./encodeDate');
3
4
  var encodeBoolean = require('./encodeBoolean');
4
5
  var deleteFromSql = require('./deleteFromSql');
@@ -53,6 +54,22 @@ function newResolveTransaction(domain, pool, { readonly = false } = {}) {
53
54
  callback(e);
54
55
  }
55
56
  });
57
+ },
58
+ executeCommand: function(query, callback) {
59
+ pool.connect((err, client, done) => {
60
+ if (err) {
61
+ return callback(err);
62
+ }
63
+ try {
64
+ wrapCommand(domain, client)(query, (err, res) => {
65
+ done();
66
+ callback(err, res);
67
+ });
68
+ } catch (e) {
69
+ done();
70
+ callback(e);
71
+ }
72
+ });
56
73
  }
57
74
  };
58
75
  domain.rdb = rdb;
@@ -69,6 +86,7 @@ function newResolveTransaction(domain, pool, { readonly = false } = {}) {
69
86
  return;
70
87
  }
71
88
  client.executeQuery = wrapQuery(domain, client);
89
+ client.executeCommand = wrapCommand(domain, client);
72
90
  rdb.dbClient = client;
73
91
  rdb.dbClientDone = done;
74
92
  domain.rdb = rdb;
@@ -0,0 +1,31 @@
1
+ var log = require('../table/log');
2
+ var replaceParamChar = require('./replaceParamChar');
3
+
4
+ function wrapCommand(_context, connection) {
5
+ var runOriginalQuery = connection.query;
6
+ return runCommand;
7
+
8
+ function runCommand(query, onCompleted) {
9
+ var params = query.parameters;
10
+ log.emitQuery({sql: query.sql(), parameters: params});
11
+ var sql = replaceParamChar(query, params);
12
+ query = {
13
+ text: sql,
14
+ values: params,
15
+ types: query.types
16
+ };
17
+
18
+ runOriginalQuery.call(connection, query, onInnerCompleted);
19
+
20
+ function onInnerCompleted(err, result) {
21
+ if (err)
22
+ onCompleted(err);
23
+ else
24
+ onCompleted(null, { rowsAffected: result.rowCount });
25
+
26
+ }
27
+ }
28
+
29
+ }
30
+
31
+ module.exports = wrapCommand;
@@ -1,4 +1,5 @@
1
1
  var wrapQuery = require('./wrapQuery');
2
+ var wrapCommand = require('./wrapCommand');
2
3
  var encodeDate = require('../pg/encodeDate');
3
4
  const encodeBinary = require('../nodeSqlite/encodeBinary');
4
5
  const decodeBinary = require('../nodeSqlite/decodeBinary');
@@ -51,6 +52,22 @@ function newResolveTransaction(domain, pool, { readonly = false } = {}) {
51
52
  callback(e);
52
53
  }
53
54
  });
55
+ },
56
+ executeCommand: function(query, callback) {
57
+ pool.connect((err, client, done) => {
58
+ if (err) {
59
+ return callback(err);
60
+ }
61
+ try {
62
+ wrapCommand(domain, client)(query, (err, res) => {
63
+ done();
64
+ callback(err, res);
65
+ });
66
+ } catch (e) {
67
+ done();
68
+ callback(e);
69
+ }
70
+ });
54
71
  }
55
72
  };
56
73
  domain.rdb = rdb;
@@ -67,6 +84,7 @@ function newResolveTransaction(domain, pool, { readonly = false } = {}) {
67
84
  return;
68
85
  }
69
86
  client.executeQuery = wrapQuery(domain, client);
87
+ client.executeCommand = wrapCommand(domain, client);
70
88
  rdb.dbClient = client;
71
89
  rdb.dbClientDone = done;
72
90
  domain.rdb = rdb;
@@ -0,0 +1,30 @@
1
+ var log = require('../table/log');
2
+ var replaceParamChar = require('../pg/replaceParamChar');
3
+
4
+ function wrapCommand(_context, connection) {
5
+ var runOriginalQuery = connection.query;
6
+ return runQuery;
7
+
8
+ function runQuery(query, onCompleted) {
9
+ var params = query.parameters;
10
+ var sql = replaceParamChar(query, params);
11
+ log.emitQuery({ sql, parameters: params });
12
+
13
+ runOriginalQuery
14
+ .call(connection, sql, params)
15
+ .then(
16
+ (result) => onInnerCompleted(null, result),
17
+ (e) => onInnerCompleted(e)
18
+ );
19
+
20
+ function onInnerCompleted(err, result) {
21
+ if (err) return onCompleted(err);
22
+
23
+ if (Array.isArray(result)) result = result[result.length - 1];
24
+
25
+ onCompleted(null, { rowsAffected: result.affectedRows });
26
+ }
27
+ }
28
+ }
29
+
30
+ module.exports = wrapCommand;