oracledb 6.0.3 → 6.2.0

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 (65) hide show
  1. package/README.md +2 -2
  2. package/build/Release/oracledb-6.2.0-darwin-x64.node +0 -0
  3. package/build/Release/oracledb-6.2.0-darwin-x64.node-buildinfo.txt +1 -0
  4. package/build/Release/oracledb-6.2.0-js-buildinfo.txt +1 -0
  5. package/build/Release/oracledb-6.2.0-linux-arm64.node +0 -0
  6. package/build/Release/oracledb-6.2.0-linux-arm64.node-buildinfo.txt +1 -0
  7. package/build/Release/oracledb-6.2.0-linux-x64.node +0 -0
  8. package/build/Release/oracledb-6.2.0-linux-x64.node-buildinfo.txt +1 -0
  9. package/build/Release/oracledb-6.2.0-win32-x64.node +0 -0
  10. package/build/Release/oracledb-6.2.0-win32-x64.node-buildinfo.txt +1 -0
  11. package/examples/dbconfig.js +7 -14
  12. package/examples/example.js +0 -1
  13. package/lib/aqQueue.js +40 -26
  14. package/lib/connection.js +16 -4
  15. package/lib/dbObject.js +9 -0
  16. package/lib/errors.js +17 -13
  17. package/lib/impl/connection.js +9 -0
  18. package/lib/impl/resultset.js +7 -4
  19. package/lib/oracledb.js +26 -18
  20. package/lib/pool.js +7 -1
  21. package/lib/sodaCollection.js +12 -1
  22. package/lib/sodaOperation.js +16 -0
  23. package/lib/thin/connection.js +229 -182
  24. package/lib/thin/dbObject.js +4 -1
  25. package/lib/thin/pool.js +153 -68
  26. package/lib/thin/protocol/buffer.js +83 -64
  27. package/lib/thin/protocol/constants.js +3 -14
  28. package/lib/thin/protocol/encryptDecrypt.js +17 -17
  29. package/lib/thin/protocol/messages/auth.js +21 -23
  30. package/lib/thin/protocol/messages/base.js +29 -45
  31. package/lib/thin/protocol/messages/connectionCookie.js +76 -0
  32. package/lib/thin/protocol/messages/dataType.js +13 -9
  33. package/lib/thin/protocol/messages/execute.js +7 -7
  34. package/lib/thin/protocol/messages/index.js +2 -0
  35. package/lib/thin/protocol/messages/protocol.js +31 -20
  36. package/lib/thin/protocol/messages/withData.js +58 -47
  37. package/lib/thin/protocol/oson.js +17 -14
  38. package/lib/thin/protocol/packet.js +36 -14
  39. package/lib/thin/protocol/utils.js +2 -2
  40. package/lib/thin/resultSet.js +6 -6
  41. package/lib/thin/sqlnet/connStrategy.js +130 -5
  42. package/lib/thin/sqlnet/constants.js +2 -0
  43. package/lib/thin/sqlnet/ezConnectResolver.js +29 -61
  44. package/lib/thin/sqlnet/navNodes.js +34 -27
  45. package/lib/thin/sqlnet/networkSession.js +46 -47
  46. package/lib/thin/sqlnet/ntTcp.js +30 -14
  47. package/lib/thin/sqlnet/nvStrToNvPair.js +16 -16
  48. package/lib/thin/sqlnet/packet.js +10 -3
  49. package/lib/thin/sqlnet/paramParser.js +9 -9
  50. package/lib/thin/sqlnet/sessionAtts.js +4 -0
  51. package/lib/thin/statement.js +345 -113
  52. package/lib/thin/util.js +23 -86
  53. package/lib/transformer.js +3 -1
  54. package/lib/util.js +4 -13
  55. package/lib/version.js +2 -2
  56. package/package.json +1 -1
  57. package/build/Release/oracledb-6.0.3-darwin-x64.node +0 -0
  58. package/build/Release/oracledb-6.0.3-darwin-x64.node-buildinfo.txt +0 -1
  59. package/build/Release/oracledb-6.0.3-js-buildinfo.txt +0 -1
  60. package/build/Release/oracledb-6.0.3-linux-arm64.node +0 -0
  61. package/build/Release/oracledb-6.0.3-linux-arm64.node-buildinfo.txt +0 -1
  62. package/build/Release/oracledb-6.0.3-linux-x64.node +0 -0
  63. package/build/Release/oracledb-6.0.3-linux-x64.node-buildinfo.txt +0 -1
  64. package/build/Release/oracledb-6.0.3-win32-x64.node +0 -0
  65. package/build/Release/oracledb-6.0.3-win32-x64.node-buildinfo.txt +0 -1
