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
package/README.md CHANGED
@@ -1,10 +1,10 @@
1
- # node-oracledb version 6.0.3
1
+ # node-oracledb version 6.2.0
2
2
 
3
3
  The node-oracledb add-on for Node.js powers high performance Oracle Database
4
4
  applications. Applications can be written in TypeScript, or directly in
5
5
  JavaScript.
6
6
 
7
- Use node-oracledb 6.0.3 to connect Node.js 14.6, or later, to Oracle
7
+ Use node-oracledb 6.2.0 to connect Node.js 14.6, or later, to Oracle
8
8
  Database. Older versions of node-oracledb may work with older versions of
9
9
  Node.js.
10
10
 
@@ -0,0 +1 @@
1
+ oracledb-6.2.0-darwin-x64.node v16.20.2 fe16239d5a7ceb588ae0e0766e74da2d20fb7af9 20785f251426f274f4216369b9259908a103384d Wed, 27 Sep 2023 05:56:04 GMT
@@ -0,0 +1 @@
1
+ fe16239d5a7ceb588ae0e0766e74da2d20fb7af9
@@ -0,0 +1 @@
1
+ oracledb-6.2.0-linux-arm64.node v18.15.0 fe16239d5a7ceb588ae0e0766e74da2d20fb7af9 20785f251426f274f4216369b9259908a103384d Wed, 27 Sep 2023 06:02:23 GMT
@@ -0,0 +1 @@
1
+ oracledb-6.2.0-linux-x64.node v16.19.1 fe16239d5a7ceb588ae0e0766e74da2d20fb7af9 20785f251426f274f4216369b9259908a103384d Thu, 28 Sep 2023 16:23:40 GMT
@@ -0,0 +1 @@
1
+ oracledb-6.2.0-win32-x64.node v16.19.0 fe16239d5a7ceb588ae0e0766e74da2d20fb7af9 20785f251426f274f4216369b9259908a103384d Wed, 27 Sep 2023 10:36:18 GMT
@@ -30,7 +30,7 @@
30
30
  * to the database. Production applications should consider using
31
31
  * External Authentication to avoid hard coded credentials.
32
32
  *
33
- * To create a database user see
33
+ * To create a database user, see
34
34
  * https://blogs.oracle.com/sql/post/how-to-create-users-grant-them-privileges-and-remove-them-in-oracle-database
35
35
  *
36
36
  * Applications can set the connectString value to an Easy Connect
@@ -46,8 +46,8 @@
46
46
  * Commonly just the host_name and service_name are needed
47
47
  * e.g. "localhost/orclpdb1" or "example.com/XEPDB1"
48
48
  *
49
- * The Easy Connect syntax was enhanced in Oracle Database 19c to
50
- * allow more options, refer to the documentation:
49
+ * The Easy Connect syntax supports lots of options. To know more, please
50
+ * refer to the latest Oracle documentation on Easy Connect syntax:
51
51
  * https://www.oracle.com/pls/topic/lookup?ctx=dblatest&id=GUID-B0437826-43C1-49EC-A94D-B650B6A4A6EE
52
52
  *
53
53
  * If using a tnsnames.ora file, the file can be in a default
@@ -66,17 +66,10 @@
66
66
  * creating a pool should not be set when externalAuth is true.
67
67
  *
68
68
  * TROUBLESHOOTING
69
- * Errors like:
70
- * ORA-12541: TNS:no listener
71
- * or
72
- * ORA-12154: TNS:could not resolve the connect identifier specified
73
- * indicate connectString is invalid.
74
- *
75
- * The error:
76
- * ORA-12514: TNS:listener does not currently know of requested in connect descriptor
77
- * indicates connectString is invalid. You are reaching a computer
78
- * with Oracle installed but the service name isn't known.
79
- * Use 'lsnrctl services' on the database server to find available services
69
+ * Refer to the Error Handling section in node-oracledb documentation
70
+ * to understand the different types of errors in both the Thin and Thick
71
+ * modes of node-oracledb:
72
+ * https://node-oracledb.readthedocs.io/en/latest/user_guide/exception_handling.html#errors-in-thin-and-thick-modes
80
73
  *
81
74
  *****************************************************************************/
82
75
 
