oracledb 6.9.0 → 7.0.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 (100) hide show
  1. package/LICENSE.txt +1 -1
  2. package/NOTICE.txt +1 -1
  3. package/README.md +9 -9
  4. package/build/Release/oracledb-7.0.0-darwin-arm64.node +0 -0
  5. package/build/Release/oracledb-7.0.0-darwin-arm64.node-buildinfo.txt +1 -0
  6. package/build/Release/oracledb-7.0.0-js-buildinfo.txt +1 -0
  7. package/build/Release/oracledb-7.0.0-linux-arm64.node +0 -0
  8. package/build/Release/oracledb-7.0.0-linux-arm64.node-buildinfo.txt +1 -0
  9. package/build/Release/oracledb-7.0.0-linux-x64.node +0 -0
  10. package/build/Release/oracledb-7.0.0-linux-x64.node-buildinfo.txt +1 -0
  11. package/build/Release/oracledb-7.0.0-win32-x64.node +0 -0
  12. package/build/Release/oracledb-7.0.0-win32-x64.node-buildinfo.txt +1 -0
  13. package/eslint.config.js +39 -0
  14. package/lib/aqDeqOptions.js +18 -1
  15. package/lib/aqQueue.js +10 -6
  16. package/lib/connection.js +418 -39
  17. package/lib/dbObject.js +25 -4
  18. package/lib/endUserSecurityContext.js +176 -0
  19. package/lib/errors.js +99 -8
  20. package/lib/impl/aqDeqOptions.js +10 -1
  21. package/lib/impl/connection.js +76 -2
  22. package/lib/impl/datahandlers/buffer.js +68 -5
  23. package/lib/impl/datahandlers/oson.js +7 -2
  24. package/lib/impl/datahandlers/vector.js +25 -5
  25. package/lib/impl/lob.js +9 -0
  26. package/lib/impl/parserHelpers.js +443 -0
  27. package/lib/impl/resultset.js +1 -1
  28. package/lib/impl/sodaDocument.js +5 -14
  29. package/lib/lob.js +27 -14
  30. package/lib/obfuscation.js +97 -0
  31. package/lib/oracledb.js +163 -49
  32. package/lib/parser.js +204 -0
  33. package/lib/pipeline.js +113 -0
  34. package/lib/pool.js +203 -147
  35. package/lib/poolStatistics.js +1 -1
  36. package/lib/resultset.js +42 -21
  37. package/lib/settings.js +1 -0
  38. package/lib/sodaCollection.js +12 -8
  39. package/lib/sodaDatabase.js +35 -8
  40. package/lib/sodaDocument.js +24 -6
  41. package/lib/sodaOperation.js +7 -6
  42. package/lib/thin/aq.js +475 -0
  43. package/lib/thin/connection.js +518 -54
  44. package/lib/thin/dbObject.js +7 -1
  45. package/lib/thin/lob.js +20 -1
  46. package/lib/thin/pool.js +42 -62
  47. package/lib/thin/protocol/capabilities.js +21 -4
  48. package/lib/thin/protocol/constants.js +143 -2
  49. package/lib/thin/protocol/encryptDecrypt.js +45 -10
  50. package/lib/thin/protocol/messages/aqArray.js +238 -0
  51. package/lib/thin/protocol/messages/aqBase.js +305 -0
  52. package/lib/thin/protocol/messages/aqDeq.js +164 -0
  53. package/lib/thin/protocol/messages/aqEnq.js +135 -0
  54. package/lib/thin/protocol/messages/auth.js +18 -28
  55. package/lib/thin/protocol/messages/base.js +245 -4
  56. package/lib/thin/protocol/messages/dataType.js +8 -3
  57. package/lib/thin/protocol/messages/directPathLoadStream.js +377 -0
  58. package/lib/thin/protocol/messages/directPathOp.js +65 -0
  59. package/lib/thin/protocol/messages/directPathPrepare.js +158 -0
  60. package/lib/thin/protocol/messages/endPipeline.js +56 -0
  61. package/lib/thin/protocol/messages/execute.js +9 -7
  62. package/lib/thin/protocol/messages/index.js +9 -1
  63. package/lib/thin/protocol/messages/protocol.js +2 -2
  64. package/lib/thin/protocol/messages/withData.js +10 -142
  65. package/lib/thin/protocol/packet.js +120 -28
  66. package/lib/thin/protocol/protocol.js +110 -25
  67. package/lib/thin/protocol/utils.js +1 -26
  68. package/lib/thin/resultSet.js +13 -19
  69. package/lib/thin/sqlnet/ezConnectResolver.js +2 -2
  70. package/lib/thin/sqlnet/networkSession.js +63 -41
  71. package/lib/thin/sqlnet/ntTcp.js +24 -0
  72. package/lib/thin/sqlnet/nvStrToNvPair.js +50 -25
  73. package/lib/thin/sqlnet/packet.js +25 -4
  74. package/lib/thin/sqlnet/paramParser.js +10 -7
  75. package/lib/thin/statementCache.js +2 -4
  76. package/lib/traceHandler.js +59 -2
  77. package/lib/transformer.js +8 -3
  78. package/lib/types.js +36 -22
  79. package/lib/util.js +6 -19
  80. package/lib/version.js +3 -3
  81. package/package/install.js +5 -5
  82. package/package/prunebinaries.js +1 -1
  83. package/package.json +1 -1
  84. package/plugins/configProviders/awsCommon.js +125 -0
  85. package/plugins/configProviders/awss3/index.js +138 -0
  86. package/plugins/configProviders/awssecretsmanager/index.js +147 -0
  87. package/plugins/configProviders/azure/index.js +7 -5
  88. package/plugins/token/extensionAzure/index.js +0 -1
  89. package/plugins/token/extensionOci/index.js +0 -1
  90. package/build/Release/oracledb-6.9.0-darwin-arm64.node +0 -0
  91. package/build/Release/oracledb-6.9.0-darwin-arm64.node-buildinfo.txt +0 -1
  92. package/build/Release/oracledb-6.9.0-darwin-x64.node +0 -0
  93. package/build/Release/oracledb-6.9.0-darwin-x64.node-buildinfo.txt +0 -1
  94. package/build/Release/oracledb-6.9.0-js-buildinfo.txt +0 -1
  95. package/build/Release/oracledb-6.9.0-linux-arm64.node +0 -0
  96. package/build/Release/oracledb-6.9.0-linux-arm64.node-buildinfo.txt +0 -1
  97. package/build/Release/oracledb-6.9.0-linux-x64.node +0 -0
  98. package/build/Release/oracledb-6.9.0-linux-x64.node-buildinfo.txt +0 -1
  99. package/build/Release/oracledb-6.9.0-win32-x64.node +0 -0
  100. package/build/Release/oracledb-6.9.0-win32-x64.node-buildinfo.txt +0 -1
