oracledb 6.5.0 → 6.6.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 (59) hide show
  1. package/README.md +2 -2
  2. package/build/Release/oracledb-6.6.0-darwin-arm64.node +0 -0
  3. package/build/Release/oracledb-6.6.0-darwin-arm64.node-buildinfo.txt +1 -0
  4. package/build/Release/oracledb-6.6.0-darwin-x64.node +0 -0
  5. package/build/Release/oracledb-6.6.0-darwin-x64.node-buildinfo.txt +1 -0
  6. package/build/Release/oracledb-6.6.0-js-buildinfo.txt +1 -0
  7. package/build/Release/oracledb-6.6.0-linux-arm64.node +0 -0
  8. package/build/Release/oracledb-6.6.0-linux-arm64.node-buildinfo.txt +1 -0
  9. package/build/Release/oracledb-6.6.0-linux-x64.node +0 -0
  10. package/build/Release/oracledb-6.6.0-linux-x64.node-buildinfo.txt +1 -0
  11. package/build/Release/oracledb-6.6.0-win32-x64.node +0 -0
  12. package/build/Release/oracledb-6.6.0-win32-x64.node-buildinfo.txt +1 -0
  13. package/examples/README.md +4 -0
  14. package/lib/configProviders/azure.js +167 -0
  15. package/lib/configProviders/base.js +99 -0
  16. package/lib/configProviders/ociobject.js +203 -0
  17. package/lib/connection.js +28 -12
  18. package/lib/constants.js +1 -0
  19. package/lib/errors.js +68 -1
  20. package/lib/impl/datahandlers/buffer.js +2 -2
  21. package/lib/impl/datahandlers/constants.js +3 -1
  22. package/lib/impl/datahandlers/vector.js +24 -9
  23. package/lib/impl/lob.js +27 -0
  24. package/lib/impl/resultset.js +26 -1
  25. package/lib/lob.js +52 -1
  26. package/lib/oracledb.js +61 -34
  27. package/lib/pool.js +7 -0
  28. package/lib/thin/connection.js +232 -16
  29. package/lib/thin/dbObject.js +4 -0
  30. package/lib/thin/lob.js +193 -1
  31. package/lib/thin/pool.js +15 -0
  32. package/lib/thin/protocol/capabilities.js +2 -0
  33. package/lib/thin/protocol/constants.js +30 -1
  34. package/lib/thin/protocol/messages/index.js +5 -1
  35. package/lib/thin/protocol/messages/lobOp.js +17 -5
  36. package/lib/thin/protocol/messages/transactionChangeState.js +99 -0
  37. package/lib/thin/protocol/messages/transactionSwitch.js +139 -0
  38. package/lib/thin/protocol/messages/withData.js +37 -8
  39. package/lib/thin/protocol/protocol.js +4 -0
  40. package/lib/thin/sqlnet/networkSession.js +2 -1
  41. package/lib/thin/sqlnet/packet.js +3 -1
  42. package/lib/thin/sqlnet/paramParser.js +87 -50
  43. package/lib/thin/sqlnet/sessionAtts.js +13 -1
  44. package/lib/thin/statement.js +4 -0
  45. package/lib/thin/statementCache.js +5 -0
  46. package/lib/transformer.js +1 -2
  47. package/lib/types.js +1 -1
  48. package/lib/util.js +62 -2
  49. package/lib/version.js +1 -1
  50. package/package.json +1 -1
  51. package/build/Release/oracledb-6.5.0-darwin-x64.node +0 -0
  52. package/build/Release/oracledb-6.5.0-darwin-x64.node-buildinfo.txt +0 -1
  53. package/build/Release/oracledb-6.5.0-js-buildinfo.txt +0 -1
  54. package/build/Release/oracledb-6.5.0-linux-arm64.node +0 -0
  55. package/build/Release/oracledb-6.5.0-linux-arm64.node-buildinfo.txt +0 -1
  56. package/build/Release/oracledb-6.5.0-linux-x64.node +0 -0
  57. package/build/Release/oracledb-6.5.0-linux-x64.node-buildinfo.txt +0 -1
  58. package/build/Release/oracledb-6.5.0-win32-x64.node +0 -0
  59. package/build/Release/oracledb-6.5.0-win32-x64.node-buildinfo.txt +0 -1
@@ -32,6 +32,7 @@ const process = require('process');
32
32
  const readline = require('readline');
33
33
  const errors = require("../../errors.js");
34
34
 
