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.
- package/dist/index.browser.mjs +4365 -3540
- package/dist/index.mjs +5204 -3601
- package/docs/changelog.md +5 -1
- package/package.json +1 -1
- package/src/applyPatch.js +67 -45
- package/src/bunPg/newTransaction.js +18 -0
- package/src/bunPg/wrapCommand.js +148 -0
- package/src/bunSqlite/newTransaction.js +18 -0
- package/src/bunSqlite/wrapCommand.js +30 -0
- package/src/bunSqlite/wrapQuery.js +1 -1
- package/src/client/index.js +3 -2
- package/src/client/netAdapter.js +2 -0
- package/src/d1/newTransaction.js +18 -0
- package/src/d1/wrapCommand.js +34 -0
- package/src/map2.d.ts +3 -3
- package/src/mssql/newTransaction.js +19 -0
- package/src/mssql/wrapCommand.js +129 -0
- package/src/mySql/newTransaction.js +18 -0
- package/src/mySql/wrapCommand.js +22 -0
- package/src/nodeSqlite/newTransaction.js +18 -0
- package/src/nodeSqlite/wrapCommand.js +34 -0
- package/src/oracle/newTransaction.js +18 -0
- package/src/oracle/wrapCommand.js +37 -0
- package/src/patchTable.js +107 -17
- package/src/pg/newTransaction.js +18 -0
- package/src/pg/wrapCommand.js +31 -0
- package/src/pglite/newTransaction.js +18 -0
- package/src/pglite/wrapCommand.js +30 -0
- package/src/sap/newTransaction.js +18 -0
- package/src/sqlite3/newTransaction.js +18 -0
- package/src/sqlite3/wrapCommand.js +23 -0
- package/src/table/commands/delete/newSingleCommand.js +3 -3
- package/src/table/commands/delete/singleCommand/newSingleCommandCore.js +112 -3
- package/src/table/commands/newDeleteCommand.js +3 -3
- package/src/table/commands/newRow.js +2 -2
- package/src/table/commands/newUpdateCommand.js +52 -2
- package/src/table/commands/newUpdateCommandCore.js +307 -4
- package/src/table/executeQueries/executeChanges.js +3 -3
- package/src/table/executeQueries/executeCommand.js +8 -0
- package/src/table/executeQueries/negotiateNullParams.js +26 -0
- package/src/table/executeQueries/resolveExecuteCommand.js +28 -0
- package/src/table/executeQueries/resolveExecuteQuery.js +1 -23
- package/src/table/isJsonUpdateSupported.js +5 -0
- package/src/table/resultToRows/decodeDbRow.js +13 -7
- package/src/table/resultToRows/delete.js +43 -2
- package/src/table/resultToRows/newDecodeDbRow.js +1 -7
- package/src/table.js +62 -0
- package/src/tedious/newTransaction.js +18 -0
- package/src/tedious/wrapCommand.js +121 -0
- package/src/validateDeleteAllowed.js +27 -10
- package/src/patchRow.js +0 -13
- package/src/table/insertDefault.js +0 -88
- 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
|
|
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
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
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] =
|
|
119
|
-
|
|
120
|
-
|
|
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
|
-
|
|
234
|
+
if (!row)
|
|
235
|
+
row = await getOrCreateRow({ table, strategy: {}, property });
|
|
220
236
|
if (path.length === 0) {
|
|
221
237
|
await validateDeleteAllowed({ row, options, table });
|
|
222
|
-
|
|
223
|
-
|
|
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] =
|
|
229
|
-
|
|
246
|
+
dto[property] = oldColumnValue;
|
|
247
|
+
const _oldValue = fromCompareObject(oldValue);
|
|
230
248
|
|
|
231
|
-
|
|
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;
|
package/src/pg/newTransaction.js
CHANGED
|
@@ -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;
|