@@ -1,4 +1,4 @@
1
- // Copyright (c) 2022, 2023, Oracle and/or its affiliates.
1
+ // Copyright (c) 2022, 2026, Oracle and/or its affiliates.
2
2
 
3
3
  //-----------------------------------------------------------------------------
4
4
  //
@@ -28,8 +28,43 @@
28
28
 
29
29
  const { Buffer } = require('buffer');
30
30
  const crypto = require('crypto');
31
+ const errors = require('../../errors.js');
32
+
33
+ const MAX_PBKDF2_ITERATIONS = 100_000;
34
+
35
+ function getPBKDF2Iterations(sessionData, key) {
36
+ const iterations = Number(sessionData[key]);
37
+ if (!Number.isInteger(iterations) || iterations < 1 ||
38
+ iterations > MAX_PBKDF2_ITERATIONS) {
39
+ errors.throwErr(errors.ERR_INVALID_SERVER_RESPONSE);
40
+ }
41
+ return iterations;
42
+ }
43
+
44
+ function resolveCipherKey(key) {
45
+ if (!Buffer.isBuffer(key)) {
46
+ errors.throwErr(errors.ERR_INTERNAL,
47
+ 'Encryption key must be a Buffer');
48
+ }
49
+
50
+ let cipherAlg;
51
+ switch (key.length) {
52
+ case 16:
53
+ cipherAlg = 'aes-128-cbc';
54
+ break;
55
+ case 24:
56
+ cipherAlg = 'aes-192-cbc';
57
+ break;
58
+ case 32:
59
+ cipherAlg = 'aes-256-cbc';
60
+ break;
61
+ default:
62
+ errors.throwErr(errors.ERR_UNSUPPORTED_KEY_LENGTH, key.length);
63
+ }
64
+
65
+ return cipherAlg;
66
+ }
31
67
 
32
- let algorithm = 'aes-256-cbc';
33
68
  const _appendBuffer = Buffer.from([0x00, 0x01]);
34
69
 