35
+ const MAX_IFILE_DEPTH = 4;
35
36
  /**
36
37
  * Returns File path of the tnsnames.ora if it exists.
37
38
  */
@@ -59,9 +60,12 @@ function tnsnamesFilePath(configDir) {
59
60
  }
60
61
  }
61
62
 
62
- let prevmtime = 0;
63
-
64
63
  class NLParamParser {
64
+
65
+ constructor() {
66
+ this.waiters = [];
67
+ this.readInProgress = false;
68
+ }
65
69
  /**
66
70
  * Reads the given file line by line and stores the
67
71
  * network service names mapped to connect descriptors in the hashtable.
@@ -69,13 +73,29 @@ class NLParamParser {
69
73
  * @returns {Promise}
70
74
  */
71
75
  async initializeNlpa(file_path) {
72
- const stat = fs.statSync(file_path);
73
-
74
- if (!(stat.mtime - prevmtime)) {
75
- /* File has been read */
76
+ if (this.readInProgress) {
77
+ await new Promise((resolve) => {
78
+ this.waiters.push(resolve);
79
+ });
80
+ }
81
+ if (!this.checkModfTime()) {
82
+ /* No File has been modified */
76
83
  return this.ht;
77
84
  }
85
+ this.ht = new Map();
86
+ this.modTime = new Map(); //stores modified time of each IFile
87
+ this.readInProgress = true;
88
+ await this.start(file_path, 0); //start with 0 depth (tnsnames.ora)
89
+ return this.ht;
90
+ }
91
+
92
+ async start(file_path, depth) {
78
93
 
94
+ if (depth > MAX_IFILE_DEPTH)
95
+ return; //ignore after max depth
96
+ const stat = fs.statSync(file_path);
97
+ // store file path and its modified time.
98
+ this.modTime.set(file_path, stat.mtime);
79
99
  // Creating a readable stream from file
80
100
  // readline module reads line by line
81
101
  // but from a readable stream only.
@@ -84,52 +104,49 @@ class NLParamParser {
84
104
  output: process.stdout,
85
105
  terminal: false
86
106
  });
87
- this.ht = new Map();
88
-
89
- const start = async () =>{
90
- let nvElem = "";
91
- for await (let line of file) {
92
- if (line.length == 0) { // ignore empty lines
93
- continue;
94
- } else if (line[0] == '#') { // comment line
107
+ let nvElem = "";
108
+ for await (let line of file) {
109
+ if (line.length == 0) { // ignore empty lines
110
+ continue;
111
+ } else if (line[0] == '#') { // comment line
112
+ continue;
113
+ } else if ((line[0] == ' ') || // continued input on new line
114
+ (line[0] == '\t') ||
115
+ (line[0] == ')') ||
116
+ (line[0] == '(')) {
117
+ line = line.replace(/\s+/g, '');
118
+ line = this.checkNLPforComments(line);
119
+ if (line.length == 0)
95
120
  continue;
96
- } else if ((line[0] == ' ') || // continued input on new line
97
- (line[0] == '\t') ||
98
- (line[0] == ')') ||
99
- (line[0] == '(')) {
100
- line = line.replace(/\s+/g, '');
101
- line = this.checkNLPforComments(line);
102
- if (line.length == 0)
103
- continue;
104
- else {
105
- nvElem = nvElem + line;
106
- }
121
+ else {
122
+ nvElem = nvElem + line;
123
+ }
107
124
 
108
- } else { // new NV Element starting here
109
- if (nvElem.length == 0) {
125
+ } else { // new NV Element starting here
126
+ if (nvElem.length == 0) {
110
127
 
111
- line = this.checkNLPforComments(line);
112
- nvElem = nvElem + line;
128
+ line = this.checkNLPforComments(line);
129
+ nvElem = nvElem + line;
113
130
 
114
- } else if (nvElem.length != 0) {
115
- this.addNLPListElement(nvElem); // Add Parameter to Hashtable
116
- nvElem = ""; // Clear first, before storing current line
131
+ } else if (nvElem.length != 0) {
132
+ await this.addNLPListElement(nvElem, depth); // Add Parameter to Hashtable
133
+ nvElem = ""; // Clear first, before storing current line
117
134
 
118
- line = this.checkNLPforComments(line);
119
- nvElem = nvElem + line;
120
- }
135
+ line = this.checkNLPforComments(line);
136
+ nvElem = nvElem + line;
121
137
  }
122
138
  }
123
- if (nvElem.length != 0) { // at eof, still one more parameter to read
124
- this.addNLPListElement(nvElem);
125
- nvElem = ""; // clear nvElem buffer after added
126
- }
127
- prevmtime = stat.mtime;
128
- return this.ht;
129
- };
130
- return await start();
139
+ }
140
+ if (nvElem.length != 0) { // at eof, still one more parameter to read
141
+ await this.addNLPListElement(nvElem, depth);
142
+ nvElem = ""; // clear nvElem buffer after added
143
+ }
144
+ this.readInProgress = false;
145
+ let waiter;
146
+ while ((waiter = this.waiters.pop())) {
147
+ waiter();
148
+ }
131
149
  }
132
-
133
150
  /**
134
151
  * Given a string, this method looks if the '#' character is present.
135
152
  * If true, the line is truncated from that point onwards until the end
@@ -155,11 +172,28 @@ class NLParamParser {
155
172
  }
156
173
  return str1.join('');
157
174
  }
175
+ // check if any of the IFiles has been changed
176
+ checkModfTime() {
177
+ if (this.modTime) {
178
+ for (const [key, value] of this.modTime) {
179
+ if (fs.existsSync(key)) {
180
+ const stat = fs.statSync(key);
181
+ if ((stat.mtime - value > 0)) {
182
+ return true;
183
+ }
184
+ } else
185
+ return true;
186
+ }
187
+ } else {
188
+ return true;
189
+ }
190
+ return false;
191
+ }
158
192
  /**
159
193
  * adds name value pairs from the input buffer into the hash table.
160
194
  * @param {string} ibuf
161
195
  */
162
- addNLPListElement(ibuf) {
196
+ async addNLPListElement(ibuf, depth) {
163
197
  const res = ibuf.split(/\r?\n/).filter(element => element);
164
198
  for (let i = 0; i < res.length; i++) {
165
199
  if (res[i].charAt(0) != '(') {
@@ -169,14 +203,17 @@ class NLParamParser {
169
203
  const name = nvp.name;
170
204
  const uname = name.toUpperCase();
171
205
  nvp.name = uname;
172
- const unames = uname.split(","); //multiple aliases (alias1, alias2, alias3)
173
- for (let i = 0; i < unames.length; i++) {
174
- this.ht.set(unames[i], nvp);
206
+ // support for ifile
207
+ if (uname == 'IFILE') {
208
+ await this.start(nvp.atom, depth + 1);
209
+ } else {
210
+ const unames = uname.split(","); //multiple aliases (alias1, alias2, alias3)
211
+ for (let i = 0; i < unames.length; i++) {
212
+ this.ht.set(unames[i], nvp);
213
+ }
175
214
  }
176
215
  }
177
216
  }
178
-
179
-
180
217
  toString() {
181
218
  let out = "";
182
219
  this.ht.forEach((value) => {
@@ -77,6 +77,9 @@ class SessionAtts {
77
77
  if (typeof params.walletPassword === 'string') {
78
78
  this.nt.walletPassword = params.walletPassword;
79
79
  }
80
+ if (typeof params.walletContent === 'string') {
81
+ this.nt.wallet = params.walletContent;
82
+ }
80
83
  if (params.expireTime > 0) {
81
84
  this.nt.expireTime = params.expireTime * 1000 * 60;
82
85
  }
@@ -135,6 +138,15 @@ class SessionAtts {
135
138
  });
136
139
  }
137
140
 
141
+ /**
142
+ * Clear wallet
143
+ */
144
+ clearWallet() {
145
+ if (this.nt.wallet && Buffer.isBuffer(this.nt.wallet))
146
+ this.nt.wallet.fill(0);
147
+ this.nt.wallet = null;
148
+ }
149
+
138
150
  /**
139
151
  * Prepare attributes for connection, Generate Connection ID and read Wallet file
140
152
  *
@@ -151,7 +163,7 @@ class SessionAtts {
151
163
  }
152
164
  this.nt.connectionId = this.connectionId;
153
165
 
154
- if (protocol && (protocol.toUpperCase() == "TCPS" && this.nt.walletFile)) {
166
+ if (protocol && (protocol.toUpperCase() == "TCPS" && !this.nt.wallet && this.nt.walletFile)) {
155
167
  this.nt.wallet = await this.readWalletFile();
156
168
  }
157
169
 
@@ -29,6 +29,7 @@
29
29
  const { Buffer } = require('buffer');
30
30
  const constants = require('../constants');
31
31
  const errors = require('../errors');
32
+ const protoConstants = require('./protocol/constants');
32
33
 
33
34
  /**
34
35
  * It is used to cache the metadata about bind information
@@ -519,6 +520,9 @@ class Statement {
519
520
  // cursor also requires a full execute.
520
521
  //---------------------------------------------------------------------------
521
522
  _setVariable(bindInfo, variable) {
523
+ if (variable.type._oraTypeNum === protoConstants.TNS_DATA_TYPE_CURSOR) {
524
+ this.requiresFullExecute = true;
525
+ }
522
526
  if (variable.maxSize !== bindInfo.maxSize
523
527
  || variable.dir !== bindInfo.dir
524
528
  || variable.isArray !== bindInfo.isArray
@@ -146,6 +146,11 @@ class StatementCache {
146
146
  return stmt;
147
147
  }
148
148
 
149
+ clearCursor(statement) {
150
+ this._addCursorToClose(statement);
151
+ statement.cursorId = 0;
152
+ }
153
+
149
154
  //---------------------------------------------------------------------------
150
155
  // returnStatement()
151
156
  // Return the statement to the statement cache, if applicable. If the
@@ -228,8 +228,7 @@ function transformValueIn(info, value, options) {
228
228
  return value._impl;
229
229
 
230
230
  // handle vectors
231
- } else if (value instanceof Float32Array || value instanceof Float64Array ||
232
- value instanceof Int8Array) {
231
+ } else if (nodbUtil.isVectorValue(value)) {
233
232
  checkType(info, options, types.DB_TYPE_VECTOR);
234
233
  return value;
235
234
  } else if (info.type === types.DB_TYPE_VECTOR && Array.isArray(value)) {
package/lib/types.js CHANGED
@@ -112,7 +112,7 @@ function getTypeByOraTypeNum(oraTypeNum, csfrm) {
112
112
 
113
113
  const DB_TYPE_BFILE = new DbType(2020,
114
114
  "DB_TYPE_BFILE", "BFILE",
115
- { oraTypeNum: 114, bufferSizeFactor: 112 });
115
+ { oraTypeNum: 114, bufferSizeFactor: 4000 });
116
116
  const DB_TYPE_BINARY_DOUBLE = new DbType(2008,
117
117
  "DB_TYPE_BINARY_DOUBLE", "BINARY_DOUBLE",
118
118
  { oraTypeNum: 101, bufferSizeFactor: 8 });
package/lib/util.js CHANGED
@@ -31,6 +31,7 @@ const errors = require('./errors.js');
31
31
  const process = require('process');
32
32
  const util = require('util');
33
33
  const types = require('./types.js');
34
+ const constants = require('./constants.js');
34
35
 
35
36
  // node-oracledb version number
36
37
  let packageJSON;
@@ -224,6 +225,32 @@ function isObjectOrArray(value) {
224
225
  return (value !== null && typeof value === 'object') || Array.isArray(value);
225
226
  }
226
227
 
228
+ //---------------------------------------------------------------------------
229
+ // isPrivilege()
230
+ //
231
+ // Returns a boolean indicating if the supplied value is a valid privilege.
232
+ //---------------------------------------------------------------------------
233
+ function isPrivilege(value) {
234
+ // Privileges are mutually exclusive and cannot be specified together
235
+ // except SYSPRELIM, which cannot be specified alone, it is specified in a
236
+ // combo with SYSOPER or SYSDBA. SYSPRELIM is used only for
237
+ // startup/shutdown
238
+
239
+ // If SYSPRELIM specified, clear the bit
240
+ if (value & constants.SYSPRELIM) {
241
+ value = value ^ constants.SYSPRELIM;
242
+ }
243
+ return (
244
+ value === constants.SYSASM ||
245
+ value === constants.SYSBACKUP ||
246
+ value === constants.SYSDBA ||
247
+ value === constants.SYSDG ||
248
+ value === constants.SYSKM ||
249
+ value === constants.SYSOPER ||
250
+ value === constants.SYSRAC
251
+ );
252
+ }
253
+
227
254
  function isShardingKey(value) {
228
255
  if (!Array.isArray(value))
229
256
  return false;
@@ -250,6 +277,36 @@ function isXid(value) {
250
277
  typeof value.branchQualifier === 'string'));
251
278
  }
252
279
 
280
+ function normalizeXid(value) {
281
+ let normalizedXid;
282
+ if (Buffer.isBuffer(value.globalTransactionId) &&
283
+ Buffer.isBuffer(value.branchQualifier)) {
284
+ normalizedXid = value;
285
+ } else {
286
+ normalizedXid = {
287
+ formatId: value.formatId,
288
+ globalTransactionId: value.globalTransactionId,
289
+ branchQualifier: value.branchQualifier
290
+ };
291
+ if (typeof value.globalTransactionId === 'string') {
292
+ normalizedXid.globalTransactionId = Buffer.from(value.globalTransactionId);
293
+ }
294
+ if (typeof value.branchQualifier === 'string') {
295
+ normalizedXid.branchQualifier = Buffer.from(value.branchQualifier);
296
+ }
297
+ }
298
+ if (normalizedXid.globalTransactionId.length > 64) {
299
+ errors.throwErr(errors.ERR_INVALID_TRANSACTION_SIZE,
300
+ normalizedXid.globalTransactionId.length);
301
+ }
302
+ if (normalizedXid.branchQualifier.length > 64) {
303
+ errors.throwErr(errors.ERR_INVALID_BRANCH_SIZE,
304
+ normalizedXid.branchQualifier.length);
305
+ }
306
+
307
+ return normalizedXid;
308
+ }
309
+
253
310
  function verifySodaDoc(content) {
254
311
  if (isSodaDocument(content))
255
312
  return content._impl;
@@ -335,8 +392,9 @@ function addTypeProperties(obj, attrName) {
335
392
  // -----------------------------------------------------------------------------
336
393
  function isVectorValue(value) {
337
394
  return (value instanceof Float32Array ||
338
- value instanceof Float64Array ||
339
- value instanceof Int8Array);
395
+ value instanceof Float64Array ||
396
+ value instanceof Int8Array || (Object.getPrototypeOf(value)
397
+ === Uint8Array.prototype));
340
398
  }
341
399
 
342
400
  //-----------------------------------------------------------------------------
@@ -369,12 +427,14 @@ module.exports = {
369
427
  isArrayOfStrings,
370
428
  isObject,
371
429
  isObjectOrArray,
430
+ isPrivilege,
372
431
  isShardingKey,
373
432
  isSodaDocument,
374
433
  isTokenExpired,
375
434
  isTokenValid,
376
435
  isVectorValue,
377
436
  isXid,
437
+ normalizeXid,
378
438
  makeDate,
379
439
  preventConcurrent,
380
440
  serialize,
package/lib/version.js CHANGED
@@ -30,7 +30,7 @@
30
30
 
31
31
  module.exports = {
32
32
  VERSION_MAJOR: 6,
33
- VERSION_MINOR: 5,
33
+ VERSION_MINOR: 6,
34
34
  VERSION_PATCH: 0,
35
35
  VERSION_SUFFIX: ''
36
36
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "oracledb",
3
- "version": "6.5.0",
3
+ "version": "6.6.0",
4
4
  "description": "A Node.js module for Oracle Database access from JavaScript and TypeScript",
5
5
  "license": "(Apache-2.0 OR UPL-1.0)",
6
6
  "homepage": "http://oracle.github.io/node-oracledb/",
@@ -1 +0,0 @@
1
- oracledb-6.5.0-darwin-x64.node v20.11.1 91a7f419eccbfcd18513c19cd25f55f18a4d8ccc 42edf925eedae73b0d5bd7777167a21987bafc89 Tue, 30 Apr 2024 20:12:57 GMT
@@ -1 +0,0 @@
1
- 91a7f419eccbfcd18513c19cd25f55f18a4d8ccc
@@ -1 +0,0 @@
1
- oracledb-6.5.0-linux-arm64.node v18.19.1 91a7f419eccbfcd18513c19cd25f55f18a4d8ccc 42edf925eedae73b0d5bd7777167a21987bafc89 Wed, 01 May 2024 04:29:37 GMT
@@ -1 +0,0 @@
1
- oracledb-6.5.0-linux-x64.node v16.20.2 91a7f419eccbfcd18513c19cd25f55f18a4d8ccc 42edf925eedae73b0d5bd7777167a21987bafc89 Wed, 01 May 2024 04:22:59 GMT
@@ -1 +0,0 @@
1
- oracledb-6.5.0-win32-x64.node v18.16.0 91a7f419eccbfcd18513c19cd25f55f18a4d8ccc 42edf925eedae73b0d5bd7777167a21987bafc89 Wed, 01 May 2024 04:34:23 GMT