orange-orm 4.7.4 → 4.7.5-beta.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.mjs CHANGED
@@ -17435,6 +17435,7 @@ function requireWrapQuery$2 () {
17435
17435
  if (hasRequiredWrapQuery$2) return wrapQuery_1$2;
17436
17436
  hasRequiredWrapQuery$2 = 1;
17437
17437
  var log = requireLog();
17438
+ var getSessionSingleton = requireGetSessionSingleton();
17438
17439
 
17439
17440
  function wrapQuery(_context, connection) {
17440
17441
  var runOriginalQuery = connection.query;
@@ -17443,14 +17444,99 @@ function requireWrapQuery$2 () {
17443
17444
  function runQuery(query, onCompleted) {
17444
17445
  var params = query.parameters;
17445
17446
  var sql = query.sql();
17446
- log.emitQuery({ sql, parameters: params });
17447
- const sap = connection.msnodesqlv8;
17448
- for (let i = 0; i < params.length; i++) {
17449
- const parameter = params[i];
17450
- if (typeof parameter === 'string')
17451
- params[i] = sap.VarChar(parameter);
17447
+
17448
+ const replacements = [];
17449
+ const parametersToRemove = [];
17450
+ const engine = getSessionSingleton(_context, 'engine');
17451
+
17452
+ if (engine === 'sap') {
17453
+ const sap = connection.msnodesqlv8;
17454
+ // Helper function to check for non-ASCII UTF-8 characters
17455
+
17456
+ // Check if this is a stored procedure call
17457
+ const isStoredProcCall = /EXECUTE\s+/i.test(sql) || /EXEC\s+/i.test(sql);
17458
+ let hexVariables = [];
17459
+
17460
+ // Non-ASCII UTF-8 characters workaround
17461
+ for (let i = 0; i < params.length; i++) {
17462
+ const parameter = params[i];
17463
+
17464
+ if (typeof parameter === 'string') {
17465
+ if (hasNonAsciiCharacters(parameter)) {
17466
+
17467
+ const hexValue = stringToHex(parameter);
17468
+
17469
+ if (isStoredProcCall) {
17470
+ // For stored procedures, create a variable
17471
+ const varName = `@hex_param_${i}`;
17472
+ const convertClause = `CONVERT(VARCHAR(255), CONVERT(VARBINARY(127), 0x${hexValue}))`;
17473
+
17474
+ hexVariables.push({
17475
+ declaration: `DECLARE ${varName} VARCHAR(255)`,
17476
+ assignment: `SET ${varName} = ${convertClause}`
17477
+ });
17478
+
17479
+ replacements.push({
17480
+ index: i,
17481
+ replacement: varName
17482
+ });
17483
+ } else {
17484
+ // For regular queries, use inline conversion
17485
+ const convertClause = `CONVERT(VARCHAR(255), CONVERT(VARBINARY(127), 0x${hexValue}))`;
17486
+ replacements.push({
17487
+ index: i,
17488
+ replacement: convertClause
17489
+ });
17490
+ }
17491
+ parametersToRemove.push(i);
17492
+ }
17493
+ else
17494
+ params[i] = sap.VarChar(parameter);
17495
+ }
17496
+ }
17497
+
17498
+ // Apply replacements
17499
+ if (replacements.length > 0) {
17500
+ let questionMarkIndex = 0;
17501
+ sql = sql.replace(/\?/g, (match) => {
17502
+ const replacement = replacements.find(r => r.index === questionMarkIndex);
17503
+ questionMarkIndex++;
17504
+
17505
+ if (replacement) {
17506
+ return replacement.replacement;
17507
+ }
17508
+ return match;
17509
+ });
17510
+
17511
+ // For stored procedures, inject hex variable declarations
17512
+ if (isStoredProcCall && hexVariables.length > 0) {
17513
+ const lines = sql.split('\n');
17514
+ let insertIndex = 0;
17515
+
17516
+ // Find the last DECLARE statement
17517
+ for (let i = 0; i < lines.length; i++) {
17518
+ if (/^\s*DECLARE\s+/i.test(lines[i])) {
17519
+ insertIndex = i + 1;
17520
+ }
17521
+ }
17522
+
17523
+ // Insert hex variable declarations and assignments
17524
+ const hexDeclarations = hexVariables.map(v => v.declaration);
17525
+ const hexAssignments = hexVariables.map(v => v.assignment);
17526
+
17527
+ lines.splice(insertIndex, 0, ...hexDeclarations, ...hexAssignments);
17528
+ sql = lines.join('\n');
17529
+ }
17530
+ }
17531
+
17532
+ // Remove parameters in reverse order to maintain correct indices
17533
+ parametersToRemove.reverse().forEach(index => {
17534
+ params.splice(index, 1);
17535
+ });
17452
17536
  }
17453
17537
 
17538
+ log.emitQuery({ sql, parameters: params });
17539
+
17454
17540
  runOriginalQuery.call(connection, sql, params, onInnerCompleted);
17455
17541
  let result = [];
17456
17542
 
@@ -17464,7 +17550,6 @@ function requireWrapQuery$2 () {
17464
17550
  }
17465
17551
  result.push(rows);
17466
17552
  if (!hasMore) {
17467
-
17468
17553
  if (result.length === 1)
17469
17554
  onCompleted(null, result[0]);
17470
17555
  else
@@ -17472,9 +17557,18 @@ function requireWrapQuery$2 () {
17472
17557
  }
17473
17558
  }
17474
17559
  }
17560
+ }
17475
17561
 
17562
+ function hasNonAsciiCharacters(str) {
17563
+ // Check if string contains any character with code point > 127 (non-ASCII)
17564
+ return /[\u0080-\uFFFF]/.test(str);
17476
17565
  }
17477
17566
 
17567
+ function stringToHex(str) {
17568
+ return Buffer.from(str, 'utf8').toString('hex');
17569
+ }
17570
+
17571
+
17478
17572
  wrapQuery_1$2 = wrapQuery;
17479
17573
  return wrapQuery_1$2;
17480
17574
  }
package/docs/changelog.md CHANGED
@@ -1,4 +1,6 @@
1
1
  ## Changelog
2
+ __4.7.5__
3
+ Implemented automatic hex conversion for non-ASCII UTF-8 characters in database parameters to resolve SAP ASE encoding issues.
2
4
  __4.7.4__
3
5
  Bugfix: SAP ASE: Do not throw errors on warnings. See [#129](https://github.com/alfateam/issues/129)
4
6
  __4.7.3__
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "orange-orm",
3
- "version": "4.7.4",
3
+ "version": "4.7.5-beta.1",
4
4
  "main": "./src/index.js",
5
5
  "module": "./dist/index.mjs",
6
6
  "browser": "./dist/index.browser.mjs",
@@ -1,4 +1,5 @@
1
1
  var log = require('../table/log');
2
+ var getSessionSingleton = require('../table/getSessionSingleton');
2
3
 
3
4
  function wrapQuery(_context, connection) {
4
5
  var runOriginalQuery = connection.query;
@@ -7,14 +8,99 @@ function wrapQuery(_context, connection) {
7
8
  function runQuery(query, onCompleted) {
8
9
  var params = query.parameters;
9
10
  var sql = query.sql();
10
- log.emitQuery({ sql, parameters: params });
11
- const sap = connection.msnodesqlv8;
12
- for (let i = 0; i < params.length; i++) {
13
- const parameter = params[i];
14
- if (typeof parameter === 'string')
15
- params[i] = sap.VarChar(parameter);
11
+
12
+ const replacements = [];
13
+ const parametersToRemove = [];
14
+ const engine = getSessionSingleton(_context, 'engine');
15
+
16
+ if (engine === 'sap') {
17
+ const sap = connection.msnodesqlv8;
18
+ // Helper function to check for non-ASCII UTF-8 characters
19
+
20
+ // Check if this is a stored procedure call
21
+ const isStoredProcCall = /EXECUTE\s+/i.test(sql) || /EXEC\s+/i.test(sql);
22
+ let hexVariables = [];
23
+
24
+ // Non-ASCII UTF-8 characters workaround
25
+ for (let i = 0; i < params.length; i++) {
26
+ const parameter = params[i];
27
+
28
+ if (typeof parameter === 'string') {
29
+ if (hasNonAsciiCharacters(parameter)) {
30
+
31
+ const hexValue = stringToHex(parameter);
32
+
33
+ if (isStoredProcCall) {
34
+ // For stored procedures, create a variable
35
+ const varName = `@hex_param_${i}`;
36
+ const convertClause = `CONVERT(VARCHAR(255), CONVERT(VARBINARY(127), 0x${hexValue}))`;
37
+
38
+ hexVariables.push({
39
+ declaration: `DECLARE ${varName} VARCHAR(255)`,
40
+ assignment: `SET ${varName} = ${convertClause}`
41
+ });
42
+
43
+ replacements.push({
44
+ index: i,
45
+ replacement: varName
46
+ });
47
+ } else {
48
+ // For regular queries, use inline conversion
49
+ const convertClause = `CONVERT(VARCHAR(255), CONVERT(VARBINARY(127), 0x${hexValue}))`;
50
+ replacements.push({
51
+ index: i,
52
+ replacement: convertClause
53
+ });
54
+ }
55
+ parametersToRemove.push(i);
56
+ }
57
+ else
58
+ params[i] = sap.VarChar(parameter);
59
+ }
60
+ }
61
+
62
+ // Apply replacements
63
+ if (replacements.length > 0) {
64
+ let questionMarkIndex = 0;
65
+ sql = sql.replace(/\?/g, (match) => {
66
+ const replacement = replacements.find(r => r.index === questionMarkIndex);
67
+ questionMarkIndex++;
68
+
69
+ if (replacement) {
70
+ return replacement.replacement;
71
+ }
72
+ return match;
73
+ });
74
+
75
+ // For stored procedures, inject hex variable declarations
76
+ if (isStoredProcCall && hexVariables.length > 0) {
77
+ const lines = sql.split('\n');
78
+ let insertIndex = 0;
79
+
80
+ // Find the last DECLARE statement
81
+ for (let i = 0; i < lines.length; i++) {
82
+ if (/^\s*DECLARE\s+/i.test(lines[i])) {
83
+ insertIndex = i + 1;
84
+ }
85
+ }
86
+
87
+ // Insert hex variable declarations and assignments
88
+ const hexDeclarations = hexVariables.map(v => v.declaration);
89
+ const hexAssignments = hexVariables.map(v => v.assignment);
90
+
91
+ lines.splice(insertIndex, 0, ...hexDeclarations, ...hexAssignments);
92
+ sql = lines.join('\n');
93
+ }
94
+ }
95
+
96
+ // Remove parameters in reverse order to maintain correct indices
97
+ parametersToRemove.reverse().forEach(index => {
98
+ params.splice(index, 1);
99
+ });
16
100
  }
17
101
 
102
+ log.emitQuery({ sql, parameters: params });
103
+
18
104
  runOriginalQuery.call(connection, sql, params, onInnerCompleted);
19
105
  let result = [];
20
106
 
@@ -28,7 +114,6 @@ function wrapQuery(_context, connection) {
28
114
  }
29
115
  result.push(rows);
30
116
  if (!hasMore) {
31
-
32
117
  if (result.length === 1)
33
118
  onCompleted(null, result[0]);
34
119
  else
@@ -36,7 +121,16 @@ function wrapQuery(_context, connection) {
36
121
  }
37
122
  }
38
123
  }
124
+ }
39
125
 
126
+ function hasNonAsciiCharacters(str) {
127
+ // Check if string contains any character with code point > 127 (non-ASCII)
128
+ return /[\u0080-\uFFFF]/.test(str);
40
129
  }
41
130
 
131
+ function stringToHex(str) {
132
+ return Buffer.from(str, 'utf8').toString('hex');
133
+ }
134
+
135
+
42
136
  module.exports = wrapQuery;