oracledb 6.0.3 → 6.1.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 (61) hide show
  1. package/README.md +2 -2
  2. package/build/Release/oracledb-6.1.0-darwin-x64.node +0 -0
  3. package/build/Release/oracledb-6.1.0-darwin-x64.node-buildinfo.txt +1 -0
  4. package/build/Release/oracledb-6.1.0-js-buildinfo.txt +1 -0
  5. package/build/Release/oracledb-6.1.0-linux-arm64.node +0 -0
  6. package/build/Release/oracledb-6.1.0-linux-arm64.node-buildinfo.txt +1 -0
  7. package/build/Release/oracledb-6.1.0-linux-x64.node +0 -0
  8. package/build/Release/oracledb-6.1.0-linux-x64.node-buildinfo.txt +1 -0
  9. package/build/Release/oracledb-6.1.0-win32-x64.node +0 -0
  10. package/build/Release/oracledb-6.1.0-win32-x64.node-buildinfo.txt +1 -0
  11. package/examples/example.js +0 -1
  12. package/lib/aqQueue.js +40 -26
  13. package/lib/connection.js +15 -3
  14. package/lib/errors.js +10 -6
  15. package/lib/impl/connection.js +9 -0
  16. package/lib/impl/resultset.js +7 -4
  17. package/lib/oracledb.js +15 -12
  18. package/lib/pool.js +7 -1
  19. package/lib/sodaCollection.js +1 -1
  20. package/lib/thin/connection.js +92 -30
  21. package/lib/thin/pool.js +153 -68
  22. package/lib/thin/protocol/buffer.js +19 -1
  23. package/lib/thin/protocol/constants.js +3 -14
  24. package/lib/thin/protocol/encryptDecrypt.js +17 -17
  25. package/lib/thin/protocol/messages/auth.js +21 -23
  26. package/lib/thin/protocol/messages/base.js +22 -45
  27. package/lib/thin/protocol/messages/connectionCookie.js +76 -0
  28. package/lib/thin/protocol/messages/dataType.js +13 -9
  29. package/lib/thin/protocol/messages/execute.js +7 -7
  30. package/lib/thin/protocol/messages/index.js +2 -0
  31. package/lib/thin/protocol/messages/protocol.js +31 -20
  32. package/lib/thin/protocol/messages/withData.js +49 -43
  33. package/lib/thin/protocol/oson.js +4 -4
  34. package/lib/thin/protocol/packet.js +31 -10
  35. package/lib/thin/protocol/utils.js +2 -2
  36. package/lib/thin/resultSet.js +6 -6
  37. package/lib/thin/sqlnet/connStrategy.js +130 -5
  38. package/lib/thin/sqlnet/constants.js +2 -0
  39. package/lib/thin/sqlnet/ezConnectResolver.js +20 -19
  40. package/lib/thin/sqlnet/navNodes.js +32 -25
  41. package/lib/thin/sqlnet/networkSession.js +35 -30
  42. package/lib/thin/sqlnet/ntTcp.js +30 -14
  43. package/lib/thin/sqlnet/nvStrToNvPair.js +16 -16
  44. package/lib/thin/sqlnet/packet.js +9 -2
  45. package/lib/thin/sqlnet/paramParser.js +9 -9
  46. package/lib/thin/sqlnet/sessionAtts.js +4 -0
  47. package/lib/thin/statement.js +3 -3
  48. package/lib/thin/util.js +7 -8
  49. package/lib/transformer.js +3 -1
  50. package/lib/util.js +0 -13
  51. package/lib/version.js +2 -2
  52. package/package.json +1 -1
  53. package/build/Release/oracledb-6.0.3-darwin-x64.node +0 -0
  54. package/build/Release/oracledb-6.0.3-darwin-x64.node-buildinfo.txt +0 -1
  55. package/build/Release/oracledb-6.0.3-js-buildinfo.txt +0 -1
  56. package/build/Release/oracledb-6.0.3-linux-arm64.node +0 -0
  57. package/build/Release/oracledb-6.0.3-linux-arm64.node-buildinfo.txt +0 -1
  58. package/build/Release/oracledb-6.0.3-linux-x64.node +0 -0
  59. package/build/Release/oracledb-6.0.3-linux-x64.node-buildinfo.txt +0 -1
  60. package/build/Release/oracledb-6.0.3-win32-x64.node +0 -0
  61. package/build/Release/oracledb-6.0.3-win32-x64.node-buildinfo.txt +0 -1
@@ -30,37 +30,13 @@ const { Buffer } = require('buffer');
30
30
  const constants = require("../constants.js");
31
31
  const errors = require("../../../errors.js");
32
32
 