@@ -127,7 +127,6 @@ async function run() {
127
127
  // For a complete list of options see the documentation.
128
128
  options = {
129
129
  outFormat: oracledb.OUT_FORMAT_OBJECT, // query result format
130
- // extendedMetaData: true, // get extra metadata
131
130
  // fetchArraySize: 100 // internal buffer allocation size for tuning
132
131
  };
133
132
 
package/lib/aqQueue.js CHANGED
@@ -27,13 +27,14 @@
27
27
  'use strict';
28
28
 
29
29
  const { Buffer } = require('buffer');
30
- const constants = require('./constants.js');
31
30
  const errors = require('./errors.js');
32
31
  const nodbUtil = require('./util.js');
33
32
  const AqDeqOptions = require('./aqDeqOptions.js');
34
33
  const AqEnqOptions = require('./aqEnqOptions.js');
35
34
  const AqMessage = require('./aqMessage.js');
36
35
  const BaseDbObject = require('./dbObject.js');
36
+ const transformer = require('./transformer.js');
37
+ const types = require('./types.js');
37
38
 
38
39
  class AqQueue {
39
40
 
@@ -47,6 +48,19 @@ class AqQueue {
47
48
  value instanceof BaseDbObject);
48
49
  }
49
50
 
51
+ //---------------------------------------------------------------------------
52
+ // _makeMessage()
53
+ //
54
+ // For enqOne()/deqOne()/enqMany()/deqMany(), wrap the return value with JS
55
+ // layer object.
56
+ //---------------------------------------------------------------------------
57
+ _makeMessage(msgImpl) {
58
+ const msg = new AqMessage();
59
+ msg._impl = msgImpl;
60
+ msg._payloadTypeClass = this._payloadTypeClass;
61
+ return msg;
62
+ }
63
+
50
64
  //---------------------------------------------------------------------------
51
65
  // _verifyMessage()
52
66
  //
@@ -64,7 +78,7 @@ class AqQueue {
64
78
  message = {};
65
79
  } else {
66
80
  message = {...message};
67
- if (this._isPayload(message.payload)) {
81
+ if (this._isJson || this._isPayload(message.payload)) {
68
82
  payload = message.payload;
69
83
  } else if (this._payloadTypeClass) {
70
84
  payload = new this._payloadTypeClass(message.payload);
@@ -74,7 +88,9 @@ class AqQueue {
74
88
  }
75
89
 
76
90
  // validate payload
77
- if (typeof payload === 'string') {
91
+ if (this._isJson) {
92
+ message.payload = transformer.transformJsonValue(payload);
93
+ } else if (typeof payload === 'string') {
78
94
  message.payload = Buffer.from(payload);
79
95
  } else if (Buffer.isBuffer(payload)) {
80
96
  message.payload = payload;
@@ -116,8 +132,17 @@ class AqQueue {
116
132
  // Creates the queue and populates some internal attributes.
117
133
  //---------------------------------------------------------------------------
118
134
  async create(conn, name, options) {
119
- if (options.payloadType) {
120
- if (typeof options.payloadType == 'string') {
135
+ if (options.payloadType === types.DB_TYPE_JSON) {
136
+ this._isJson = true;
137
+ this._payloadType = types.DB_TYPE_JSON;
138
+ this._payloadTypeName = "JSON";
139
+ } else if (options.payloadType === undefined ||
140
+ options.payloadType === types.DB_TYPE_RAW) {
141
+ this._payloadType = types.DB_TYPE_RAW;
142
+ this._payloadTypeName = "RAW";
143
+ } else {
144
+ if (typeof options.payloadType === 'string') {
145
+ // DB Object type
121
146
  const cls = await conn._getDbObjectClassForName(options.payloadType);
122
147
  this._payloadTypeClass = cls;
123
148
  options.payloadType = cls;
@@ -126,14 +151,12 @@ class AqQueue {
126
151
  options.payloadType.prototype instanceof BaseDbObject, 2, "payloadType");
127
152
  this._payloadTypeClass = options.payloadType;
128
153
  }
129
- this._payloadType = constants.DB_TYPE_OBJECT;
154
+ this._payloadType = types.DB_TYPE_OBJECT;
130
155
  this._payloadTypeName = this._payloadTypeClass.prototype.name;
131
- } else {
132
- this._payloadType = constants.DB_TYPE_RAW;
133
- this._payloadTypeName = "RAW";
134
156
  }
135
157
  this._name = name;
136
- this._impl = await conn._impl.getQueue(name, options);
158
+ this._impl = await conn._impl.getQueue(name, this._payloadTypeClass,
159
+ this._payloadType);
137
160
  }
138
161
 
139
162
  //---------------------------------------------------------------------------
@@ -147,14 +170,7 @@ class AqQueue {
147
170
  errors.assertParamValue(Number.isInteger(maxMessages) && maxMessages > 0,
148
171
  1);
149
172
  const msgImpls = await this._impl.deqMany(maxMessages);
150
- const messages = new Array(msgImpls.length);
151
- for (let i = 0; i < msgImpls.length; i++) {
152
- const msg = new AqMessage();
153
- msg._impl = msgImpls[i];
154
- msg._payloadTypeClass = this._payloadTypeClass;
155
- messages[i] = msg;
156
- }
157
- return messages;
173
+ return msgImpls.map(i => this._makeMessage(i));
158
174
  }
159
175
 
160
176
  //---------------------------------------------------------------------------
@@ -165,12 +181,8 @@ class AqQueue {
165
181
  async deqOne() {
166
182
  errors.assertArgCount(arguments, 0, 0);
167
183
  const msgImpl = await this._impl.deqOne();
168
- if (msgImpl) {
169
- const msg = new AqMessage();
170
- msg._impl = msgImpl;
171
- msg._payloadTypeClass = this._payloadTypeClass;
172
- return msg;
173
- }
184
+ if (msgImpl)
185
+ return this._makeMessage(msgImpl);
174
186
  }
175
187
 
176
188
  //---------------------------------------------------------------------------
@@ -200,7 +212,8 @@ class AqQueue {
200
212
  for (let i = 0; i < messages.length; i++) {
201
213
  verifiedMessages[i] = this._verifyMessage(messages[i]);
202
214
  }
203
- return await this._impl.enqMany(verifiedMessages);
215
+ const msgImpls = await this._impl.enqMany(verifiedMessages);
216
+ return msgImpls.map(i => this._makeMessage(i));
204
217
  }
205
218
 
206
219
  //---------------------------------------------------------------------------
@@ -211,7 +224,8 @@ class AqQueue {
211
224
  async enqOne(message) {
212
225
  errors.assertArgCount(arguments, 1, 1);
213
226
  message = this._verifyMessage(message);
214
- return await this._impl.enqOne(message);
227
+ const msgImpl = await this._impl.enqOne(message);
228
+ return this._makeMessage(msgImpl);
215
229
  }
216
230
 
217
231
  //---------------------------------------------------------------------------
package/lib/connection.js CHANGED
@@ -1039,6 +1039,19 @@ class Connection extends EventEmitter {
1039
1039
  return info;
1040
1040
  }
1041
1041
 
1042
+ //---------------------------------------------------------------------------
1043
+ // instanceName
1044
+ //
1045
+ // Returns the Oracle Database instance name associated with the connection.
1046
+ // This is the equivalent of the SQL expression:
1047
+ // sys_context('userenv', 'instance_name')
1048
+ //---------------------------------------------------------------------------
1049
+ get instanceName() {
1050
+ if (this._impl)
1051
+ return this._impl.getInstanceName();
1052
+ return undefined;
1053
+ }
1054
+
1042
1055
  //---------------------------------------------------------------------------
1043
1056
  // internalName
1044
1057
  //
@@ -1061,7 +1074,7 @@ class Connection extends EventEmitter {
1061
1074
  //
1062
1075
  // Returns the health status of the connection. If this function returns
1063
1076
  // false, the caller should close the connection.
1064
- // ---------------------------------------------------------------------------
1077
+ //---------------------------------------------------------------------------
1065
1078
  isHealthy() {
1066
1079
  return (this._impl !== undefined && !this._closing &&
1067
1080
  this._impl.isHealthy());
@@ -1227,7 +1240,7 @@ class Connection extends EventEmitter {
1227
1240
  errors.assertArgCount(arguments, 2, 2);
1228
1241
  errors.assertParamValue(typeof name === 'string', 1);
1229
1242
  errors.assertParamValue(nodbUtil.isObject(options), 2);
1230
- options = {...options};
1243
+ options = {name: name, ...options};
1231
1244
  errors.assertParamPropUnsignedInt(options, 2, "namespace");
1232
1245
  if (options.namespace === undefined)
1233
1246
  options.namespace = constants.SUBSCR_NAMESPACE_DBCHANGE;
@@ -1253,14 +1266,13 @@ class Connection extends EventEmitter {
1253
1266
  errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
1254
1267
 
1255
1268
  const inSubscr = _subscriptions.get(name);
1256
- let outValue = await this._impl.subscribe(inSubscr, options);
1269
+ const outValue = await this._impl.subscribe(inSubscr, options);
1257
1270
  let subscription;
1258
1271
  if (options.namespace === constants.SUBSCR_NAMESPACE_DBCHANGE) {
1259
1272
  subscription = outValue.subscription;
1260
1273
  delete outValue.subscription;
1261
1274
  } else {
1262
1275
  subscription = outValue;
1263
- outValue = undefined;
1264
1276
  }
1265
1277
  _subscriptions.set(name, subscription);
1266
1278
  return outValue;
package/lib/dbObject.js CHANGED
@@ -319,6 +319,15 @@ class BaseDbObject {
319
319
  return this._objType.schema;
320
320
  }
321
321
 
322
+ //---------------------------------------------------------------------------
323
+ // packageName
324
+ //
325
+ // Property for the packageName of the database object type.
326
+ //---------------------------------------------------------------------------
327
+ get packageName() {
328
+ return this._objType.packageName;
329
+ }
330
+
322
331
  //---------------------------------------------------------------------------
323
332
  // setElement()
324
333
  //
package/lib/errors.js CHANGED
@@ -116,7 +116,6 @@ const ERR_UNEXPECTED_DATA = 113;
116
116
  const ERR_OSON_FIELD_NAME_LIMITATION = 114;
117
117
  const ERR_ORACLE_NUMBER_NO_REPR = 115;
118
118
  const ERR_UNSUPPORTED_VERIFIER_TYPE = 116;
119
- const ERR_INVALID_PRIVATE_KEY = 117;
120
119
  const ERR_THIN_CONNECTION_ALREADY_CREATED = 118;
121
120
  const ERR_UNSUPPORTED_CONVERSION = 119;
122
121
  const ERR_FETCH_TYPE_HANDLER_RETURN_VALUE = 120;
@@ -178,7 +177,6 @@ adjustErrorXref.set("OCI-22165", [ERR_INVALID_COLL_INDEX_SET, /index \[([0-9]+)\
178
177
  adjustErrorXref.set("ORA-00028", ERR_CONNECTION_CLOSED);
179
178
  adjustErrorXref.set("ORA-00600", ERR_CONNECTION_CLOSED);
180
179
  adjustErrorXref.set("ORA-24338", ERR_INVALID_REF_CURSOR);
181
- adjustErrorXref.set("ORA-24422", ERR_POOL_HAS_BUSY_CONNECTIONS);
182
180
  adjustErrorXref.set("ORA-25708", ERR_TOKEN_HAS_EXPIRED);
183
181
 
184
182
  // define mapping for error messages
@@ -355,8 +353,6 @@ messages.set(ERR_ORACLE_NUMBER_NO_REPR, // NJS-115
355
353
  'value cannot be represented as an Oracle Database number');
356
354
  messages.set(ERR_UNSUPPORTED_VERIFIER_TYPE, // NJS-116
357
355
  'password verifier type 0x%s is not supported by node-oracledb in Thin mode');
358
- messages.set(ERR_INVALID_PRIVATE_KEY, // NJS-117
359
- 'invalid private key. Headers and footers are not allowed');
360
356
  messages.set(ERR_THIN_CONNECTION_ALREADY_CREATED, // NJS-118
361
357
  'node-oracledb Thick mode cannot be enabled because a Thin mode connection has already been created');
362
358
  messages.set(ERR_UNSUPPORTED_CONVERSION, // NJS-119
@@ -470,7 +466,7 @@ function assertArgCount(args, minArgCount, maxArgCount) {
470
466
  //-----------------------------------------------------------------------------
471
467
  // assertParamPropBool()
472
468
  //
473
- // Asserts that the property value of a parmeter is a boolean value (or
469
+ // Asserts that the property value of a parameter is a boolean value (or
474
470
  // undefined).
475
471
  //-----------------------------------------------------------------------------
476
472
  function assertParamPropBool(obj, parameterNum, propName) {
@@ -483,7 +479,7 @@ function assertParamPropBool(obj, parameterNum, propName) {
483
479
  //-----------------------------------------------------------------------------
484
480
  // assertParamPropFunction()
485
481
  //
486
- // Asserts that the property value of a parmeter is a function (or undefined).
482
+ // Asserts that the property value of a parameter is a function (or undefined).
487
483
  //-----------------------------------------------------------------------------
488
484
  function assertParamPropFunction(obj, parameterNum, propName) {
489
485
  if (obj[propName] !== undefined) {
@@ -495,7 +491,7 @@ function assertParamPropFunction(obj, parameterNum, propName) {
495
491
  //-----------------------------------------------------------------------------
496
492
  // assertParamPropInt()
497
493
  //
498
- // Asserts that the property value of a parmeter is an integer value (or
494
+ // Asserts that the property value of a parameter is an integer value (or
499
495
  // undefined).
500
496
  //-----------------------------------------------------------------------------
501
497
  function assertParamPropInt(obj, parameterNum, propName) {
@@ -508,7 +504,7 @@ function assertParamPropInt(obj, parameterNum, propName) {
508
504
  //-----------------------------------------------------------------------------
509
505
  // assertParamPropUnsignedInt()
510
506
  //
511
- // Asserts that the property value of a parmeter is a positive integer value
507
+ // Asserts that the property value of a parameter is a positive integer value
512
508
  // (or undefined).
513
509
  //-----------------------------------------------------------------------------
514
510
  function assertParamPropUnsignedInt(obj, parameterNum, propName) {
@@ -521,7 +517,7 @@ function assertParamPropUnsignedInt(obj, parameterNum, propName) {
521
517
  //-----------------------------------------------------------------------------
522
518
  // assertParamPropString()
523
519
  //
524
- // Asserts that the property value of a parmeter is a function (or undefined).
520
+ // Asserts that the property value of a parameter is a string value (or undefined).
525
521
  //-----------------------------------------------------------------------------
526
522
  function assertParamPropString(obj, parameterNum, propName) {
527
523
  if (obj[propName] !== undefined) {
@@ -533,7 +529,7 @@ function assertParamPropString(obj, parameterNum, propName) {
533
529
  //-----------------------------------------------------------------------------
534
530
  // assertParamPropValue()
535
531
  //
536
- // Asserts that the property value of a parmeter passes the specified
532
+ // Asserts that the property value of a parameter passes the specified
537
533
  // condition.
538
534
  //-----------------------------------------------------------------------------
539
535
  function assertParamPropValue(condition, parameterNum, propName) {
@@ -544,7 +540,7 @@ function assertParamPropValue(condition, parameterNum, propName) {
544
540
  //-----------------------------------------------------------------------------
545
541
  // assertParamValue()
546
542
  //
547
- // Asserts that the parmeter value passes the specified condition.
543
+ // Asserts that the parameter value passes the specified condition.
548
544
  //-----------------------------------------------------------------------------
549
545
  function assertParamValue(condition, parameterNum) {
550
546
  assert(condition, ERR_INVALID_PARAMETER_VALUE, parameterNum);
@@ -612,10 +608,19 @@ function transformErr(err, fnOpt) {
612
608
  const pos = err.message.indexOf(":");
613
609
  if (pos > 0) {
614
610
  err.code = err.message.substr(0, pos);
611
+ /* add Oracle Database Error Help Portal URL for database error
612
+ messages, but only in thin mode since this is done
613
+ automatically in thick mode with Oracle Client 23c and higher
614
+ */
615
+ const settings = require('./settings.js');
616
+ if (err.errorNum && settings.thin) {
617
+ err.message += '\n' + 'Help: https://docs.oracle.com/error-help/db/ora-' +
618
+ `${err.errorNum.toString().padStart(5, '0')}/`;
619
+ }
615
620
  if (adjustErrorXref.has(err.code)) {
616
621
  let args = [];
617
622
  let driverErrorNum;
618
- let driverErrorInfo = adjustErrorXref.get(err.code);
623
+ const driverErrorInfo = adjustErrorXref.get(err.code);
619
624
  if (typeof driverErrorInfo === 'number') {
620
625
  driverErrorNum = driverErrorInfo;
621
626
  } else {
@@ -748,7 +753,6 @@ module.exports = {
748
753
  ERR_UNEXPECTED_DATA,
749
754
  ERR_OSON_FIELD_NAME_LIMITATION,
750
755
  ERR_OSON_VERSION_NOT_SUPPORTED,
751
- ERR_INVALID_PRIVATE_KEY,
752
756
  ERR_THIN_CONNECTION_ALREADY_CREATED,
753
757
  ERR_UNSUPPORTED_CONVERSION,
754
758
  ERR_FETCH_TYPE_HANDLER_RETURN_VALUE,
@@ -226,6 +226,15 @@ class ConnectionImpl {
226
226
  errors.throwNotImplemented("getting the external name");
227
227
  }
228
228
 
229
+ //---------------------------------------------------------------------------
230
+ // getInstanceName()
231
+ //
232
+ // Returns the Oracle Database instance name associated with the connection.
233
+ //---------------------------------------------------------------------------
234
+ getInstanceName() {
235
+ errors.throwNotImplemented("getting the Oracle Database instance name.");
236
+ }
237
+
229
238
  //---------------------------------------------------------------------------
230
239
  // getInternalName()
231
240
  //
@@ -111,14 +111,17 @@ class ResultSetImpl {
111
111
  if (metadata.dbType === types.DB_TYPE_NUMBER &&
112
112
  metadata.fetchType === types.DB_TYPE_NUMBER) {
113
113
  converter = (v) => (v === null) ? null : parseFloat(v);
114
- } else if (metadata.fetchType === types.DB_TYPE_VARCHAR &&
115
- (metadata.dbType === types.DB_TYPE_BINARY_DOUBLE ||
114
+ } else if (metadata.fetchType === types.DB_TYPE_VARCHAR) {
115
+ if (metadata.dbType === types.DB_TYPE_BINARY_DOUBLE ||
116
116
  metadata.dbType === types.DB_TYPE_BINARY_FLOAT ||
117
117
  metadata.dbType === types.DB_TYPE_DATE ||
118
118
  metadata.dbType === types.DB_TYPE_TIMESTAMP ||
119
119
  metadata.dbType === types.DB_TYPE_TIMESTAMP_LTZ ||
120
- metadata.dbType === types.DB_TYPE_TIMESTAMP_TZ)) {
121
- converter = (v) => (v === null) ? null : v.toString();
120
+ metadata.dbType === types.DB_TYPE_TIMESTAMP_TZ) {
121
+ converter = (v) => (v === null) ? null : v.toString();
122
+ } else if (metadata.dbType === types.DB_TYPE_RAW) {
123
+ converter = (v) => (v === null) ? null : v.toString('hex').toUpperCase();
124
+ }
122
125
  }
123
126
  if (userConverter && converter) {
124
127
  const internalConverter = converter;
package/lib/oracledb.js CHANGED
@@ -67,25 +67,28 @@ const defaultPoolAlias = 'default';
67
67
 
68
68
  // save arguments for call to initOracleClient()
69
69
  let _initOracleClientArgs;
70
- let _thinDriverInitialized = false;
71
70
 
72
71
  // Load the Oracledb binary
73
- function _initCLib() {
72
+ function _initCLib(options) {
74
73
  /*global __non_webpack_require__*/ // quieten eslint
75
74
  const requireBinary = (typeof __non_webpack_require__ === 'function') ? __non_webpack_require__ : require; // See Issue 1156
76
-
77
75
  const binaryLocations = [
78
76
  '../' + nodbUtil.RELEASE_DIR + '/' + nodbUtil.BINARY_FILE, // pre-built binary
79
- '../' + nodbUtil.RELEASE_DIR + '/' + 'oracledb.node', // binary built from source
80
- '../build/Debug/oracledb.node', // debug binary
77
+ '../' + nodbUtil.RELEASE_DIR + '/' + nodbUtil.BUILD_FILE, // binary built from source
78
+ '../build/Debug/' + nodbUtil.BUILD_FILE, // debug binary
81
79
  // Paths for Webpack.
82
80
  // Note: to use node-oracledb Thick mode, you will need a Webpack copy plugin to
83
81
  // copy 'node_modules/oracledb/build/' to the output directory,
84
82
  // see https://github.com/oracle/node-oracledb/issues/1156
85
83
  // If you want to use only node-oracledb Thin mode, a copy plugin is not needed.
86
84
  './node_modules/oracledb/' + nodbUtil.RELEASE_DIR + '/' + nodbUtil.BINARY_FILE,
87
- './node_modules/oracledb/' + nodbUtil.RELEASE_DIR + '/' + 'oracledb.node'
85
+ './node_modules/oracledb/' + nodbUtil.RELEASE_DIR + '/' + nodbUtil.BUILD_FILE
88
86
  ];
87
+
88
+ if (options.binaryDir !== undefined) {
89
+ binaryLocations.splice(0, 0, options.binaryDir + '/' + nodbUtil.BINARY_FILE,
90
+ options.binaryDir + '/' + nodbUtil.BUILD_FILE);
91
+ }
89
92
  let oracledbCLib;
90
93
  for (let i = 0; i < binaryLocations.length; i++) {
91
94
  try {
@@ -248,6 +251,12 @@ async function _verifyOptions(options, inCreatePool) {
248
251
  outOptions.sslServerDNMatch = options.sslServerDNMatch;
249
252
  }
250
253
 
254
+ // sslAllowWeakDNMatch must be a boolean
255
+ if (options.sslAllowWeakDNMatch !== undefined) {
256
+ errors.assertParamPropValue(typeof options.sslAllowWeakDNMatch === 'boolean',
257
+ 1, "sslAllowWeakDNMatch");
258
+ outOptions.sslAllowWeakDNMatch = options.sslAllowWeakDNMatch;
259
+ }
251
260
  // httpsProxy must be a string
252
261
  if (options.httpsProxy !== undefined) {
253
262
  errors.assertParamPropValue(typeof options.httpsProxy === 'string',
@@ -472,8 +481,10 @@ async function _verifyOptions(options, inCreatePool) {
472
481
  errors.assert(nodbUtil.isTokenValid(accessToken),
473
482
  errors.ERR_TOKEN_HAS_EXPIRED);
474
483
  if (accessToken.privateKey !== undefined) {
475
- errors.assert(nodbUtil.isPrivateKeyValid(accessToken),
476
- errors.ERR_INVALID_PRIVATE_KEY);
484
+ errors.assert(typeof accessToken.privateKey === 'string', errors.ERR_TOKEN_BASED_AUTH);
485
+ accessToken.privateKey = accessToken.privateKey.replace(/\n/g, '');
486
+ accessToken.privateKey = accessToken.privateKey.replace('-----BEGIN PRIVATE KEY-----', '');
487
+ accessToken.privateKey = accessToken.privateKey.replace('-----END PRIVATE KEY-----', '');
477
488
  }
478
489
 
479
490
  // store token and privatekey
@@ -546,7 +557,7 @@ async function createPool(options) {
546
557
  }
547
558
 
548
559
  // initialize the Oracle client, if necessary
549
- if (_initOracleClientArgs === undefined && !_thinDriverInitialized) {
560
+ if (_initOracleClientArgs === undefined && !settings.thinDriverInitialized) {
550
561
  _initializeThinDriver();
551
562
  }
552
563
 
@@ -579,6 +590,9 @@ async function createPool(options) {
579
590
  delete poolCache[pool.poolAlias];
580
591
  }
581
592
  });
593
+ if (_initOracleClientArgs === undefined) {
594
+ settings.thinDriverInitialized = true;
595
+ }
582
596
 
583
597
  return pool;
584
598
  }
@@ -638,7 +652,6 @@ async function getConnection(a1) {
638
652
  // Returns a pool for the given alias.
639
653
  //-----------------------------------------------------------------------------
640
654
  function getPool(poolAlias) {
641
- let pool;
642
655
 
643
656
  errors.assertArgCount(arguments, 0, 1);
644
657
 
@@ -649,7 +662,7 @@ function getPool(poolAlias) {
649
662
 
650
663
  poolAlias = poolAlias || defaultPoolAlias;
651
664
 
652
- pool = poolCache[poolAlias];
665
+ const pool = poolCache[poolAlias];
653
666
 
654
667
  if (!pool) {
655
668
  errors.throwErr(errors.ERR_POOL_WITH_ALIAS_NOT_FOUND, poolAlias);
@@ -673,12 +686,13 @@ function initOracleClient(arg1) {
673
686
  errors.assertParamPropString(options, 1, "configDir");
674
687
  errors.assertParamPropString(options, 1, "errorUrl");
675
688
  errors.assertParamPropString(options, 1, "driverName");
689
+ errors.assertParamPropString(options, 1, "binaryDir");
676
690
  }
677
691
  if (settings.thinDriverInitialized) {
678
692
  errors.throwErr(errors.ERR_THIN_CONNECTION_ALREADY_CREATED);
679
693
  }
680
694
  if (_initOracleClientArgs === undefined) {
681
- const oracledbCLib = _initCLib();
695
+ const oracledbCLib = _initCLib(options);
682
696
  if (options.driverName === undefined)
683
697
  options.driverName = constants.DEFAULT_DRIVER_NAME + " thk";
684
698
  if (options.errorUrl === undefined)
@@ -1053,16 +1067,10 @@ module.exports = {
1053
1067
  },
1054
1068
 
1055
1069
  get oracleClientVersion() {
1056
- if (_initOracleClientArgs === undefined) {
1057
- errors.throwNotImplemented("getting the Oracle Client version");
1058
- }
1059
1070
  return settings.oracleClientVersion;
1060
1071
  },
1061
1072
 
1062
1073
  get oracleClientVersionString() {
1063
- if (_initOracleClientArgs === undefined) {
1064
- errors.throwNotImplemented("getting the Oracle Client version");
1065
- }
1066
1074
  return settings.oracleClientVersionString;
1067
1075
  },
1068
1076
 
package/lib/pool.js CHANGED
@@ -279,8 +279,14 @@ class Pool extends EventEmitter {
279
279
  });
280
280
  }
281
281
 
282
+ // if any connections are still out and the pool is not being force closed,
283
+ // throw an exception
284
+ if (!forceClose && this._connectionsOut > 0) {
285
+ errors.throwErr(errors.ERR_POOL_HAS_BUSY_CONNECTIONS);
286
+ }
287
+
282
288
  // close the pool
283
- await this._impl.close({forceClose: forceClose});
289
+ await this._impl.close();
284
290
  this._status = constants.POOL_STATUS_CLOSED;
285
291
  this.emit('_afterPoolClose');
286
292
 
@@ -109,7 +109,7 @@ class SodaCollection {
109
109
  errors.assertArgCount(arguments, 1, 1);
110
110
  errors.assertParamValue(Array.isArray(docs) && docs.length > 0, 1);
111
111
 
112
- let actualDocs = Array(docs.length);
112
+ const actualDocs = Array(docs.length);
113
113
  for (let i = 0; i < docs.length; i++) {
114
114
  actualDocs[i] = nodbUtil.verifySodaDoc(docs[i]);
115
115
  }
@@ -188,6 +188,16 @@ class SodaCollection {
188
188
  return doc;
189
189
  }
190
190
 
191
+ //---------------------------------------------------------------------------
192
+ // listIndexes()
193
+ //
194
+ // To obtain all indices from the collection
195
+ //---------------------------------------------------------------------------
196
+ async listIndexes() {
197
+ const arr = await this._impl.listIndexes();
198
+ return arr.map(i => JSON.parse(i));
199
+ }
200
+
191
201
  //---------------------------------------------------------------------------
192
202
  // metaData()
193
203
  //
@@ -262,6 +272,7 @@ nodbUtil.wrapFns(SodaCollection.prototype,
262
272
  "insertManyAndGet",
263
273
  "insertOne",
264
274
  "insertOneAndGet",
275
+ "listIndexes",
265
276
  "save",
266
277
  "saveAndGet",
267
278
  "truncate");
@@ -94,6 +94,22 @@ class SodaOperation {
94
94
  }
95
95
  }
96
96
 
97
+
98
+ //---------------------------------------------------------------------------
99
+ // lock()
100
+ //
101
+ // Pessimistic locking - similar to SELECT FOR UPDATE, these documents
102
+ // cannot be updated by other threads until an explicit commit/rollback is
103
+ // called. With autoCommit set to true is applicable only for one immediate
104
+ // operation and is not recommended in this context
105
+ //---------------------------------------------------------------------------
106
+ lock() {
107
+ errors.assertArgCount(arguments, 0, 0);
108
+ this._options.lock = true;
109
+ return this;
110
+ }
111
+
112
+
97
113
  //---------------------------------------------------------------------------
98
114
  // replaceOne()
99
115
  //