35
70
  /**
@@ -40,9 +75,10 @@ class EncryptDecrypt {
40
75
 
41
76
  // Key length is dependent on the algorithm. In this case for aes192, it is
42
77
  // 24 bytes (192 bits).
43
- _decrypt(key, val) {
78
+ decrypt(key, val) {
44
79
  const iv = Buffer.alloc(16, 0); // Initialization vector, same is used in server
45
- const decipher = crypto.createDecipheriv(algorithm, key, iv);
80
+ const cipherAlg = resolveCipherKey(key);
81
+ const decipher = crypto.createDecipheriv(cipherAlg, key, iv);
46
82
  decipher.setAutoPadding(false);
47
83
  let decrypted = decipher.update(val);
48
84
  decrypted = Buffer.concat([decrypted, decipher.final()]);
@@ -61,7 +97,8 @@ class EncryptDecrypt {
61
97
  val = Buffer.concat([val, nv]);
62
98
  }
63
99
  }
64
- const cipher = crypto.createCipheriv(algorithm, key, iv);
100
+ const cipherAlg = resolveCipherKey(key);
101
+ const cipher = crypto.createCipheriv(cipherAlg, key, iv);
65
102
  let encrypted = cipher.update(val);
66
103
  encrypted = Buffer.concat([encrypted, cipher.final()]);
67
104
  if (!padding) {
@@ -108,13 +145,11 @@ class EncryptDecrypt {
108
145
 
109
146
  const verifierData = Buffer.from(sessionData['AUTH_VFR_DATA'], 'hex');
110
147
  const encodedServerKey = Buffer.from(sessionData['AUTH_SESSKEY'], 'hex');
111
- let iterations = Number(sessionData['AUTH_PBKDF2_VGEN_COUNT']);
112
148
  const passwordBytes = Buffer.from(password, 'utf8');
113
149
  let passwordHash;
114
150
  let passwordKey;
115
151
 
116
152
  if (verifier11G) {
117
- algorithm = 'aes-192-cbc';
118
153
  keyLen = 24;
119
154
  hashAlg = 'sha1';
120
155
  const h = crypto.createHash(hashAlg);
@@ -124,9 +159,9 @@ class EncryptDecrypt {
124
159
  passwordHash = Buffer.alloc(ph.length + 4);
125
160
  ph.copy(passwordHash, 0, 0, ph.length);
126
161
  } else {
127
- algorithm = 'aes-256-cbc';
128
162
  const temp = Buffer.from('AUTH_PBKDF2_SPEEDY_KEY', 'utf8');
129
163
  const salt = Buffer.concat([verifierData, temp]);
164
+ const iterations = getPBKDF2Iterations(sessionData, 'AUTH_PBKDF2_VGEN_COUNT');
130
165
  passwordKey = crypto.pbkdf2Sync(passwordBytes, salt, iterations, 64, 'sha512');
131
166
  const h = crypto.createHash(hashAlg);
132
167
  h.update(passwordKey);
@@ -138,7 +173,7 @@ class EncryptDecrypt {
138
173
  if (newPassword) {
139
174
  newPasswordBytes = Buffer.from(newPassword, 'utf8');
140
175
  }
141
- const sessionKeyParta = this._decrypt(passwordHash, encodedServerKey);
176
+ const sessionKeyParta = this.decrypt(passwordHash, encodedServerKey);
142
177
  const sessionKeyPartb = Buffer.alloc(sessionKeyParta.length);
143
178
  crypto.randomFillSync(sessionKeyPartb);
144
179
  const encodedClientKey = this._encrypt(passwordHash, sessionKeyPartb);
@@ -155,7 +190,7 @@ class EncryptDecrypt {
155
190
  } else {
156
191
  authObj.sessionKey = encodedClientKey.slice().toString('hex').toUpperCase().slice(0, 64);
157
192
  const mixingSalt = Buffer.from(sessionData['AUTH_PBKDF2_CSK_SALT'], 'hex');
158
- iterations = Number(sessionData['AUTH_PBKDF2_SDER_COUNT']);
193
+ const iterations = getPBKDF2Iterations(sessionData, 'AUTH_PBKDF2_SDER_COUNT');
159
194
  const partABKey = Buffer.concat([sessionKeyPartb.slice(0, keyLen), sessionKeyParta.slice(0, keyLen)]);
160
195
  const partABKeyStr = partABKey.toString('hex').toUpperCase();
161
196
  const partABKeyBuffer = Buffer.from(partABKeyStr, 'utf8');
@@ -0,0 +1,238 @@
1
+ // Copyright (c) 2025, 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
+ //-----------------------------------------------------------------------------
28
+ // aqArray.js
29
+ //
30
+ // This file defines the messages that are sent to the database and the
31
+ // responses that are received by the client for enqueuing and dequeuing
32
+ // an array of AQ messages.
33
+ //-----------------------------------------------------------------------------
34
+
35
+ 'use strict';
36
+
37
+ const AqBaseMessage = require("./aqBase.js");
38
+ const constants = require("../constants.js");
39
+ const errors = require("../../../errors.js");
40
+
41
+ class AqArrayMessage extends AqBaseMessage {
42
+
43
+ constructor(connImpl) {
44
+ super(connImpl);
45
+ this.functionCode = constants.TNS_FUNC_ARRAY_AQ;
46
+ this.numIters = 0;
47
+ this.propsImpls = [];
48
+ this.noMsgFound = false;
49
+ }
50
+
51
+ //--------------------------------------------------------------------------
52
+ // processReturnParameter()
53
+ //
54
+ // Process the return parameters of the AQ array enqueue/dequeue request.
55
+ // We recieve all the msg details in deq and in case of enq the msgIds.
56
+ //--------------------------------------------------------------------------
57
+ processReturnParameter(buf) {
58
+ const numIters = buf.readUB4();
59
+ for (let i = 0; i < numIters; i++) {
60
+ const propsImpl = this.propsImpls[i];
61
+ let temp16 = buf.readUB2();
62
+ if (temp16 > 0) {
63
+ buf.skipUB1();
64
+ this._processMsgProps(buf, propsImpl);
65
+ }
66
+ propsImpl.recipients = this._processRecipients(buf);
67
+ temp16 = buf.readUB2();
68
+ if (temp16 > 0) {
69
+ propsImpl.payload = this._processPayload(buf);
70
+ }
71
+ const msgId = buf.readBytesAndLength();// msgIds array
72
+ if (this.operation === constants.TNS_AQ_ARRAY_ENQ) {
73
+ for (let j = 0; j < this.propsImpls.length; j++) {
74
+ this.propsImpls[j].msgId = Buffer.from(msgId.slice(j * 16, (j + 1) * 16));
75
+ }
76
+ } else {
77
+ propsImpl.msgId = Buffer.from(msgId);
78
+ }
79
+ temp16 = buf.readUB2(); // extensions len
80
+ if (temp16 > 0) {
81
+ errors.throwErr(errors.ERR_NOT_IMPLEMENTED);
82
+ }
83
+ buf.skipUB2(); // output ack
84
+ }
85
+ if (this.operation === constants.TNS_AQ_ARRAY_ENQ) {
86
+ this.numIters = buf.readUB4();
87
+ } else {
88
+ this.numIters = numIters;
89
+ }
90
+ }
91
+
92
+ //--------------------------------------------------------------------------
93
+ // _writeArrayDeq()
94
+ //
95
+ // Writes to the buffer the fields specific to the array dequeue of AQ
96
+ // messages.
97
+ //--------------------------------------------------------------------------
98
+ _writeArrayDeq(buf) {
99
+ let consumerNameBytes = null;
100
+ let correlationBytes = null;
101
+ let conditionBytes = null;
102
+ const queueNameBytes = Buffer.from(this.queueImpl.name);
103
+ const deliveryMode = this.deqOptionsImpl.deliveryMode;
104
+ let flags = 0;
105
+
106
+ if (deliveryMode === constants.TNS_AQ_MSG_BUFFERED) {
107
+ flags |= constants.TNS_KPD_AQ_BUFMSG;
108
+ } else if (deliveryMode === constants.TNS_AQ_MSG_PERSISTENT_OR_BUFFERED) {
109
+ flags |= constants.TNS_KPD_AQ_EITHER;
110
+ }
111
+
112
+ if (this.deqOptionsImpl.consumerName) {
113
+ consumerNameBytes = Buffer.from(this.deqOptionsImpl.consumerName, 'utf-8');
114
+ }
115
+ if (this.deqOptionsImpl.condition) {
116
+ conditionBytes = Buffer.from(this.deqOptionsImpl.condition, 'utf-8');
117
+ }
118
+ if (this.deqOptionsImpl.correlation) {
119
+ correlationBytes = Buffer.from(this.deqOptionsImpl.correlation, 'utf-8');
120
+ }
121
+
122
+ for (const propsImpl of this.propsImpls) {
123
+ buf.writeUB4(queueNameBytes.length);
124
+ buf.writeBytesWithLength(queueNameBytes);
125
+ this._writeMsgProps(buf, propsImpl);
126
+ buf.writeUB4(0); // num recipients
127
+ this._writeValueWithLength(buf, consumerNameBytes);
128
+ buf.writeSB4(this.deqOptionsImpl.mode);
129
+ buf.writeSB4(this.deqOptionsImpl.navigation);
130
+ buf.writeSB4(this.deqOptionsImpl.visibility);
131
+ buf.writeSB4(this.deqOptionsImpl.wait);
132
+ this._writeValueWithLength(buf, this.deqOptionsImpl.msgid);
133
+ this._writeValueWithLength(buf, correlationBytes);
134
+ this._writeValueWithLength(buf, conditionBytes);
135
+ buf.writeUB4(0); // extensions
136
+ buf.writeUB4(0); // rel msg id
137
+ buf.writeSB4(0); // seq deviation
138
+ buf.writeUB4(16); // toid length
139
+ buf.writeBytesWithLength(this.queueImpl.payloadToid);
140
+ buf.writeUB2(constants.TNS_AQ_MESSAGE_VERSION);
141
+ buf.writeUB4(0); // payload length
142
+ buf.writeUB4(0); // raw pay length
143
+ buf.writeUB4(0);
144
+ buf.writeUB4(flags); // deliveryMode flag
145
+ buf.writeUB4(0); // extensions len
146
+ buf.writeUB4(0); // source seq len
147
+ }
148
+ }
149
+
150
+ //--------------------------------------------------------------------------
151
+ // _writeArrayEnq()
152
+ //
153
+ // Writes input parameters in case of array enqueue.
154
+ //--------------------------------------------------------------------------
155
+ _writeArrayEnq(buf) {
156
+ const queueNameBytes = Buffer.from(this.queueImpl.name);
157
+ const deliveryMode = this.enqOptionsImpl.deliveryMode;
158
+ let flags = 0;
159
+
160
+ if (deliveryMode === constants.TNS_AQ_MSG_BUFFERED) {
161
+ flags |= constants.TNS_KPD_AQ_BUFMSG;
162
+ } else if (deliveryMode === constants.TNS_AQ_MSG_PERSISTENT_OR_BUFFERED) {
163
+ flags |= constants.TNS_KPD_AQ_EITHER;
164
+ }
165
+
166
+ buf.writeUB4(0); // rel msgid len
167
+ buf.writeUInt8(constants.TNS_MSG_TYPE_ROW_HEADER);
168
+ buf.writeUB4(queueNameBytes.length);
169
+ buf.writeBytesWithLength(queueNameBytes);
170
+ buf.writeBytes(this.queueImpl.payloadToid);
171
+ buf.writeUB2(constants.TNS_AQ_MESSAGE_VERSION);
172
+ buf.writeUB4(flags);
173
+
174
+ for (const propsImpl of this.propsImpls) {
175
+ buf.writeUInt8(constants.TNS_MSG_TYPE_ROW_DATA);
176
+ buf.writeUB4(flags); // aqi flags
177
+ this._writeMsgProps(buf, propsImpl);
178
+ if (propsImpl.recipients === null || propsImpl.recipients.length === 0) {
179
+ buf.writeUB4(0); // num recipients
180
+ } else {
181
+ buf.writeUB4(3 * propsImpl.recipients.length);
182
+ this._writeRecipients(buf, propsImpl);
183
+ }
184
+ buf.writeSB4(this.enqOptionsImpl.visibility);
185
+ buf.writeUB4(0); // relative msg id
186
+ buf.writeSB4(0); // seq deviation
187
+ if (!this.queueImpl.payloadTypeClass && !this.queueImpl.isJson) {
188
+ buf.writeUB4(propsImpl.payload.length);
189
+ }
190
+ this._writePayload(buf, propsImpl);
191
+ }
192
+ buf.writeUInt8(constants.TNS_MSG_TYPE_STATUS);
193
+ }
194
+
195
+ //--------------------------------------------------------------------------
196
+ // _writeMessageBody()
197
+ //
198
+ // Writes the body of the message to the buffer.
199
+ //--------------------------------------------------------------------------
200
+ encode(buf) {
201
+ this.writeFunctionHeader(buf);
202
+ if (this.operation === constants.TNS_AQ_ARRAY_ENQ) {
203
+ buf.writeUInt8(0); // input params
204
+ buf.writeUB4(0); // length
205
+ } else {
206
+ buf.writeUInt8(1);
207
+ buf.writeUB4(this.numIters);
208
+ }
209
+ buf.writeUB4(constants.TNS_AQ_ARRAY_FLAGS_RETURN_MESSAGE_ID);
210
+ if (this.operation === constants.TNS_AQ_ARRAY_ENQ) {
211
+ buf.writeUInt8(1); // output params
212
+ buf.writeUInt8(0); // length
213
+ } else {
214
+ buf.writeUInt8(1);
215
+ buf.writeUInt8(1);
216
+ }
217
+ buf.writeSB4(this.operation);
218
+ if (this.operation === constants.TNS_AQ_ARRAY_ENQ) {
219
+ buf.writeUInt8(1); // num iters (pointer)
220
+ } else {
221
+ buf.writeUInt8(0);
222
+ }
223
+ if (buf.caps.ttcFieldVersion >= constants.TNS_CCAP_FIELD_VERSION_21_1) {
224
+ buf.writeUB4(0xffff); // shard id
225
+ }
226
+ if (this.operation === constants.TNS_AQ_ARRAY_ENQ) {
227
+ buf.writeUB4(this.numIters);
228
+ }
229
+ if (this.operation === constants.TNS_AQ_ARRAY_ENQ) {
230
+ this._writeArrayEnq(buf);
231
+ } else {
232
+ this._writeArrayDeq(buf);
233
+ }
234
+ }
235
+
236
+ }
237
+
238
+ module.exports = AqArrayMessage;
@@ -0,0 +1,305 @@
1
+ // Copyright (c) 2025, 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
+ //-----------------------------------------------------------------------------
28
+ // aqBase.js
29
+ //
30
+ // This file defines the base class for messages that are sent to the
31
+ // database and the responses that are received by the client for enqueuing and
32
+ // dequeuing AQ messages.
33
+ //-----------------------------------------------------------------------------
34
+
35
+ 'use strict';
36
+
37
+ const constants = require("../constants.js");
38
+ const errors = require("../../../errors.js");
39
+ const BaseMessage = require("./base.js");
40
+ const { ThinDbObjectImpl } = require("../../dbObject.js");
41
+ const oson = require('../../../impl/datahandlers/oson.js');
42
+
43
+ class AqBaseMessage extends BaseMessage {
44
+
45
+ constructor(connImpl) {
46
+ super(connImpl);
47
+ this.queueImpl = null;
48
+ this.deqOptionsImpl = null;
49
+ this.enqOptionsImpl = null;
50
+ this.noMsgFound = false;
51
+ }
52
+
53
+ //--------------------------------------------------------------------------
54
+ // _processDate()
55
+ //
56
+ // Processes a date found in the buffer.
57
+ //--------------------------------------------------------------------------
58
+ _processDate(buf) {
59
+ const numBytes = buf.readUB4();
60
+ if (numBytes > 0)
61
+ return buf.readOracleDate(true);
62
+ }
63
+
64
+ //--------------------------------------------------------------------------
65
+ // _processErrorInfo()
66
+ //
67
+ // Process error information from the buffer. If the error that indicates
68
+ // that no messages were received is detected, the error is cleared and
69
+ // the flag set so that the dequeue can handle that case.
70
+ //--------------------------------------------------------------------------
71
+ processErrorInfo(buf) {
72
+ super.processErrorInfo(buf);
73
+ if (this.errorInfo.num === constants.TNS_ERR_NO_MESSAGES_FOUND) {
74
+ this.errorInfo.num = 0;
75
+ this.errorOccurred = false;
76
+ this.noMsgFound = true;
77
+ }
78
+ }
79
+
80
+ //--------------------------------------------------------------------------
81
+ // _processExtensions()
82
+ //
83
+ // Processes extensions to the message property object returned by the
84
+ // database.
85
+ //--------------------------------------------------------------------------
86
+ _processExtensions(buf, propsImpl) {
87
+ const numExtensions = buf.readUB4();
88
+ if (numExtensions > 0) {
89
+ buf.skipUB1();
90
+ for (let i = 0; i < numExtensions; i++) {
91
+ const textValue = buf.readBytesAndLength();
92
+ const binaryValue = buf.readBytesAndLength();
93
+ const value = textValue || binaryValue;
94
+ const keyword = buf.readUB2();
95
+ if (value) {
96
+ if (keyword === constants.TNS_AQ_EXT_KEYWORD_AGENT_NAME) {
97
+ propsImpl.senderAgentName = value;
98
+ } else if (keyword === constants.TNS_AQ_EXT_KEYWORD_AGENT_ADDRESS) {
99
+ propsImpl.senderAgentAddress = value;
100
+ } else if (keyword === constants.TNS_AQ_EXT_KEYWORD_AGENT_PROTOCOL) {
101
+ propsImpl.senderAgentProtocol = value[0];
102
+ } else if (keyword === constants.TNS_AQ_EXT_KEYWORD_ORIGINAL_MSGID) {
103
+ propsImpl.originalMsgId = value;
104
+ }
105
+ }
106
+ }
107
+ }
108
+ }
109
+
110
+ //--------------------------------------------------------------------------
111
+ // _processMsgId()
112
+ //
113
+ // Reads a message id from the buffer and returns it.
114
+ //--------------------------------------------------------------------------
115
+ _processMsgId(buf) {
116
+ return Buffer.from(buf.readBytes(constants.TNS_AQ_MESSAGE_ID_LENGTH));
117
+ }
118
+
119
+ //--------------------------------------------------------------------------
120
+ // _processMsgProps()
121
+ //
122
+ // Processes a message property object returned by the database.
123
+ //--------------------------------------------------------------------------
124
+ _processMsgProps(buf, propsImpl) {
125
+ propsImpl.priority = buf.readSB4();
126
+ propsImpl.delay = buf.readSB4();
127
+ propsImpl.expiration = buf.readSB4();
128
+ propsImpl.correlation = buf.readStrAndLength();
129
+ propsImpl.numAttempts = buf.readSB4();
130
+ propsImpl.exceptionQueue = buf.readStrAndLength();
131
+ propsImpl.state = buf.readSB4();
132
+ propsImpl.enqTime = this._processDate(buf);
133
+ propsImpl.enqTxnId = buf.readBytesAndLength();
134
+ this._processExtensions(buf, propsImpl);
135
+ const temp32 = buf.readUB4(); // user properties
136
+ if (temp32 > 0) {
137
+ errors.throwErr(errors.ERR_NOT_IMPLEMENTED);
138
+ }
139
+ buf.skipUB4(); // csn
140
+ buf.skipUB4(); // dsn
141
+ const flags = buf.readUB4();
142
+ if (flags === constants.TNS_KPD_AQ_BUFMSG) {
143
+ propsImpl.deliveryMode = constants.TNS_AQ_MSG_BUFFERED;
144
+ } else {
145
+ propsImpl.deliveryMode = constants.TNS_AQ_MSG_PERSISTENT;
146
+ }
147
+ if (buf.caps.ttcFieldVersion >= constants.TNS_CCAP_FIELD_VERSION_21_1) {
148
+ buf.skipUB4(); // shard number
149
+ }
150
+ }
151
+
152
+ //--------------------------------------------------------------------------
153
+ // _processPayload()
154
+ //
155
+ // Processes the payload for an enqueued message returned by the database.
156
+ //--------------------------------------------------------------------------
157
+ _processPayload(buf) {
158
+ const payloadData = buf.readDbObject();
159
+ if (this.queueImpl.payloadTypeClass) {
160
+ const obj = new this.queueImpl.payloadTypeClass();
161
+ const objImpl = new ThinDbObjectImpl(this.queueImpl.payloadTypeClass,
162
+ payloadData.packedData);
163
+ if (payloadData) {
164
+ objImpl.toid = payloadData.toid;
165
+ objImpl.oid = payloadData.oid;
166
+ }
167
+ obj._impl = objImpl;
168
+ return obj;
169
+ } else {
170
+ if (payloadData.packedData) {
171
+ const payload = Buffer.from(payloadData.packedData.slice(4));
172
+ if (this.queueImpl.isJson) {
173
+ const decoder = new oson.OsonDecoder(payload);
174
+ return decoder.decode();
175
+ }
176
+ return payload;
177
+ } else if (!this.queueImpl.isJson) {
178
+ return Buffer.alloc(0);
179
+ }
180
+ }
181
+ }
182
+
183
+ //--------------------------------------------------------------------------
184
+ // _processRecipients()
185
+ //
186
+ // Process recipients for a message.
187
+ //--------------------------------------------------------------------------
188
+ _processRecipients(buf) {
189
+ const numRecipients = buf.readUB4();
190
+ if (numRecipients > 0)
191
+ errors.throwNotImplemented('aq recipients');
192
+ return [];
193
+ }
194
+
195
+ //--------------------------------------------------------------------------
196
+ // _writeMsgProps()
197
+ //
198
+ // Write a message property object to the buffer.
199
+ //--------------------------------------------------------------------------
200
+ _writeMsgProps(buf, propsImpl) {
201
+ buf.writeSB4(propsImpl.priority);
202
+ buf.writeSB4(propsImpl.delay);
203
+ buf.writeSB4(propsImpl.expiration);
204
+ this._writeValueWithLength(buf, propsImpl.correlation);
205
+ buf.writeUB4(0); // number of attempts
206
+ this._writeValueWithLength(buf, propsImpl.exceptionQueue);
207
+ buf.writeUB4(propsImpl.state);
208
+ buf.writeUB4(0); // enqueue time length
209
+ this._writeValueWithLength(buf, propsImpl.enqTxnId);
210
+ buf.writeUB4(4); // number of extensions
211
+ buf.writeUInt8(0x0e); // unknown extra byte
212
+
213
+ this._writeKeywordValuePair(buf, null, null,
214
+ constants.TNS_AQ_EXT_KEYWORD_AGENT_NAME);
215
+ this._writeKeywordValuePair(buf, null, null,
216
+ constants.TNS_AQ_EXT_KEYWORD_AGENT_ADDRESS);
217
+ this._writeKeywordValuePair(buf, null, Buffer.from([0x00]),
218
+ constants.TNS_AQ_EXT_KEYWORD_AGENT_PROTOCOL);
219
+ this._writeKeywordValuePair(buf, null, null,
220
+ constants.TNS_AQ_EXT_KEYWORD_ORIGINAL_MSGID);
221
+
222
+ buf.writeUB4(0); // user property
223
+ buf.writeUB4(0); // cscn
224
+ buf.writeUB4(0); // dscn
225
+ buf.writeUB4(0); // flags
226
+ if (buf.caps.ttcFieldVersion >= constants.TNS_CCAP_FIELD_VERSION_21_1) {
227
+ buf.writeUB4(0xffffffff); // shard id
228
+ }
229
+ }
230
+
231
+ //--------------------------------------------------------------------------
232
+ // _writePayload()
233
+ //
234
+ // Writes the payload of the message property object to the buffer.
235
+ //--------------------------------------------------------------------------
236
+ _writePayload(buf, propsImpl) {
237
+ if (this.queueImpl.isJson) {
238
+ buf.writeOson(propsImpl.payload, this.connection._osonMaxFieldNameSize,
239
+ false);
240
+ } else if (this.queueImpl.payloadTypeClass) {
241
+ buf.writeDbObject(propsImpl.payload);
242
+ } else {
243
+ buf.writeBytes(propsImpl.payload);
244
+ }
245
+ }
246
+
247
+ //--------------------------------------------------------------------------
248
+ // _writeRecipients()
249
+ //
250
+ // Write the recipient list of the message property object to the buffer.
251
+ //--------------------------------------------------------------------------
252
+ _writeRecipients(buf, propsImpl) {
253
+ let index = 0;
254
+ for (const recipient of propsImpl.recipients) {
255
+ this._writeKeywordValuePair(buf, recipient, null, index);
256
+ this._writeKeywordValuePair(buf, null, null, index + 1);
257
+ this._writeKeywordValuePair(buf, null, Buffer.from([0x00]), index + 2);
258
+ index += 3;
259
+ }
260
+ }
261
+
262
+ //--------------------------------------------------------------------------
263
+ // _writeValueWithLength()
264
+ //
265
+ // Write a string to the buffer, prefixed by a length.
266
+ //--------------------------------------------------------------------------
267
+ _writeValueWithLength(buf, value) {
268
+ if (!value) {
269
+ buf.writeUB4(0);
270
+ } else {
271
+ const valueBytes = Buffer.isBuffer(value) ?
272
+ value : Buffer.from(value, 'utf-8');
273
+ buf.writeUB4(valueBytes.length);
274
+ buf.writeBytesWithLength(valueBytes);
275
+ }
276
+ }
277
+
278
+ //--------------------------------------------------------------------------
279
+ // _writeKeywordValuePair()
280
+ //
281
+ // Writes a keyword value pair to the buffer.
282
+ //--------------------------------------------------------------------------
283
+ _writeKeywordValuePair(buf, textValue, binaryValue, keyword) {
284
+ let textValueBytes;
285
+ if (!textValue) {
286
+ buf.writeUB4(0);
287
+ } else {
288
+ textValueBytes = Buffer.from(textValue);
289
+ buf.writeUB4(textValueBytes.length);
290
+ buf.writeBytesWithLength(textValueBytes);
291
+ }
292
+ if (!binaryValue) {
293
+ buf.writeUB4(0);
294
+ } else {
295
+ buf.writeUB4(binaryValue.length);
296
+ buf.writeBytesWithLength(binaryValue);
297
+ }
298
+
299
+ buf.writeUB2(keyword);
300
+ }
301
+
302
+ }
303
+
304
+
305
+ module.exports = AqBaseMessage;