33
- class OracleErrorInfo {
34
- constructor() {
35
- this.num = 0;
36
- this.cursorId = 0;
37
- this.pos = 0;
38
- this.rowCount = 0;
39
- this.message = "";
40
- this.rowID = null;
41
- this.batchErrors;
42
- }
43
- }
44
-
45
- class Error {
46
- constructor(num, message = "", context = "", isRecoverable = false, isWarning = false, code = 0, offset = 0) {
47
- this.num = num;
48
- this.message = message;
49
- this.context = context;
50
- this.isRecoverable = isRecoverable;
51
- this.isWarning = isWarning;
52
- this.code = code;
53
- this.offset = offset;
54
- }
55
- }
56
-
57
33
  /**
58
34
  *
59
35
  * Base class for all the RPC messages to support encode/decode functions
60
36
  */
61
37
  class Message {
62
38
  constructor(connection) {
63
- this.errorInfo = new OracleErrorInfo();
39
+ this.errorInfo = {};
64
40
  this.connection = connection;
65
41
  this.messageType = constants.TNS_MSG_TYPE_FUNCTION;
66
42
  this.functionCode = 0;
@@ -106,7 +82,7 @@ class Message {
106
82
  buf.skipUB1(); // call number
107
83
  buf.skipUB2(); // padding
108
84
  buf.skipUB4(); // success iters
109
- let numBytes = buf.readUB4(); // oerrdd (logical rowid)
85
+ const numBytes = buf.readUB4(); // oerrdd (logical rowid)
110
86
  if (numBytes > 0) {
111
87
  buf.skipBytesChunked();
112
88
  }
@@ -114,12 +90,12 @@ class Message {
114
90
  let numEntries = buf.readUB2(); // batch error codes array
115
91
  if (numEntries > 0) {
116
92
  this.errorInfo.batchErrors = [];
117
- let firstByte = buf.readUInt8();
93
+ const firstByte = buf.readUInt8();
118
94
  for (let i = 0; i < numEntries; i++) {
119
95
  if (firstByte === constants.TNS_LONG_LENGTH_INDICATOR) {
120
96
  buf.skipUB4(); // chunk length ignored
121
97
  }
122
- let errorCode = buf.readUB2();
98
+ const errorCode = buf.readUB2();
123
99
  this.errorInfo.batchErrors.push(new Error(errorCode));
124
100
  }
125
101
  if (firstByte === constants.TNS_LONG_LENGTH_INDICATOR) {
@@ -130,7 +106,7 @@ class Message {
130
106
  // batch error offset
131
107
  numEntries = buf.readUB2(); // batch error row offset array
132
108
  if (numEntries > 0) {
133
- let firstByte = buf.readUInt8();
109
+ const firstByte = buf.readUInt8();
134
110
  for (let i = 0; i < numEntries; i++) {
135
111
  if (firstByte === constants.TNS_LONG_LENGTH_INDICATOR) {
136
112
  buf.skipUB4(); // chunk length ignored
@@ -172,7 +148,7 @@ class Message {
172
148
 
173
149
  processWarningInfo(buf) {
174
150
  this.errorInfo.num = buf.readUB2(); // error number
175
- let numBytes = buf.readUB2(); // length of error message
151
+ const numBytes = buf.readUB2(); // length of error message
176
152
  buf.skipUB2(); // flags
177
153
  if (this.errorInfo.num != 0 && numBytes > 0) {
178
154
  this.errorInfo.message = buf.readStr(constants.CSFRM_IMPLICIT);
@@ -224,18 +200,19 @@ class Message {
224
200
  if (opcode === constants.TNS_SERVER_PIGGYBACK_LTXID) {
225
201
  const num_bytes = buf.readUB4();
226
202
  if (num_bytes > 0) {
227
- buf.skipBytes(num_bytes);
203
+ buf.skipBytesChunked();
228
204
  }
229
205
  } else if ((opcode === constants.TNS_SERVER_PIGGYBACK_QUERY_CACHE_INVALIDATION)
230
206
  || (opcode === constants.TNS_SERVER_PIGGYBACK_TRACE_EVENT)) {
231
207
  // pass
232
208
  } else if (opcode === constants.TNS_SERVER_PIGGYBACK_OS_PID_MTS) {
233
- buf.skipUB2();
234
- buf.skipBytesChunked();
209
+ const numDtys = buf.readUB2();
210
+ buf.skipUB1();
211
+ buf.skipBytes(numDtys);
235
212
  } else if (opcode === constants.TNS_SERVER_PIGGYBACK_SYNC) {
236
213
  buf.skipUB2(); // skip number of DTYs
237
214
  buf.skipUB1(); // skip length of DTYs
238
- const num_elements = buf.readUB2();
215
+ const num_elements = buf.readUB4();
239
216
  buf.skipBytes(1); // skip length
240
217
  for (let i = 0; i < num_elements; i++) {
241
218
  let temp16 = buf.readUB2();
@@ -247,20 +224,20 @@ class Message {
247
224
  buf.skipBytesChunked();
248
225
  }
249
226
  buf.skipUB2(); // skip flags
250
- buf.skipUB4(); // skip overall flags
251
227
  }
228
+ buf.skipUB4(); // skip overall flags
252
229
  } else if (opcode === constants.TNS_SERVER_PIGGYBACK_EXT_SYNC) {
253
230
  buf.skipUB2();
254
231
  buf.skipUB1();
255
232
  } else if (opcode === constants.TNS_SERVER_PIGGYBACK_AC_REPLAY_CONTEXT) {
256
233
  buf.skipUB2(); // skip number of DTYs
257
- buf.skipUB1(1); // skip length of DTYs
234
+ buf.skipUB1(); // skip length of DTYs
258
235
  buf.skipUB4(); // skip flags
259
236
  buf.skipUB4(); // skip error code
260
237
  buf.skipUB1(); // skip queue
261
238
  const num_bytes = buf.readUB4(); // skip replay context
262
239
  if (num_bytes > 0) {
263
- buf.skipBytes(num_bytes);
240
+ buf.skipBytesChunked();
264
241
  }
265
242
  } else if (opcode === constants.TNS_SERVER_PIGGYBACK_SESS_RET) {
266
243
  buf.skipUB2();
@@ -283,7 +260,7 @@ class Message {
283
260
  const flags = buf.readUB4(); // session flags
284
261
  if (flags & constants.TNS_SESSGET_SESSION_CHANGED) {
285
262
  if (this.connection._drcpEstablishSession) {
286
- this.connection.resetStatmentCache();
263
+ this.connection.resetStatementCache();
287
264
  }
288
265
  }
289
266
  this.connection._drcpEstablishSession = false;
@@ -335,8 +312,8 @@ class Message {
335
312
  }
336
313
 
337
314
  writeCloseTempLobsPiggyback(buf) {
338
- let lobsToClose = this.connection._tempLobsToClose;
339
- let opCode = constants.TNS_LOB_OP_FREE_TEMP | constants.TNS_LOB_OP_ARRAY;
315
+ const lobsToClose = this.connection._tempLobsToClose;
316
+ const opCode = constants.TNS_LOB_OP_FREE_TEMP | constants.TNS_LOB_OP_ARRAY;
340
317
 
341
318
  this.writePiggybackHeader(buf, constants.TNS_FUNC_LOB_OP);
342
319
 
@@ -406,9 +383,9 @@ class Message {
406
383
  buf.writeUInt8(0); // pointer (cidser)
407
384
  buf.writeUB4(flags);
408
385
 
409
- let clientIdentifierBytes = this.writeEndEndTraceValue(buf, this.connection._clientIdentifier, this.connection._clientIdentifierModified);
410
- let moduleBytes = this.writeEndEndTraceValue(buf, this.connection._module, this.connection._moduleModified);
411
- let actionBytes = this.writeEndEndTraceValue(buf, this.connection._action, this.connection._actionModified);
386
+ const clientIdentifierBytes = this.writeEndEndTraceValue(buf, this.connection._clientIdentifier, this.connection._clientIdentifierModified);
387
+ const moduleBytes = this.writeEndEndTraceValue(buf, this.connection._module, this.connection._moduleModified);
388
+ const actionBytes = this.writeEndEndTraceValue(buf, this.connection._action, this.connection._actionModified);
412
389
 
413
390
  // write unsupported bits
414
391
  buf.writeUInt8(0); // pointer (cideci)
@@ -416,13 +393,13 @@ class Message {
416
393
  buf.writeUInt8(0); // cidcct
417
394
  buf.writeUB4(0); // cidecs
418
395
 
419
- let clientInfoBytes = this.writeEndEndTraceValue(buf, this.connection._clientInfo, this.connection._clientInfoModified);
396
+ const clientInfoBytes = this.writeEndEndTraceValue(buf, this.connection._clientInfo, this.connection._clientInfoModified);
420
397
  // write unsupported bits
421
398
  buf.writeUInt8(0); // pointer (cideci)
422
399
  buf.writeUB4(0); // length (cideci)
423
400
  buf.writeUInt8(0); // cidcct
424
401
  buf.writeUB4(0); // cidecs
425
- let dbOpBytes = this.writeEndEndTraceValue(buf, this.connection._dbOp, this.connection._dbOpModified);
402
+ const dbOpBytes = this.writeEndEndTraceValue(buf, this.connection._dbOp, this.connection._dbOpModified);
426
403
 
427
404
  // write strings
428
405
  if (this.connection._clientIdentifierModified && this.connection._clientIdentifier) {
@@ -0,0 +1,76 @@
1
+ // Copyright (c) 2023 Oracle and/or its affiliates.
2
+
3
+ //-----------------------------------------------------------------------------
4
+ //
5
+ // This software is dual-licensed to you under the Universal Permissive License
6
+ // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License
7
+ // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose
8
+ // either license.
9
+ //
10
+ // If you elect to accept the software under the Apache License, Version 2.0,
11
+ // the following applies:
12
+ //
13
+ // Licensed under the Apache License, Version 2.0 (the "License");
14
+ // you may not use this file except in compliance with the License.
15
+ // You may obtain a copy of the License at
16
+ //
17
+ // https://www.apache.org/licenses/LICENSE-2.0
18
+ //
19
+ // Unless required by applicable law or agreed to in writing, software
20
+ // distributed under the License is distributed on an "AS IS" BASIS,
21
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22
+ // See the License for the specific language governing permissions and
23
+ // limitations under the License.
24
+ //
25
+ //-----------------------------------------------------------------------------
26
+
27
+ 'use strict';
28
+
29
+ const constants = require("../constants.js");
30
+ const Message = require("./base.js");
31
+
32
+ /**
33
+ * Executes a Fast Negotiation RPC function.
34
+ * It sends Protocol Negotiation, Cookie Message, Datatype Negotiation
35
+ * and OSESS Key RPC in single round trip.
36
+ *
37
+ * @class ConnectionCookieMessage
38
+ * @extends {Message}
39
+ */
40
+ class ConnectionCookieMessage extends Message {
41
+
42
+ /**
43
+ * Serializes the ConnectionCookieMessage function arguments
44
+ *
45
+ * @param {object} buf input arguments
46
+ */
47
+ encode(buf) {
48
+ this.protocolMessage.encode(buf);
49
+ buf.writeUInt8(constants.TNS_MSG_TYPE_COOKIE);
50
+ buf.writeUInt8(1); // cookie version
51
+ buf.writeUInt8(this.cookie.protocolVersion);
52
+ buf.writeUInt16LE(this.cookie.charsetID);
53
+ buf.writeUInt8(this.cookie.flags);
54
+ buf.writeUInt16LE(this.cookie.ncharsetID);
55
+ buf.writeBytesWithLength(this.cookie.serverBanner);
56
+ buf.writeBytesWithLength(this.cookie.compileCaps);
57
+ buf.writeBytesWithLength(this.cookie.runtimeCaps);
58
+ this.dataTypeMessage.encode(buf);
59
+ this.authMessage.encode(buf);
60
+ }
61
+
62
+ processMessage(buf, messageType) {
63
+ if (messageType === constants.TNS_MSG_TYPE_RENEGOTIATE) {
64
+ this.cookie.populated = false;
65
+ } else if (messageType === constants.TNS_MSG_TYPE_PROTOCOL) {
66
+ this.protocolMessage.processMessage(buf, messageType);
67
+ } else if (messageType === constants.TNS_MSG_TYPE_DATA_TYPES) {
68
+ this.dataTypeMessage.processMessage(buf, messageType);
69
+ } else {
70
+ this.authMessage.processMessage(buf, messageType);
71
+ }
72
+ }
73
+
74
+ }
75
+
76
+ module.exports = ConnectionCookieMessage;
@@ -38,14 +38,18 @@ const Message = require("./base.js");
38
38
  */
39
39
  class DataTypeMessage extends Message {
40
40
 
41
- processMessage(buf) {
42
- while (true) { // eslint-disable-line
43
- const dataType = buf.readUInt16BE();
44
- if (dataType === 0)
45
- break;
46
- const convDataType = buf.readUInt16BE();
47
- if (convDataType !== 0)
48
- buf.skipBytes(4);
41
+ processMessage(buf, messageType) {
42
+ if (messageType === constants.TNS_MSG_TYPE_DATA_TYPES) {
43
+ while (true) { // eslint-disable-line
44
+ const dataType = buf.readUInt16BE();
45
+ if (dataType === 0)
46
+ break;
47
+ const convDataType = buf.readUInt16BE();
48
+ if (convDataType !== 0)
49
+ buf.skipBytes(4);
50
+ }
51
+ } else {
52
+ super.processMessage(buf, messageType);
49
53
  }
50
54
  }
51
55
 
@@ -57,7 +61,7 @@ class DataTypeMessage extends Message {
57
61
  constants.TNS_ENCODING_CONV_LENGTH);
58
62
  buf.writeBytesWithLength(buf.caps.compileCaps);
59
63
  buf.writeBytesWithLength(buf.caps.runtimeCaps);
60
- for (let val of dataTypes) {
64
+ for (const val of dataTypes) {
61
65
  buf.writeUInt16BE(val[0]);
62
66
  buf.writeUInt16BE(val[1]);
63
67
  buf.writeUInt16BE(val[2]);
@@ -65,8 +65,8 @@ class ExecuteMessage extends MessageWithData {
65
65
  let numParams = 0;
66
66
  let numIters = 1;
67
67
  // Configuring the options field thats send to the server
68
- let stmt = this.statement;
69
- let params = stmt.bindInfoList;
68
+ const stmt = this.statement;
69
+ const params = stmt.bindInfoList;
70
70
 
71
71
  if (!stmt.requiresDefine && !this.parseOnly && params) {
72
72
  numParams = params.length;
@@ -223,7 +223,7 @@ class ExecuteMessage extends MessageWithData {
223
223
  // Write the message header for a re-execute and return the bind parameters.
224
224
  //-------------------------------------------------------------------------
225
225
  writeReExecuteMessage(buf) {
226
- let stmt = this.statement;
226
+ const stmt = this.statement;
227
227
  let params = stmt.bindInfoList;
228
228
  let execFlag1 = 0, execFlag2 = 0, numIters;
229
229
  if (params !== undefined) {
@@ -236,7 +236,7 @@ class ExecuteMessage extends MessageWithData {
236
236
  });
237
237
  }
238
238
 
239
- let tmpparams = [];
239
+ const tmpparams = [];
240
240
  params.forEach(info => {
241
241
  if (info.bindDir !== constants.TNS_BIND_DIR_OUTPUT && !info.isReturnBind) {
242
242
  tmpparams.push(info);
@@ -274,9 +274,9 @@ class ExecuteMessage extends MessageWithData {
274
274
 
275
275
  // no rows have yet been sent so the header information needs to be sent
276
276
  if (this.currentRow === 0) {
277
- let stmt = this.statement;
278
- if (stmt.cursorId !== 0 && !stmt.requiresFullExecute && !this.parseOnly && !stmt.requiresDefine && !stmt.isDdl && !this.batchErrors) {
279
- if (stmt.isQuery && !stmt.requiresDefine && !stmt.noPrefetch && this.options.prefetchRows > 0) {
277
+ const stmt = this.statement;
278
+ if (stmt.cursorId !== 0 && !stmt.requiresFullExecute && !this.parseOnly && !stmt.requiresDefine && !stmt.noPrefetch && !stmt.isDdl && !this.batchErrors) {
279
+ if (stmt.isQuery && this.options.prefetchRows > 0) {
280
280
  this.functionCode = constants.TNS_FUNC_REEXECUTE_AND_FETCH;
281
281
  } else {
282
282
  this.functionCode = constants.TNS_FUNC_REEXECUTE;
@@ -37,10 +37,12 @@ const PingMessage = require('./ping.js');
37
37
  const ProtocolMessage = require('./protocol.js');
38
38
  const RollbackMessage = require('./rollback.js');
39
39
  const SessionReleaseMessage = require('./sessionRelease.js');
40
+ const ConnectionCookieMessage = require('./connectionCookie.js');
40
41
 
41
42
  module.exports = {
42
43
  AuthMessage,
43
44
  CommitMessage,
45
+ ConnectionCookieMessage,
44
46
  DataTypeMessage,
45
47
  ExecuteMessage,
46
48
  FetchMessage,
@@ -50,26 +50,37 @@ class ProtocolMessage extends Message {
50
50
  buf.writeUInt8(0);
51
51
  }
52
52
 
53
- decode(buf) {
54
- let message_type = buf.readUInt8();
55
- if (message_type === constants.TNS_MSG_TYPE_PROTOCOL) {
56
- buf.skipBytes(2); // skip protocol array
57
- let x = buf.readUInt8();
58
- while (x !== 0) { // skip server banner
59
- x = buf.readUInt8();
60
- }
61
- buf.skipBytes(2); // character set ID
62
- buf.skipUB1(1); // skip server flags
63
- let num_elem = buf.readUInt16LE();
64
- if (num_elem > 0) { // skip elements
65
- buf.skipBytes(num_elem * 5);
66
- }
67
- let fdoLen = buf.readUInt16BE();
68
- let fdo = buf.readBytes(fdoLen);
69
- let ix = 6 + fdo[5] + fdo[6];
70
- buf.caps.nCharsetId = (fdo[ix + 3] << 8) + fdo[ix + 4];
71
- buf.caps.adjustForServerCompileCaps(buf.readBytesWithLength());
72
- buf.caps.adjustForServerRuntimeCaps(buf.readBytesWithLength());
53
+ processMessage(buf, messageType) {
54
+ if (messageType === constants.TNS_MSG_TYPE_PROTOCOL) {
55
+ this.processProtocolInfo(buf);
56
+ } else {
57
+ super.processMessage(buf, messageType);
58
+ }
59
+ }
60
+
61
+ processProtocolInfo(buf) {
62
+ this.serverVersion = buf.readUInt8();
63
+ buf.skipUB1();
64
+ this.serverBanner = buf.readNullTerminatedBytes(48);
65
+ buf.caps.charSetID = buf.readUInt16LE();
66
+ this.serverFlags = buf.readUInt8();
67
+ const num_elem = buf.readUInt16LE();
68
+ if (num_elem > 0) { // skip elements
69
+ buf.skipBytes(num_elem * 5);
70
+ }
71
+ const fdoLen = buf.readUInt16BE();
72
+ const fdo = buf.readBytes(fdoLen);
73
+ const ix = 6 + fdo[5] + fdo[6];
74
+ buf.caps.nCharsetId = (fdo[ix + 3] << 8) + fdo[ix + 4];
75
+ const serverCompileCaps = buf.readBytesWithLength();
76
+ if (serverCompileCaps) {
77
+ this.serverCompileCaps = Buffer.from(serverCompileCaps);
78
+ buf.caps.adjustForServerCompileCaps(this.serverCompileCaps);
79
+ }
80
+ const serverRunTimeCaps = buf.readBytesWithLength();
81
+ if (serverRunTimeCaps) {
82
+ this.serverRunTimeCaps = Buffer.from(serverRunTimeCaps);
83
+ buf.caps.adjustForServerRuntimeCaps(this.serverRunTimeCaps);
73
84
  }
74
85
  }
75
86
 
@@ -65,11 +65,12 @@ class MessageWithData extends Message {
65
65
  processMessage(buf, messageType) {
66
66
  if (messageType === constants.TNS_MSG_TYPE_DESCRIBE_INFO) {
67
67
  buf.skipBytesChunked();
68
+ const prevQueryVars = this.statement.queryVars;
68
69
  this.statement.queryVars = [];
69
70
  this.statement.numQueryVars = 0;
70
71
  this.statement.bufferRowCount = 0;
71
72
  this.statement.bufferRowIndex = 0;
72
- this.processDescribeInfo(buf, this.resultSet);
73
+ this.processDescribeInfo(buf, this.resultSet, prevQueryVars);
73
74
  this.outVariables = this.statement.queryVars;
74
75
  } else if (messageType === constants.TNS_MSG_TYPE_ROW_HEADER) {
75
76
  this.processRowHeader(buf);
@@ -123,7 +124,22 @@ class MessageWithData extends Message {
123
124
  }
124
125
  }
125
126
 
126
- processDescribeInfo(buf, resultSet) {
127
+ //---------------------------------------------------------------------------
128
+ // If we have fetched this column earlier, we set that
129
+ // fetch type for the describe info variable received
130
+ // assuming the returned column order is same as previous.
131
+ //---------------------------------------------------------------------------
132
+ _adjustFetchType(pVar, cVar) {
133
+ if ((cVar.fetchInfo.dbType._oraTypeNum === constants.TNS_DATA_TYPE_CLOB
134
+ && pVar.fetchInfo.fetchType._oraTypeNum === constants.TNS_DATA_TYPE_LONG)
135
+ || (cVar.fetchInfo.dbType._oraTypeNum === constants.TNS_DATA_TYPE_BLOB
136
+ && pVar.fetchInfo.fetchType._oraTypeNum === constants.TNS_DATA_TYPE_LONG_RAW)) {
137
+ cVar.type = pVar.fetchInfo.fetchType;
138
+ cVar.maxSize = pVar.maxSize;
139
+ }
140
+ }
141
+
142
+ processDescribeInfo(buf, resultSet, prevQueryVars) {
127
143
  const statement = resultSet.statement;
128
144
  buf.skipUB4(); // max row size
129
145
  statement.numQueryVars = buf.readUB4();
@@ -133,6 +149,9 @@ class MessageWithData extends Message {
133
149
  resultSet.metadata = [];
134
150
  for (let i = 0; i < statement.numQueryVars; i++) {
135
151
  const variable = this.processColumnInfo(buf, i + 1);
152
+ if (prevQueryVars && i < prevQueryVars.length) {
153
+ this._adjustFetchType(prevQueryVars[i], variable);
154
+ }
136
155
  statement.queryVars.push(variable);
137
156
  resultSet.metadata.push(variable.fetchInfo);
138
157
  }
@@ -257,8 +276,7 @@ class MessageWithData extends Message {
257
276
  buf.skipUB2(); // buffer length
258
277
  let numBytes = buf.readUB4();
259
278
  if (numBytes > 0) {
260
- buf.skipUB1(); // skip repeated length
261
- this.getBitVector(buf, numBytes);
279
+ this.bitVector = Buffer.from(buf.readBytesWithLength());
262
280
  }
263
281
  numBytes = buf.readUB4();
264
282
  if (numBytes > 0) {
@@ -267,28 +285,28 @@ class MessageWithData extends Message {
267
285
  }
268
286
 
269
287
  isDuplicateData(columnName) {
270
- if (this.bitVector === null || this.bitVector === undefined) {
288
+ if (!this.bitVector) {
271
289
  return false;
272
290
  }
273
- let byteNum = Math.floor(columnName / 8);
274
- let bitNum = columnName % 8;
291
+ const byteNum = Math.floor(columnName / 8);
292
+ const bitNum = columnName % 8;
275
293
  return (this.bitVector[byteNum] & (1 << bitNum)) === 0;
276
294
  }
277
295
 
278
296
  processRowData(buf) {
279
297
  let value;
280
- for (let [col, variable] of this.outVariables.entries()) {
298
+ for (const [col, variable] of this.outVariables.entries()) {
281
299
  if (variable.isArray) {
282
300
  variable.numElementsInArray = buf.readUB4();
283
- let values = new Array(variable.numElementsInArray).fill(null);
301
+ const values = new Array(variable.numElementsInArray).fill(null);
284
302
  for (let pos = 0; pos < variable.numElementsInArray; pos++) {
285
303
  value = this.processColumnData(buf, variable, pos);
286
304
  values[pos] = value;
287
305
  }
288
306
  variable.values[this.rowIndex] = values;
289
307
  } else if (this.statement.isReturning) {
290
- let numRows = buf.readUB4();
291
- let values = Array(numRows).fill(null);
308
+ const numRows = buf.readUB4();
309
+ const values = Array(numRows).fill(null);
292
310
  for (let j = 0; j < numRows; j++) {
293
311
  values[j] = this.processColumnData(buf, variable, j);
294
312
  }
@@ -331,7 +349,7 @@ class MessageWithData extends Message {
331
349
  }
332
350
  this.outVariables = [];
333
351
  for (let i = 0; i < numBinds; i++) { // bind directions
334
- let bindInfo = this.statement.bindInfoList[i];
352
+ const bindInfo = this.statement.bindInfoList[i];
335
353
  bindInfo.bindDir = buf.readUInt8();
336
354
  if (bindInfo.bindDir === constants.TNS_BIND_DIR_INPUT) {
337
355
  continue;
@@ -383,11 +401,11 @@ class MessageWithData extends Message {
383
401
  if (!this.inFetch) {
384
402
  colValue = buf.readStr(constants.CSFRM_IMPLICIT);
385
403
  } else {
386
- let numBytes = buf.readUInt8();
404
+ const numBytes = buf.readUInt8();
387
405
  if (isNullLength(numBytes)) {
388
406
  colValue = null;
389
407
  } else {
390
- let rowid = buf.readRowID();
408
+ const rowid = buf.readRowID();
391
409
  colValue = utils.encodeRowID(rowid);
392
410
  }
393
411
  }
@@ -406,7 +424,7 @@ class MessageWithData extends Message {
406
424
  if (colValue !== null)
407
425
  colValue = parseFloat(colValue);
408
426
  } else if (oraTypeNum === constants.TNS_DATA_TYPE_CURSOR) {
409
- let numBytes = buf.readUInt8();
427
+ const numBytes = buf.readUInt8();
410
428
  if (isNullLength(numBytes)) {
411
429
  colValue = null;
412
430
  } else {
@@ -425,7 +443,7 @@ class MessageWithData extends Message {
425
443
  } else if (oraTypeNum === constants.TNS_DATA_TYPE_BOOLEAN) {
426
444
  colValue = buf.readBool();
427
445
  } else if (oraTypeNum === constants.TNS_DATA_TYPE_CLOB || oraTypeNum === constants.TNS_DATA_TYPE_BLOB) {
428
- let bvalue = buf.readUB4();
446
+ const bvalue = buf.readUB4();
429
447
  if (bvalue > 0) { // Non Null data in column
430
448
  colValue = new ThinLobImpl();
431
449
  const length = buf.readUB8();
@@ -497,25 +515,15 @@ class MessageWithData extends Message {
497
515
  buf.skip(numBytes);
498
516
  }
499
517
  if (this.arrayDmlRowCounts) {
500
- let numRows = buf.readUB4();
501
- let rowCounts = this.options.dmlRowCounts = [];
518
+ const numRows = buf.readUB4();
519
+ const rowCounts = this.options.dmlRowCounts = [];
502
520
  for (let i = 0; i < numRows; i++) {
503
- let rowCount = buf.readUB8();
521
+ const rowCount = buf.readUB8();
504
522
  rowCounts.push(rowCount);
505
523
  }
506
524
  }
507
525
  }
508
526
 
509
- process(buf) {
510
- this.bitVector = this.savedBitVector;
511
- super.process(buf);
512
- }
513
-
514
- savePoint(buf) {
515
- this.savedBitVector = this.bitVector;
516
- super.savePoint(buf);
517
- }
518
-
519
527
  async postProcess() {
520
528
  if (this.outVariables) {
521
529
  for (const variable of this.outVariables) {
@@ -546,8 +554,10 @@ class MessageWithData extends Message {
546
554
  variable.type = variable.fetchInfo.fetchType;
547
555
  variable.maxSize = constants.TNS_MAX_LONG_LENGTH;
548
556
  }
549
- resultSet.statement.requiresDefine = true;
550
- resultSet.statement.noPrefetch = true;
557
+ if (!resultSet.statement.noPrefetch) {
558
+ resultSet.statement.requiresDefine = true;
559
+ resultSet.statement.noPrefetch = true;
560
+ }
551
561
  }
552
562
  }
553
563
  }
@@ -580,10 +590,6 @@ class MessageWithData extends Message {
580
590
  if (this.statement.numQueryVars % 8 > 0) {
581
591
  numBytes += 1;
582
592
  }
583
- this.getBitVector(buf, numBytes);
584
- }
585
-
586
- getBitVector(buf, numBytes) {
587
593
  this.bitVector = Buffer.from(buf.readBytes(numBytes));
588
594
  }
589
595
 
@@ -651,15 +657,15 @@ class MessageWithData extends Message {
651
657
  const objType = variable.objType;
652
658
  buf.writeUB4(objType.oid.length);
653
659
  buf.writeBytesWithLength(objType.oid);
654
- buf.writeUB4(objType.version);
660
+ buf.writeUB2(objType.version);
655
661
  } else {
656
662
  buf.writeUB4(0); // OID
657
- buf.writeUB4(0); // version
663
+ buf.writeUB2(0); // version
658
664
  }
659
665
  if (variable.type._csfrm !== 0) {
660
- buf.writeUB4(constants.TNS_CHARSET_UTF8);
666
+ buf.writeUB2(constants.TNS_CHARSET_UTF8);
661
667
  } else {
662
- buf.writeUB4(0);
668
+ buf.writeUB2(0);
663
669
  }
664
670
  buf.writeUInt8(variable.type._csfrm);
665
671
  buf.writeUB4(lobPrefetchLength); // max chars (LOB prefetch)
@@ -670,14 +676,14 @@ class MessageWithData extends Message {
670
676
  }
671
677
 
672
678
  writeBindParamsRow(buf, params, pos) {
673
- let offset = this.offset;
679
+ const offset = this.offset;
674
680
  let foundLong = false;
675
681
  for (const bindInfo of params) {
676
682
  if (bindInfo.isReturnBind)
677
683
  continue;
678
- let variable = bindInfo.bindVar;
684
+ const variable = bindInfo.bindVar;
679
685
  if (variable.isArray) {
680
- let numElements = variable.values.length;
686
+ const numElements = variable.values.length;
681
687
  buf.writeUB4(numElements);
682
688
  for (let i = 0; i < numElements; i++) {
683
689
  this.writeBindParamsColumn(buf, variable, variable.values[i]);
@@ -800,7 +806,7 @@ class MessageWithData extends Message {
800
806
  for (let i = 0; i < numResults; i++) {
801
807
  const numBytes = buf.readUInt8();
802
808
  buf.skipBytes(numBytes);
803
- let childResultSet = this.createCursorFromDescribe(buf);
809
+ const childResultSet = this.createCursorFromDescribe(buf);
804
810
  childResultSet.statement.cursorId = buf.readUB2();
805
811
  this.options.implicitResultSet.push(childResultSet);
806
812
  }
@@ -352,7 +352,7 @@ class OsonFieldNamesSegment extends GrowableBuffer {
352
352
  //---------------------------------------------------------------------------
353
353
  _examineNode(value) {
354
354
  if (Array.isArray(value)) {
355
- for (let element of value) {
355
+ for (const element of value) {
356
356
  this._examineNode(element);
357
357
  }
358
358
  } else if (value && Array.isArray(value.fields)) {
@@ -418,7 +418,7 @@ class OsonTreeSegment extends GrowableBuffer {
418
418
  this._encodeContainer(constants.TNS_JSON_TYPE_ARRAY, value.length);
419
419
  let offsetsBufPos = 0;
420
420
  const offsetsBuf = this.reserveBytes(value.length * 4);
421
- for (let element of value) {
421
+ for (const element of value) {
422
422
  offsetsBuf.writeUInt32BE(this.pos, offsetsBufPos);
423
423
  offsetsBufPos += 4;
424
424
  this.encodeNode(element, fnamesSeg);
@@ -627,12 +627,12 @@ class OsonEncoder extends GrowableBuffer {
627
627
  this.writeUInt16BE(0);
628
628
 
629
629
  // write array of hash ids
630
- for (let fieldName of fnamesSeg.fieldNames) {
630
+ for (const fieldName of fnamesSeg.fieldNames) {
631
631
  this.writeUInt8(fieldName.hashId);
632
632
  }
633
633
 
634
634
  // write array of field name offsets
635
- for (let fieldName of fnamesSeg.fieldNames) {
635
+ for (const fieldName of fnamesSeg.fieldNames) {
636
636
  if (fnamesSeg.pos < 65536) {
637
637
  this.writeUInt16BE(fieldName.offset);
638
638
  } else {