@@ -28,29 +28,6 @@
28
28
 
29
29
  const { Buffer } = require('buffer');
30
30
  const constants = require('../constants');
31
- const thinUtil = require("./util.js");
32
-
33
- /* eslint-disable no-useless-escape */
34
- // Rules for named binds:
35
- // 1. Quoted and non-quoted bind names are allowed.
36
- // 2. Quoted binds can contain any characters.
37
- // 3. Non-quoted binds must begin with an alphabet character.
38
- // 4. Non-quoted binds can only contain alphanumeric characters, the underscore,
39
- // the dollar sign and the pound sign.
40
- // 5. Non-quoted binds cannot be Oracle Database Reserved Names
41
- // (Server handles this case and returns an appropriate error)
42
- const BIND_PATTERN = /(?<=:)\s*((?:".*?")|(?:[\p{L}][\p{L}\p{Nd}_\$#]*)|\p{Nd}+)/gu;
43
-
44
- // pattern used for detecting a DML returning clause; bind variables in the
45
- // first group are input variables; bind variables in the second group are
46
- // output only variables
47
- // assumes expressions/variables are seperated by delimiters space and comma
48
- const DML_RETURNING_KEY = /(?<=\bRETURN(?:ING)?\b)/si;
49
- const DML_RETURNING_INTO_KEY = /(?<=\bINTO\b)/gsi;
50
-
51
- const SINGLE_LINE_COMMENT_PATTERN = /--.*/g;
52
- const MULTI_LINE_COMMENT_PATTERN = /\/\*.*?\*\//sg;
53
- const CONSTANT_STRING_PATTERN = /'.*?'/sg;
54
31
 
55
32
  /**
56
33
  * It is used to cache the metadata about bind information
@@ -77,6 +54,286 @@ class BindInfo {
77
54
  */
78
55
  module.exports.BindInfo = BindInfo;
79
56
 
57
+ class Parser {
58
+ constructor() {
59
+ this.returningKeywordFound = false;
60
+ this.pos = 0;
61
+ this.maxPos = 0;
62
+ this.sqlData = "";
63
+ }
64
+
65
+ /**
66
+ * Bind variables are identified as follows:
67
+ * - Quoted and non-quoted bind names are allowed.
68
+ * - Quoted bind names can contain any characters.
69
+ * - Non-quoted bind names must begin with an alphabetic character.
70
+ * - Non-quoted bind names can only contain alphanumeric characters, the
71
+ * underscore, the dollar sign and the pound sign.
72
+ * - Non-quoted bind names cannot be Oracle Database Reserved Names (this
73
+ * is left to the server to detect and return an appropriate error).
74
+ */
75
+ _parseBindName(stmt) {
76
+ let quotedName = false;
77
+ let inBind = false;
78
+ let digitsOnly = false;
79
+ let startPos = 0;
80
+ let pos = this.pos + 1;
81
+ let bindName;
82
+ let ch;
83
+
84
+ while (pos <= this.maxPos) {
85
+ ch = this.sqlData[pos];
86
+ if (!inBind) {
87
+ if (/\p{space}/u.test(ch)) {
88
+ pos += 1;
89
+ continue;
90
+ } else if (ch === '"') {
91
+ quotedName = true;
92
+ } else if (/\p{N}/u.test(ch)) {
93
+ digitsOnly = true;
94
+ } else if (!/\p{Alpha}/u.test(ch)) {
95
+ break;
96
+ }
97
+ inBind = true;
98
+ startPos = pos;
99
+ } else if (digitsOnly && !(/\p{N}/u.test(ch))) {
100
+ this.pos = pos - 1;
101
+ break;
102
+ } else if (quotedName && ch === '"') {
103
+ this.pos = pos;
104
+ break;
105
+ } else if (!digitsOnly && !quotedName
106
+ && !(/[\p{L}\p{N}]/u.test(ch))
107
+ && !['$', '_', '#'].includes(ch)) {
108
+ this.pos = pos - 1;
109
+ break;
110
+ }
111
+ pos += 1;
112
+ }
113
+
114
+ if (inBind) {
115
+ if (quotedName) {
116
+ bindName = stmt.sql.substring(startPos + 1, pos);
117
+ } else if (digitsOnly) {
118
+ bindName = stmt.sql.substring(startPos, pos);
119
+ } else {
120
+ bindName = stmt.sql.substring(startPos, pos).toUpperCase();
121
+ }
122
+ stmt._addBind(bindName);
123
+ }
124
+ }
125
+
126
+ /**
127
+ * Multiple line comments consist of the characters /* followed by all
128
+ * characters up until * followed by /. This method is called when the first
129
+ * slash is detected and checks for the subsequent asterisk. If found,
130
+ * the comment is traversed and the current position is updated; otherwise,
131
+ * the current position is left untouched.
132
+ */
133
+ _parseMultiLineComment() {
134
+ let inComment = false;
135
+ let exitingComment = false;
136
+ let pos = this.pos + 1;
137
+ let ch;
138
+ while (pos <= this.maxPos) {
139
+ ch = this.sqlData[pos];
140
+ if (!inComment) {
141
+ if (ch !== '*') {
142
+ break;
143
+ }
144
+ inComment = true;
145
+ } else if (!exitingComment && ch === '*') {
146
+ exitingComment = true;
147
+ } else if (exitingComment) {
148
+ if (ch === '/') {
149
+ this.pos = pos;
150
+ break;
151
+ }
152
+ exitingComment = false;
153
+ }
154
+ pos += 1;
155
+ }
156
+ }
157
+
158
+ /** Parses a q-string which consists of the characters "q" and a single
159
+ * quote followed by a start separator, any text that does not contain the
160
+ * end seprator and the end separator and ending quote. The following are
161
+ * examples that demonstrate this:
162
+ * - q'[...]'
163
+ * - q'{...}'
164
+ * - q'<...>'
165
+ * - q'(...)'
166
+ * - q'?...?' (where ? is any character)
167
+ */
168
+ _parseQstring() {
169
+ let exitingQstring = false;
170
+ let inQstring = false;
171
+ let sep;
172
+ let ch;
173
+
174
+ this.pos += 1;
175
+
176
+ while (this.pos <= this.maxPos) {
177
+ ch = this.sqlData[this.pos];
178
+ if (!inQstring) {
179
+ if (ch === '[') {
180
+ sep = ']';
181
+ } else if (ch === '{') {
182
+ sep = '}';
183
+ } else if (ch === '(') {
184
+ sep = ')';
185
+ } else if (ch === '<') {
186
+ sep = '>';
187
+ } else {
188
+ sep = ch;
189
+ }
190
+ inQstring = true;
191
+ } else if (!exitingQstring && ch === sep) {
192
+ exitingQstring = true;
193
+ } else if (exitingQstring) {
194
+ if (ch === "'") {
195
+ break;
196
+ } else if (ch !== sep) {
197
+ exitingQstring = false;
198
+ }
199
+ }
200
+ this.pos += 1;
201
+ }
202
+ }
203
+
204
+ /**
205
+ * Parses a quoted string with the given separator. All characters until
206
+ * the separate is detected are discarded.
207
+ */
208
+ _parseQuotedString(sep) {
209
+ let ch;
210
+ this.pos += 1;
211
+ while (this.pos <= this.maxPos) {
212
+ ch = this.sqlData[this.pos];
213
+ if (ch === sep) {
214
+ break;
215
+ }
216
+ this.pos += 1;
217
+ }
218
+ }
219
+
220
+ /**
221
+ * Single line comments consist of two dashes and all characters up to the
222
+ * next line break. This method is called when the first dash is detected
223
+ * and checks for the subsequent dash. If found, the single line comment
224
+ * is traversed and the current position is updated; otherwise, the
225
+ * current position is left untouched.
226
+ */
227
+ _parseSingleLineComment() {
228
+ let inComment = false;
229
+ let pos = this.pos + 1;
230
+ let ch;
231
+
232
+ while (pos <= this.maxPos) {
233
+ ch = this.sqlData[pos];
234
+ if (!inComment) {
235
+ if (ch !== '-') {
236
+ break;
237
+ }
238
+ inComment = true;
239
+ } else if (ch === '\n') {
240
+ this.pos = pos;
241
+ break;
242
+ }
243
+ pos += 1;
244
+ }
245
+ }
246
+
247
+ /**
248
+ * Parses the SQL stored in the statement in order to determine the
249
+ * keyword that identifies the type of SQL being executed as well as a
250
+ * list of bind variable names. A check is also made for DML returning
251
+ * statements since the bind variables following the "INTO" keyword are
252
+ * treated differently from other bind variables.
253
+ */
254
+ parse(stmt) {
255
+ let initialKeywordFound = false;
256
+ let lastWasString = false;
257
+ let ch, lastCh = '', alphaStartCh = '';
258
+ let alphaStartPos = 0, alphaLen;
259
+ let isAlpha, lastWasAlpha = false;
260
+ let keyword;
261
+
262
+ // initialization
263
+ this.pos = 0;
264
+ this.maxPos = stmt.sql.length - 1;
265
+ this.sqlData = stmt.sql;
266
+
267
+ // scan all the characters in the string
268
+ while (this.pos <= this.maxPos) {
269
+ ch = this.sqlData[this.pos];
270
+ // look for certain keywords (initial keyword and the ones for
271
+ // detecting DML returning statements
272
+ isAlpha = /\p{L}/u.test(ch);
273
+ if (isAlpha && !lastWasAlpha) {
274
+ alphaStartPos = this.pos;
275
+ alphaStartCh = ch;
276
+ } else if (!isAlpha && lastWasAlpha) {
277
+ alphaLen = this.pos - alphaStartPos;
278
+ if (!initialKeywordFound) {
279
+ keyword = stmt.sql.substring(alphaStartPos, this.pos).toUpperCase();
280
+ stmt._determineStatementType(keyword);
281
+ initialKeywordFound = true;
282
+ if (stmt.isDdl) {
283
+ break;
284
+ }
285
+ } else if (stmt.isDml && !this.returningKeywordFound
286
+ && (alphaLen === 9 || alphaLen === 6)
287
+ && ['r', 'R'].includes(alphaStartCh)) {
288
+ keyword = stmt.sql.substring(alphaStartPos, this.pos).toUpperCase();
289
+ if (['RETURNING', 'RETURN'].includes(keyword)) {
290
+ this.returningKeywordFound = true;
291
+ }
292
+ } else if (this.returningKeywordFound && alphaLen === 4
293
+ && ['i', 'I'].includes(alphaStartCh)) {
294
+ keyword = stmt.sql.substring(alphaStartPos, this.pos).toUpperCase();
295
+ if (keyword === 'INTO') {
296
+ stmt.isReturning = true;
297
+ }
298
+ }
299
+ }
300
+
301
+ // need to keep track of whether the last token parsed was a string
302
+ // (excluding whitespace) as if the last token parsed was a string
303
+ // a following colon is not a bind variable but a part of the JSON
304
+ // constant syntax
305
+ if (ch === "'") {
306
+ lastWasString = true;
307
+ if (['q', 'Q'].includes(lastCh)) {
308
+ this._parseQstring();
309
+ } else {
310
+ this._parseQuotedString(ch);
311
+ }
312
+ } else if (!(/\p{space}/u.test(ch))) {
313
+ if (ch === '-') {
314
+ this._parseSingleLineComment();
315
+ } else if (ch === '/') {
316
+ this._parseMultiLineComment();
317
+ } else if (ch === '"') {
318
+ this._parseQuotedString(ch);
319
+ } else if (ch === ':' && !lastWasString) {
320
+ this._parseBindName(stmt);
321
+ }
322
+ lastWasString = false;
323
+ }
324
+
325
+ this.pos += 1;
326
+ lastWasAlpha = isAlpha;
327
+ lastCh = ch;
328
+ }
329
+
330
+ // if only a single word is found in sql, e.g. in case of commit/rollback
331
+ if (!initialKeywordFound) {
332
+ stmt._determineStatementType(stmt.sql.toUpperCase());
333
+ }
334
+ }
335
+ }
336
+
80
337
  class Statement {
81
338
  constructor() {
82
339
  this.sql = "";
@@ -143,54 +400,72 @@ class Statement {
143
400
  // Determine the type of the SQL statement by examining the first keyword
144
401
  // found in the statement
145
402
  //---------------------------------------------------------------------------
146
- _determineStatementType(sql) {
147
- sql = thinUtil.cleanSql(sql);
148
- let tokens = sql.trim().trimStart('(').substring(0, 10).split(" ");
149
- if (tokens.length > 0) {
150
- const sqlKeyword = tokens[0].toUpperCase();
151
- if (["DECLARE", "BEGIN", "CALL"].includes(sqlKeyword)) {
403
+ _determineStatementType(sqlKeyword) {
404
+ switch (sqlKeyword) {
405
+ case 'DECLARE':
152
406
  this.isPlSql = true;
153
- if (sqlKeyword === 'DECLARE') {
154
- this.statementType = constants.STMT_TYPE_DECLARE;
155
- } else if (sqlKeyword === 'BEGIN') {
156
- this.statementType = constants.STMT_TYPE_BEGIN;
157
- } else if (sqlKeyword === 'CALL') {
158
- this.statementType = constants.STMT_TYPE_CALL;
159
- }
160
- } else if (["SELECT", "WITH"].includes(sqlKeyword)) {
407
+ this.statementType = constants.STMT_TYPE_DECLARE;
408
+ break;
409
+ case 'CALL':
410
+ this.isPlSql = true;
411
+ this.statementType = constants.STMT_TYPE_CALL;
412
+ break;
413
+ case 'BEGIN':
414
+ this.isPlSql = true;
415
+ this.statementType = constants.STMT_TYPE_BEGIN;
416
+ break;
417
+ case 'SELECT':
161
418
  this.isQuery = true;
162
- if (sqlKeyword === "SELECT") {
163
- this.statementType = constants.STMT_TYPE_SELECT;
164
- }
165
- } else if (["INSERT", "UPDATE", "DELETE", "MERGE"].includes(sqlKeyword)) {
419
+ this.statementType = constants.STMT_TYPE_SELECT;
420
+ break;
421
+ case 'WITH':
422
+ this.isQuery = true;
423
+ break;
424
+ case 'INSERT':
166
425
  this.isDml = true;
167
- if (sqlKeyword === 'INSERT') {
168
- this.statementType = constants.STMT_TYPE_INSERT;
169
- } else if (sqlKeyword === 'UPDATE') {
170
- this.statementType = constants.STMT_TYPE_UPDATE;
171
- } else if (sqlKeyword === 'DELETE') {
172
- this.statementType = constants.STMT_TYPE_DELETE;
173
- } else if (sqlKeyword === 'MERGE') {
174
- this.statementType = constants.STMT_TYPE_MERGE;
175
- }
176
- } else if (["CREATE", "ALTER", "DROP", "TRUNCATE"].includes(sqlKeyword)) {
426
+ this.statementType = constants.STMT_TYPE_INSERT;
427
+ break;
428
+ case 'UPDATE':
429
+ this.isDml = true;
430
+ this.statementType = constants.STMT_TYPE_UPDATE;
431
+ break;
432
+ case 'DELETE':
433
+ this.isDml = true;
434
+ this.statementType = constants.STMT_TYPE_DELETE;
435
+ break;
436
+ case 'MERGE':
437
+ this.isDml = true;
438
+ this.statementType = constants.STMT_TYPE_MERGE;
439
+ break;
440
+ case 'ALTER':
177
441
  this.isDdl = true;
178
- if (sqlKeyword === 'CREATE') {
179
- this.statementType = constants.STMT_TYPE_CREATE;
180
- } else if (sqlKeyword === 'ALTER') {
181
- this.statementType = constants.STMT_TYPE_ALTER;
182
- } else if (sqlKeyword === 'DROP') {
183
- this.statementType = constants.STMT_TYPE_DROP;
184
- }
185
- } else if (sqlKeyword === 'COMMIT') {
442
+ this.statementType = constants.STMT_TYPE_ALTER;
443
+ break;
444
+ case 'CREATE':
445
+ this.isDdl = true;
446
+ this.statementType = constants.STMT_TYPE_CREATE;
447
+ break;
448
+ case 'DROP':
449
+ this.isDdl = true;
450
+ this.statementType = constants.STMT_TYPE_DROP;
451
+ break;
452
+ case 'ANALYZE':
453
+ case 'AUDIT':
454
+ case 'COMMENT':
455
+ case 'GRANT':
456
+ case 'REVOKE':
457
+ case 'TRUNCATE':
458
+ this.isDdl = true;
459
+ break;
460
+ case 'COMMIT':
186
461
  this.statementType = constants.STMT_TYPE_COMMIT;
187
- } else if (sqlKeyword === 'ROLLBACK') {
462
+ break;
463
+ case 'ROLLBACK':
188
464
  this.statementType = constants.STMT_TYPE_ROLLBACK;
189
- } else if (sqlKeyword === 'MERGE') {
190
- this.statementType = constants.STMT_TYPE_MERGE;
191
- } else {
465
+ break;
466
+ default:
192
467
  this.statementType = constants.STMT_TYPE_UNKNOWN;
193
- }
468
+ break;
194
469
  }
195
470
  }
196
471
 
@@ -205,40 +480,8 @@ class Statement {
205
480
  this.sql = sql;
206
481
  this.sqlBytes = Buffer.from(this.sql, 'utf8');
207
482
  this.sqlLength = this.sqlBytes.length;
208
- // replace literals with a specific literal
209
- sql = sql.replace(CONSTANT_STRING_PATTERN, "'S'");
210
- sql = sql.replace(SINGLE_LINE_COMMENT_PATTERN, "");
211
- sql = sql.replace(MULTI_LINE_COMMENT_PATTERN, "");
212
- this._determineStatementType(sql);
213
- let returningSql;
214
- if (this.isQuery || this.isDml || this.isPlSql) {
215
- let inputSql = sql;
216
- if (this.isDml) {
217
- /*
218
- * get starting index after DML_RETURNING_KEY from begining of sql and starting index
219
- * after DML_RETURNING_INTO_KEY from the end of sql
220
- */
221
- let result;
222
- let intoKey = -1;
223
- const retKey = sql.search(DML_RETURNING_KEY);
224
- let intoRegex = DML_RETURNING_INTO_KEY;
225
- // simulate lastInfdexOf with intoRegex input
226
- while ((result = intoRegex.exec(sql.slice(retKey))) != null) {
227
- intoKey = result.index;
228
- intoRegex.lastIndex = result.index + 1;
229
- }
230
- if (retKey > -1 && intoKey > -1) {
231
- intoKey = retKey + intoKey;
232
- inputSql = sql.slice(0, intoKey);
233
- returningSql = sql.slice(intoKey);
234
- }
235
- }
236
- this._addBinds(inputSql, false);
237
- if (returningSql) {
238
- this.isReturning = true;
239
- this._addBinds(returningSql, true);
240
- }
241
- }
483
+ const parser = new Parser();
484
+ parser.parse(this);
242
485
  }
243
486
 
244
487
  //---------------------------------------------------------------------------
@@ -247,27 +490,16 @@ class Statement {
247
490
  // Add bind information to the statement by examining the passed SQL for
248
491
  // bind variable names.
249
492
  //---------------------------------------------------------------------------
250
- _addBinds(sql, isReturnBind) {
251
- const regexMatchArray = [...sql.matchAll(BIND_PATTERN)];
252
- let name;
253
- regexMatchArray.forEach(element => {
254
- if (element[0].startsWith('"') && element[0].endsWith('"')) {
255
- name = element[0].substring(1, element[0].length - 1);
256
- } else {
257
- name = element[0].trim().toUpperCase();
258
- }
259
- if (this.isPlSql && this.bindInfoDict.has(name)) {
260
- return;
261
- }
262
- let info = new BindInfo(name, isReturnBind);
493
+ _addBind(name) {
494
+ if (!this.isPlSql || !this.bindInfoDict.has(name)) {
495
+ const info = new BindInfo(name, this.isReturning);
263
496
  this.bindInfoList.push(info);
264
-
265
497
  if (this.bindInfoDict.has(info.bindName)) {
266
498
  this.bindInfoDict.get(info.bindName).push(info);
267
499
  } else {
268
500
  this.bindInfoDict.set(info.bindName, [info]);
269
501
  }
270
- });
502
+ }
271
503
  }
272
504
 
273
505
  //---------------------------------------------------------------------------
package/lib/thin/util.js CHANGED
@@ -63,99 +63,41 @@ function getMetadataMany(vars) {
63
63
  }
64
64
 
65
65
  //---------------------------------------------------------------------------
66
- // getOutBinds(sql)
66
+ // getOutBindValues(sql)
67
67
  //
68
- // Get the outBinds for the sql
68
+ // Return the values for the out binds at the given position (row).
69
69
  //---------------------------------------------------------------------------
70
- function getOutBinds(bindVars, pos) {
71
- let bindByPos = (bindVars[0].name === undefined);
72
- let outBinds;
73
- if (bindByPos) {
74
- outBinds = [];
75
- } else {
76
- outBinds = {};
77
- }
70
+ function getOutBindValues(bindVars, pos) {
71
+ const bindByPos = (bindVars[0].name === undefined);
72
+ const outBindValues = (bindByPos) ? [] : {};
78
73
  for (let i = 0; i < bindVars.length; i++) {
79
- if (bindVars[i].dir === constants.BIND_IN)
80
- continue;
81
74
  if (bindByPos) {
82
- outBinds.push(bindVars[i].values[pos]);
75
+ outBindValues.push(bindVars[i].values[pos]);
83
76
  } else {
84
- outBinds[bindVars[i].name] = bindVars[i].values[pos];
77
+ outBindValues[bindVars[i].name] = bindVars[i].values[pos];
85
78
  }
86
79
  }
87
- return outBinds;
88
- }
89
-
90
- //---------------------------------------------------------------------------
91
- // getExecuteManyOutBinds(sql)
92
- //
93
- // Get the outBinds for the sql when doing an executeMany call
94
- //---------------------------------------------------------------------------
95
- function getExecuteManyOutBinds(bindVars, numIters) {
96
- let numOutBinds = getNumOutBinds(bindVars);
97
- if (numOutBinds === 0) {
98
- return;
99
- }
100
- let outBinds = new Array(numIters).fill(null);
101
- for (let i = 0; i < numIters; i++) {
102
- outBinds[i] = getOutBinds(bindVars, i);
103
- }
104
- return outBinds;
80
+ return outBindValues;
105
81
  }
106
82
 
107
83
  //---------------------------------------------------------------------------
108
- // getNumOutBinds(sql)
84
+ // getOutBinds()
109
85
  //
110
- // Get the number of outBinds for the sql
86
+ // Return the out binds for the given statement.
111
87
  //---------------------------------------------------------------------------
112
- function getNumOutBinds(bindVars) {
113
- let numOutBinds = 0;
114
- for (let i = 0; i < bindVars.length; i++) {
115
- if (bindVars[i].dir !== constants.BIND_IN) {
116
- numOutBinds++;
88
+ function getOutBinds(statement, numIters, executeManyFlag) {
89
+ const bindVars = statement.bindInfoList.map(i => i.bindVar);
90
+ const outBinds = bindVars.filter(v => v.dir !== constants.BIND_IN);
91
+ if (outBinds.length > 0) {
92
+ if (executeManyFlag) {
93
+ const outBindValues = new Array(numIters);
94
+ for (let i = 0; i < numIters; i++) {
95
+ outBindValues[i] = getOutBindValues(outBinds, i);
96
+ }
97
+ return outBindValues;
117
98
  }
99
+ return getOutBindValues(outBinds, 0);
118
100
  }
119
- return numOutBinds;
120
- }
121
-
122
- //---------------------------------------------------------------------------
123
- // getExecuteOutBinds(sql)
124
- //
125
- // Get the outBinds for the sql when doing an execute call
126
- //---------------------------------------------------------------------------
127
- function getExecuteOutBinds(bindVars) {
128
- let numOutBinds = getNumOutBinds(bindVars);
129
- if (numOutBinds === 0) {
130
- return;
131
- }
132
- return getOutBinds(bindVars, 0);
133
- }
134
-
135
- //---------------------------------------------------------------------------
136
- // cleanSql(sql)
137
- //
138
- // Sanitize the sql to remove comment and redundant information
139
- //---------------------------------------------------------------------------
140
- function cleanSql(sql) {
141
- sql = sql.trim();
142
- sql = sql.replace(/\--.*(\n|$)/g, ""); // eslint-disable-line
143
- sql = sql.replace(/\/\\*[\S\n ]+\\*\//g, "");
144
- sql = sql.replace(/\s+/g, " ");
145
- return sql;
146
- }
147
-
148
- //---------------------------------------------------------------------------
149
- // getOutBinds(sql)
150
- //
151
- // Get the bind variables from the bindInfoList of the statement object
152
- //---------------------------------------------------------------------------
153
- function getBindVars(statement) {
154
- let bindVars = [];
155
- for (const bindInfo of statement.bindInfoList) {
156
- bindVars.push(bindInfo.bindVar);
157
- }
158
- return bindVars;
159
101
  }
160
102
 
161
103
  //---------------------------------------------------------------------------
@@ -167,8 +109,7 @@ function checkProxyUserValidity(userName) {
167
109
  let schemaUser = '', proxyUser = '';
168
110
  let quoteFound = false, openSquareBracketFound = false;
169
111
  let lastQuoteFoundIndex = 0;
170
- let schemaUserStartIndex;
171
- let result = {
112
+ const result = {
172
113
  status : -1,
173
114
  proxyUser : '',
174
115
  schemaUser : ''
@@ -219,7 +160,7 @@ function checkProxyUserValidity(userName) {
219
160
  // extract schema user
220
161
  index = index + 1;
221
162
  quoteFound = false;
222
- schemaUserStartIndex = index;
163
+ const schemaUserStartIndex = index;
223
164
  lastQuoteFoundIndex = 0;
224
165
  while (index < userNameLength) {
225
166
  // check for double quotes
@@ -299,12 +240,8 @@ function checkCredentials(params) {
299
240
 
300
241
  module.exports = {
301
242
  getMetadataMany,
302
- cleanSql,
303
243
  CLIENT_INFO,
304
- getExecuteOutBinds,
305
- getExecuteManyOutBinds,
306
244
  getOutBinds,
307
- getBindVars,
308
245
  checkProxyUserValidity,
309
246
  checkCredentials
310
247
  };
@@ -248,5 +248,7 @@ function transformValueIn(info, value, options) {
248
248
 
249
249
  // define exports
250
250
  module.exports = {
251
- transformValueIn,
251
+ transformJsonValue,
252
+ transformValueIn
253
+
252
254
  };