oracledb 6.1.0 → 6.3.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.3.0-darwin-x64.node +0 -0
  3. package/build/Release/oracledb-6.3.0-darwin-x64.node-buildinfo.txt +1 -0
  4. package/build/Release/oracledb-6.3.0-js-buildinfo.txt +1 -0
  5. package/build/Release/oracledb-6.3.0-linux-arm64.node +0 -0
  6. package/build/Release/oracledb-6.3.0-linux-arm64.node-buildinfo.txt +1 -0
  7. package/build/Release/oracledb-6.3.0-linux-x64.node +0 -0
  8. package/build/Release/oracledb-6.3.0-linux-x64.node-buildinfo.txt +1 -0
  9. package/build/Release/oracledb-6.3.0-win32-x64.node +0 -0
  10. package/build/Release/oracledb-6.3.0-win32-x64.node-buildinfo.txt +1 -0
  11. package/examples/README.md +26 -8
  12. package/examples/dbconfig.js +57 -40
  13. package/examples/example.js +6 -4
  14. package/lib/connection.js +67 -1
  15. package/lib/dbObject.js +9 -0
  16. package/lib/errors.js +25 -7
  17. package/lib/future.js +53 -0
  18. package/lib/impl/connection.js +56 -0
  19. package/lib/impl/pool.js +5 -3
  20. package/lib/impl/resultset.js +48 -11
  21. package/lib/oracledb.js +34 -14
  22. package/lib/pool.js +10 -0
  23. package/lib/sodaCollection.js +11 -0
  24. package/lib/sodaOperation.js +16 -0
  25. package/lib/thin/connection.js +184 -155
  26. package/lib/thin/dbObject.js +49 -2
  27. package/lib/thin/index.js +1 -1
  28. package/lib/thin/pool.js +3 -2
  29. package/lib/thin/protocol/buffer.js +79 -70
  30. package/lib/thin/protocol/capabilities.js +3 -1
  31. package/lib/thin/protocol/constants.js +31 -14
  32. package/lib/thin/protocol/messages/auth.js +6 -2
  33. package/lib/thin/protocol/messages/base.js +36 -14
  34. package/lib/thin/protocol/messages/dataType.js +8 -5
  35. package/lib/thin/protocol/messages/lobOp.js +7 -8
  36. package/lib/thin/protocol/messages/withData.js +62 -22
  37. package/lib/thin/protocol/oson.js +13 -10
  38. package/lib/thin/protocol/packet.js +6 -5
  39. package/lib/thin/protocol/utils.js +2 -2
  40. package/lib/thin/sqlnet/connStrategy.js +8 -4
  41. package/lib/thin/sqlnet/constants.js +138 -138
  42. package/lib/thin/sqlnet/ezConnectResolver.js +10 -43
  43. package/lib/thin/sqlnet/navNodes.js +7 -7
  44. package/lib/thin/sqlnet/networkSession.js +22 -21
  45. package/lib/thin/sqlnet/ntTcp.js +7 -7
  46. package/lib/thin/sqlnet/packet.js +1 -1
  47. package/lib/thin/statement.js +345 -113
  48. package/lib/thin/util.js +35 -86
  49. package/lib/types.js +6 -1
  50. package/lib/util.js +12 -0
  51. package/lib/version.js +1 -1
  52. package/package.json +1 -1
  53. package/build/Release/oracledb-6.1.0-darwin-x64.node +0 -0
  54. package/build/Release/oracledb-6.1.0-darwin-x64.node-buildinfo.txt +0 -1
  55. package/build/Release/oracledb-6.1.0-js-buildinfo.txt +0 -1
  56. package/build/Release/oracledb-6.1.0-linux-arm64.node +0 -0
  57. package/build/Release/oracledb-6.1.0-linux-arm64.node-buildinfo.txt +0 -1
  58. package/build/Release/oracledb-6.1.0-linux-x64.node +0 -0
  59. package/build/Release/oracledb-6.1.0-linux-x64.node-buildinfo.txt +0 -1
  60. package/build/Release/oracledb-6.1.0-win32-x64.node +0 -0
  61. package/build/Release/oracledb-6.1.0-win32-x64.node-buildinfo.txt +0 -1
@@ -30,7 +30,9 @@ const constants = require('../constants.js');
30
30
  const errors = require('../errors.js');
31
31
  const nodbUtil = require('../util.js');
32
32
  const settings = require('../settings.js');
33
+ const future = require('../future.js');
33
34
  const types = require('../types.js');
35
+ const Lob = require('../lob.js');
34
36
 
35
37
  // define implementation class
36
38
  class ResultSetImpl {
@@ -100,36 +102,71 @@ class ResultSetImpl {
100
102
  metadata.fetchType = actualFetchType;
101
103
  }
102
104
 
105
+ let converter;
106
+ const userConverter = metadata.converter;
107
+
108
+ // If IsJson is set convert to JSON objects unless
109
+ // user defined output type handler overwrites it.
110
+ if (future.oldJsonColumnAsObj && metadata.isJson && metadata.dbType !== types.DB_TYPE_JSON
111
+ && userConverter === undefined) {
112
+ const outConverter = async function(val) {
113
+ if (!val) {
114
+ return val;
115
+ }
116
+
117
+ let result = val;
118
+ if (val instanceof Lob) {
119
+ result = await val.getData();
120
+ }
121
+ if (result instanceof Buffer) {
122
+ result = result.toString();
123
+ }
124
+ result = JSON.parse(result);
125
+ return result;
126
+ };
127
+ converter = outConverter;
128
+ }
129
+
103
130
  // in thin mode, Oracle NUMBER values are internally fetched as string in
104
131
  // order to preserve precision so must be converted to JavaScript Number
105
132
  // when needed; other numeric and date types are fetched natively as
106
133
  // JavaScript Number and Date values and are converted to string using
107
134
  // toString() when desired
108
135
  if (settings.thin) {
109
- let converter;
110
- const userConverter = metadata.converter;
111
136
  if (metadata.dbType === types.DB_TYPE_NUMBER &&
112
- metadata.fetchType === types.DB_TYPE_NUMBER) {
137
+ metadata.fetchType === types.DB_TYPE_NUMBER) {
113
138
  converter = (v) => (v === null) ? null : parseFloat(v);
114
139
  } else if (metadata.fetchType === types.DB_TYPE_VARCHAR) {
115
140
  if (metadata.dbType === types.DB_TYPE_BINARY_DOUBLE ||
116
- metadata.dbType === types.DB_TYPE_BINARY_FLOAT ||
117
- metadata.dbType === types.DB_TYPE_DATE ||
118
- metadata.dbType === types.DB_TYPE_TIMESTAMP ||
119
- metadata.dbType === types.DB_TYPE_TIMESTAMP_LTZ ||
120
- metadata.dbType === types.DB_TYPE_TIMESTAMP_TZ) {
141
+ metadata.dbType === types.DB_TYPE_BINARY_FLOAT ||
142
+ metadata.dbType === types.DB_TYPE_DATE ||
143
+ metadata.dbType === types.DB_TYPE_TIMESTAMP ||
144
+ metadata.dbType === types.DB_TYPE_TIMESTAMP_LTZ ||
145
+ metadata.dbType === types.DB_TYPE_TIMESTAMP_TZ) {
121
146
  converter = (v) => (v === null) ? null : v.toString();
122
147
  } else if (metadata.dbType === types.DB_TYPE_RAW) {
123
148
  converter = (v) => (v === null) ? null : v.toString('hex').toUpperCase();
124
149
  }
150
+ } else if (metadata.dbType === types.DB_TYPE_XMLTYPE) {
151
+ const xmlConverter = async function(val) {
152
+ if (!val) {
153
+ return val;
154
+ }
155
+ if (typeof val === 'string') {
156
+ return val;
157
+ }
158
+ return await val.getData();
159
+ };
160
+ converter = xmlConverter;
125
161
  }
126
162
  if (userConverter && converter) {
127
163
  const internalConverter = converter;
128
164
  converter = (v) => userConverter(internalConverter(v));
129
165
  }
130
- if (converter) {
131
- metadata.converter = converter;
132
- }
166
+ }
167
+
168
+ if (converter) {
169
+ metadata.converter = converter;
133
170
  }
134
171
 
135
172
  }
package/lib/oracledb.js CHANGED
@@ -48,6 +48,7 @@ const AqDeqOptions = require('./aqDeqOptions.js');
48
48
  const AqEnqOptions = require('./aqEnqOptions.js');
49
49
  const AqMessage = require('./aqMessage.js');
50
50
  const AqQueue = require('./aqQueue.js');
51
+ const future = require('./future.js');
51
52
  const BaseDbObject = require('./dbObject.js');
52
53
  const Connection = require('./connection.js');
53
54
  const Lob = require('./lob.js');
@@ -69,22 +70,26 @@ const defaultPoolAlias = 'default';
69
70
  let _initOracleClientArgs;
70
71
 
71
72
  // Load the Oracledb binary
72
- function _initCLib() {
73
+ function _initCLib(options) {
73
74
  /*global __non_webpack_require__*/ // quieten eslint
74
75
  const requireBinary = (typeof __non_webpack_require__ === 'function') ? __non_webpack_require__ : require; // See Issue 1156
75
-
76
76
  const binaryLocations = [
77
77
  '../' + nodbUtil.RELEASE_DIR + '/' + nodbUtil.BINARY_FILE, // pre-built binary
78
- '../' + nodbUtil.RELEASE_DIR + '/' + 'oracledb.node', // binary built from source
79
- '../build/Debug/oracledb.node', // debug binary
78
+ '../' + nodbUtil.RELEASE_DIR + '/' + nodbUtil.BUILD_FILE, // binary built from source
79
+ '../build/Debug/' + nodbUtil.BUILD_FILE, // debug binary
80
80
  // Paths for Webpack.
81
81
  // Note: to use node-oracledb Thick mode, you will need a Webpack copy plugin to
82
82
  // copy 'node_modules/oracledb/build/' to the output directory,
83
83
  // see https://github.com/oracle/node-oracledb/issues/1156
84
84
  // If you want to use only node-oracledb Thin mode, a copy plugin is not needed.
85
85
  './node_modules/oracledb/' + nodbUtil.RELEASE_DIR + '/' + nodbUtil.BINARY_FILE,
86
- './node_modules/oracledb/' + nodbUtil.RELEASE_DIR + '/' + 'oracledb.node'
86
+ './node_modules/oracledb/' + nodbUtil.RELEASE_DIR + '/' + nodbUtil.BUILD_FILE
87
87
  ];
88
+
89
+ if (options.binaryDir !== undefined) {
90
+ binaryLocations.splice(0, 0, options.binaryDir + '/' + nodbUtil.BINARY_FILE,
91
+ options.binaryDir + '/' + nodbUtil.BUILD_FILE);
92
+ }
88
93
  let oracledbCLib;
89
94
  for (let i = 0; i < binaryLocations.length; i++) {
90
95
  try {
@@ -467,9 +472,10 @@ async function _verifyOptions(options, inCreatePool) {
467
472
  let accessToken;
468
473
  if (typeof options.accessToken === 'function') {
469
474
  outOptions.accessTokenFn = options.accessToken;
470
- accessToken = await options.accessToken(false);
475
+ outOptions.accessTokenConfig = options.accessTokenConfig;
476
+ accessToken = await options.accessToken(false, options.accessTokenConfig);
471
477
  if (!nodbUtil.isTokenValid(accessToken)) {
472
- accessToken = await options.accessToken(true);
478
+ accessToken = await options.accessToken(true, options.accessTokenConfig);
473
479
  }
474
480
  } else {
475
481
  accessToken = options.accessToken;
@@ -478,9 +484,7 @@ async function _verifyOptions(options, inCreatePool) {
478
484
  errors.ERR_TOKEN_HAS_EXPIRED);
479
485
  if (accessToken.privateKey !== undefined) {
480
486
  errors.assert(typeof accessToken.privateKey === 'string', errors.ERR_TOKEN_BASED_AUTH);
481
- accessToken.privateKey = accessToken.privateKey.replace(/\n/g, '');
482
- accessToken.privateKey = accessToken.privateKey.replace('-----BEGIN PRIVATE KEY-----', '');
483
- accessToken.privateKey = accessToken.privateKey.replace('-----END PRIVATE KEY-----', '');
487
+ accessToken.privateKey = nodbUtil.denormalizePrivateKey(accessToken.privateKey);
484
488
  }
485
489
 
486
490
  // store token and privatekey
@@ -493,9 +497,20 @@ async function _verifyOptions(options, inCreatePool) {
493
497
 
494
498
  }
495
499
 
496
- // Check external Auth config
497
- if (outOptions.token === undefined && outOptions.externalAuth && (outOptions.user || outOptions.password)) {
498
- errors.throwErr(errors.ERR_WRONG_CRED_FOR_EXTAUTH);
500
+ // Check external Auth config.
501
+ // Allow Session User enclosed in [] for proxy authentication.
502
+ if (outOptions.token === undefined && outOptions.externalAuth) {
503
+ if (outOptions.password) {
504
+ errors.throwErr(errors.ERR_WRONG_CRED_FOR_EXTAUTH);
505
+ }
506
+ if (outOptions.user) {
507
+ if (inCreatePool) {
508
+ errors.throwErr(errors.ERR_WRONG_CRED_FOR_EXTAUTH);
509
+ } else if (outOptions.user[0] !== '[' || outOptions.user.slice(-1) !== ']') {
510
+ // username is not enclosed in [].
511
+ errors.throwErr(errors.ERR_WRONG_USER_FORMAT_EXTAUTH_PROXY);
512
+ }
513
+ }
499
514
  }
500
515
 
501
516
  return outOptions;
@@ -682,12 +697,13 @@ function initOracleClient(arg1) {
682
697
  errors.assertParamPropString(options, 1, "configDir");
683
698
  errors.assertParamPropString(options, 1, "errorUrl");
684
699
  errors.assertParamPropString(options, 1, "driverName");
700
+ errors.assertParamPropString(options, 1, "binaryDir");
685
701
  }
686
702
  if (settings.thinDriverInitialized) {
687
703
  errors.throwErr(errors.ERR_THIN_CONNECTION_ALREADY_CREATED);
688
704
  }
689
705
  if (_initOracleClientArgs === undefined) {
690
- const oracledbCLib = _initCLib();
706
+ const oracledbCLib = _initCLib(options);
691
707
  if (options.driverName === undefined)
692
708
  options.driverName = constants.DEFAULT_DRIVER_NAME + " thk";
693
709
  if (options.errorUrl === undefined)
@@ -863,6 +879,7 @@ module.exports = {
863
879
  DB_TYPE_TIMESTAMP_LTZ: types.DB_TYPE_TIMESTAMP_LTZ,
864
880
  DB_TYPE_TIMESTAMP_TZ: types.DB_TYPE_TIMESTAMP_TZ,
865
881
  DB_TYPE_VARCHAR: types.DB_TYPE_VARCHAR,
882
+ DB_TYPE_XMLTYPE: types.DB_TYPE_XMLTYPE,
866
883
 
867
884
  // fetchInfo type defaulting
868
885
  DEFAULT: constants.DEFAULT,
@@ -1008,6 +1025,9 @@ module.exports = {
1008
1025
  ARRAY: constants.OUT_FORMAT_ARRAY,
1009
1026
  OBJECT: constants.OUT_FORMAT_OBJECT,
1010
1027
 
1028
+ // Instances
1029
+ future,
1030
+
1011
1031
  // property getters
1012
1032
  get autoCommit() {
1013
1033
  return settings.autoCommit;
package/lib/pool.js CHANGED
@@ -192,10 +192,20 @@ class Pool extends EventEmitter {
192
192
  outOptions.user = options.username;
193
193
  }
194
194
 
195
+ if (this.externalAuth &&
196
+ outOptions.user && (outOptions.user[0] !== '['
197
+ || outOptions.user.slice(-1) !== ']')) {
198
+ // username is not enclosed in [].
199
+ errors.throwErr(errors.ERR_WRONG_USER_FORMAT_EXTAUTH_PROXY);
200
+ }
201
+
195
202
  // password must be a string
196
203
  if (options.password !== undefined) {
197
204
  errors.assertParamPropValue(typeof options.password === 'string', 1,
198
205
  "password");
206
+ if (this.externalAuth) {
207
+ errors.throwErr(errors.ERR_WRONG_CRED_FOR_EXTAUTH);
208
+ }
199
209
  outOptions.password = options.password;
200
210
  }
201
211
 
@@ -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
  //
@@ -32,7 +32,7 @@ const ThinResultSetImpl = require('./resultSet.js');
32
32
  const ThinLobImpl = require("./lob.js");
33
33
  const Protocol = require("./protocol/protocol.js");
34
34
  const { BaseBuffer } = require('./protocol/buffer.js');
35
- const {NetworkSession:nsi} = require("./sqlnet/networkSession.js");
35
+ const {NetworkSession: nsi} = require("./sqlnet/networkSession.js");
36
36
  const { Statement } = require("./statement");
37
37
  const thinUtil = require('./util');
38
38
  const sqlNetConstants = require('./sqlnet/constants.js');
@@ -59,23 +59,29 @@ class ThinConnectionImpl extends ConnectionImpl {
59
59
  * @return {Promise}
60
60
  */
61
61
  async close() {
62
- if (this._protocol.txnInProgress) {
63
- await this.rollback();
64
- }
65
- this._protocol.callTimeout = 0; // not applicable for close
66
- if (this._drcpEnabled) {
67
- await this._sessRelease();
68
- this._drcpEstablishSession = true;
69
- }
62
+ try {
63
+ if (this._protocol.txnInProgress) {
64
+ await this.rollback();
65
+ }
66
+ this._protocol.callTimeout = 0; // not applicable for close
67
+ if (this._drcpEnabled) {
68
+ await this._sessRelease();
69
+ this._drcpEstablishSession = true;
70
+ }
70
71
 
71
- if (this._pool && !this._dropSess) {
72
- await this._pool.release(this);
73
- } else {
74
- if (!this._drcpEnabled) {
75
- const message = new messages.LogOffMessage(this);
76
- await this._protocol._processMessage(message);
72
+ if (this._pool && !this._dropSess) {
73
+ await this._pool.release(this);
74
+ } else {
75
+ if (!this._drcpEnabled) {
76
+ const message = new messages.LogOffMessage(this);
77
+ await this._protocol._processMessage(message);
78
+ }
79
+ this.nscon.disconnect();
77
80
  }
78
- this.nscon.disconnect();
81
+ } catch (err) {
82
+ // immediate close of open socket on failure
83
+ // exception won't be thrown to user
84
+ this.nscon.disconnect(sqlNetConstants.NSFIMM);
79
85
  }
80
86
  }
81
87
 
@@ -153,6 +159,101 @@ class ThinConnectionImpl extends ConnectionImpl {
153
159
  }
154
160
  }
155
161
 
162
+ //---------------------------------------------------------------------------
163
+ // _execute()
164
+ //
165
+ // Calls the RPC that executes a SQL statement and returns the results.
166
+ //---------------------------------------------------------------------------
167
+ async _execute(statement, numIters, binds, options, executeManyFlag) {
168
+
169
+ // perform binds
170
+ const numBinds = statement.bindInfoList.length;
171
+ const numVars = binds.length;
172
+ if (numBinds !== numVars && (numVars === 0 || !binds[0].name)) {
173
+ errors.throwErr(errors.ERR_WRONG_NUMBER_OF_POSITIONAL_BINDS, numBinds, numVars);
174
+ }
175
+ for (let i = 0; i < binds.length; i++) {
176
+ await this._bind(statement, binds[i], i + 1);
177
+ }
178
+ if (statement.isPlSql && (options.batchErrors || options.dmlRowCounts)) {
179
+ errors.throwErr(errors.ERR_EXEC_MODE_ONLY_FOR_DML);
180
+ }
181
+
182
+ // send database request
183
+ const message = new messages.ExecuteMessage(this, statement, options);
184
+ message.numExecs = numIters;
185
+ message.arrayDmlRowCounts = options.dmlRowCounts;
186
+ message.batchErrors = options.batchErrors;
187
+ if (statement.isPlSql && statement.requiresFullExecute) {
188
+ message.numExecs = 1;
189
+ await this._protocol._processMessage(message);
190
+ statement.requiresFullExecute = false;
191
+ message.numExecs = numIters - 1;
192
+ message.offset = 1;
193
+ }
194
+ if (message.numExecs > 0) {
195
+ await this._protocol._processMessage(message);
196
+ statement.requiresFullExecute = false;
197
+ }
198
+
199
+ // if a define is required, send an additional request to the database
200
+ if (statement.requiresDefine && statement.sql) {
201
+ statement.requiresFullExecute = true;
202
+ await this._protocol._processMessage(message);
203
+ statement.requiresFullExecute = false;
204
+ statement.requiresDefine = false;
205
+ }
206
+
207
+ // process results
208
+ const result = {};
209
+ if (message.warning) {
210
+ result.warning = message.warning;
211
+ }
212
+ if (statement.numQueryVars > 0) {
213
+ result.resultSet = message.resultSet;
214
+ } else {
215
+ statement.bufferRowIndex = 0;
216
+ const outBinds = thinUtil.getOutBinds(statement, numIters,
217
+ executeManyFlag);
218
+ if (outBinds) {
219
+ result.outBinds = outBinds;
220
+ }
221
+ if (executeManyFlag) {
222
+ if (!statement.isPlSql) {
223
+ result.rowsAffected = statement.rowCount;
224
+ delete statement.rowCount;
225
+ }
226
+ if (options.dmlRowCounts) {
227
+ result.dmlRowCounts = options.dmlRowCounts;
228
+ }
229
+ if (options.batchErrors) {
230
+ result.batchErrors = options.batchErrors;
231
+ }
232
+ } else {
233
+ if (statement.isPlSql && options.implicitResultSet) {
234
+ result.implicitResults = options.implicitResultSet;
235
+ }
236
+ if (statement.lastRowid) {
237
+ result.lastRowid = statement.lastRowid;
238
+ delete statement.lastRowid;
239
+ }
240
+ if (statement.isPlSql) {
241
+ if (statement.rowCount) {
242
+ result.rowsAffected = statement.rowCount;
243
+ }
244
+ } else {
245
+ result.rowsAffected = statement.rowCount || 0;
246
+ }
247
+ if (statement.rowCount) {
248
+ delete statement.rowCount;
249
+ }
250
+ }
251
+ this._returnStatement(statement);
252
+ }
253
+
254
+ return result;
255
+ }
256
+
156
257
  //---------------------------------------------------------------------------
157
258
  // _parseElementType()
158
259
  //
@@ -772,26 +873,6 @@ class ThinConnectionImpl extends ConnectionImpl {
772
873
  return resultSet;
773
874
  }
774
875
 
775
- //---------------------------------------------------------------------------
776
- // Prepares the sql given by user and binds the value to the statement object
777
- //---------------------------------------------------------------------------
778
- async _prepareAndBind(sql, binds, options, isParse = false) {
779
- const stmt = this._prepare(sql, options);
780
- let position = 0;
781
- if (!isParse) {
782
- const numBinds = stmt.bindInfoList.length;
783
- const numVars = binds.length;
784
- if (numBinds !== numVars && (numVars === 0 || !binds[0].name)) {
785
- errors.throwErr(errors.ERR_WRONG_NUMBER_OF_POSITIONAL_BINDS, numBinds, numVars);
786
- }
787
- for (const variable of binds) {
788
- await this._bind(stmt, variable, position + 1);
789
- position += 1;
790
- }
791
- }
792
- return stmt;
793
- }
794
-
795
876
  //---------------------------------------------------------------------------
796
877
  // Clears the statement cache for the connection
797
878
  //---------------------------------------------------------------------------
@@ -812,139 +893,46 @@ class ThinConnectionImpl extends ConnectionImpl {
812
893
  }
813
894
 
814
895
  //---------------------------------------------------------------------------
815
- // Parses the sql given by User
816
- // calls the OAL8 RPC that parses the SQL statement and returns the metadata
817
- // information for a statment.
896
+ // getStatementInfo()
897
+ //
898
+ // Parses the SQL statement and returns information about the statement.
818
899
  //---------------------------------------------------------------------------
819
900
  async getStatementInfo(sql) {
820
901
  const options = {};
821
902
  const result = {};
822
- const statement = await this._prepareAndBind(sql, null, options, true);
903
+ const statement = this._prepare(sql, options);
823
904
  options.connection = this;
824
- // parse the statement (but not for DDL which doesn't support it)
825
- if (!statement.isDdl) {
826
- const message = new messages.ExecuteMessage(this, statement, options);
827
- message.parseOnly = true;
828
- await this._protocol._processMessage(message);
829
- }
830
- if (statement.numQueryVars > 0) {
831
- result.metaData = thinUtil.getMetadataMany(statement.queryVars);
832
- }
833
- result.bindNames = Array.from(statement.bindInfoDict.keys());
834
- result.statementType = statement.statementType;
835
- return result;
836
- }
837
-
838
- //---------------------------------------------------------------------------
839
- // Prepares the sql given by the user,
840
- // calls the OAL8 RPC that executes a SQL statement and returns the results.
841
- //---------------------------------------------------------------------------
842
- async execute(sql, numIters, binds, options, executeManyFlag) {
843
- const result = {};
844
- if (executeManyFlag) {
845
- return await this.executeMany(sql, numIters, binds, options);
846
- }
847
- const statement = await this._prepareAndBind(sql, binds, options);
848
-
849
- // send the initial request to the database
850
- const message = new messages.ExecuteMessage(this, statement, options);
851
- message.numExecs = 1;
852
- await this._protocol._processMessage(message);
853
- statement.requiresFullExecute = false;
854
-
855
- // if a define is required, send an additional request to the database
856
- if (statement.requiresDefine && statement.sql) {
857
- statement.requiresFullExecute = true;
858
- await this._protocol._processMessage(message);
859
- statement.requiresFullExecute = false;
860
- statement.requiresDefine = false;
861
- }
862
-
863
- // process message results
864
- if (statement.numQueryVars > 0) {
865
- result.resultSet = message.resultSet;
866
- } else {
867
- statement.bufferRowIndex = 0;
868
- const bindVars = thinUtil.getBindVars(statement);
869
- const outBinds = thinUtil.getExecuteOutBinds(bindVars);
870
- if (outBinds) {
871
- result.outBinds = outBinds;
872
- }
873
- if (statement.isPlSql) {
874
- if (options.implicitResultSet) {
875
- result.implicitResults = options.implicitResultSet;
876
- }
877
- }
878
- if (statement.lastRowid) {
879
- result.lastRowid = statement.lastRowid;
880
- delete statement.lastRowid;
881
- }
882
- if (statement.isPlSql) {
883
- if (statement.rowCount) {
884
- result.rowsAffected = statement.rowCount;
885
- }
886
- } else {
887
- result.rowsAffected = statement.rowCount || 0;
905
+ try {
906
+ if (!statement.isDdl) {
907
+ const message = new messages.ExecuteMessage(this, statement, options);
908
+ message.parseOnly = true;
909
+ await this._protocol._processMessage(message);
888
910
  }
889
- if (statement.rowCount) {
890
- delete statement.rowCount;
911
+ if (statement.numQueryVars > 0) {
912
+ result.metaData = thinUtil.getMetadataMany(statement.queryVars);
891
913
  }
914
+ result.bindNames = Array.from(statement.bindInfoDict.keys());
915
+ result.statementType = statement.statementType;
916
+ return result;
917
+ } finally {
892
918
  this._returnStatement(statement);
893
919
  }
894
-
895
- return result;
896
920
  }
897
921
 
898
922
  //---------------------------------------------------------------------------
899
- // executeMany()
923
+ // execute()
900
924
  //
901
- // Prepares the sql given by the user, calls the OAL8 RPC that executes a SQL
902
- // statement multiple times and returns the results.
925
+ // Calls the RPC that executes a SQL statement and returns the results.
903
926
  //---------------------------------------------------------------------------
904
- async executeMany(sql, numIters, binds, options) {
905
- const statement = await this._prepareAndBind(sql, binds, options);
906
- if (statement.isPlSql && (options.batchErrors || options.dmlRowCounts)) {
907
- errors.throwErr(errors.ERR_EXEC_MODE_ONLY_FOR_DML);
908
- }
909
-
910
- // send database request
911
- const message = new messages.ExecuteMessage(this, statement, options);
912
- message.numExecs = numIters;
913
- message.arrayDmlRowCounts = options.dmlRowCounts;
914
- message.batchErrors = options.batchErrors;
915
- if (statement.isPlSql && statement.requiresFullExecute) {
916
- message.numExecs = 1;
917
- await this._protocol._processMessage(message);
918
- statement.requiresFullExecute = false;
919
- message.numExecs = numIters - 1;
920
- message.offset = 1;
921
- }
922
- if (message.numExecs > 0) {
923
- await this._protocol._processMessage(message);
924
- }
925
-
926
- // process results
927
- const returnObj = {};
928
- statement.bufferRowIndex = 0;
929
- const bindVars = thinUtil.getBindVars(statement);
930
- const outBinds = thinUtil.getExecuteManyOutBinds(bindVars, numIters);
931
- if (outBinds) {
932
- returnObj.outBinds = outBinds;
933
- }
934
- const rowsAffected = !statement.isPlSql ? statement.rowCount : undefined;
935
- if (rowsAffected) {
936
- returnObj.rowsAffected = rowsAffected;
937
- delete statement.rowCount;
938
- }
939
- if (options.dmlRowCounts) {
940
- returnObj.dmlRowCounts = options.dmlRowCounts;
941
- }
942
- if (options.batchErrors) {
943
- returnObj.batchErrors = options.batchErrors;
927
+ async execute(sql, numIters, binds, options, executeManyFlag) {
928
+ const statement = this._prepare(sql, options);
929
+ try {
930
+ return await this._execute(statement, numIters, binds, options,
931
+ executeManyFlag);
932
+ } catch (err) {
933
+ this._returnStatement(statement);
934
+ throw err;
944
935
  }
945
- this._returnStatement(statement);
946
-
947
- return returnObj;
948
936
  }
949
937
 
950
938
  //---------------------------------------------------------------------------
@@ -1100,6 +1088,47 @@ class ThinConnectionImpl extends ConnectionImpl {
1100
1088
  getInstanceName() {
1101
1089
  return this.instanceName;
1102
1090
  }
1103
- }
1104
1091
 
1092
+ //---------------------------------------------------------------------------
1093
+ // Returns the Oracle Database domain name associated with the connection.
1094
+ //---------------------------------------------------------------------------
1095
+ getDbDomain() {
1096
+ return this.dbDomain;
1097
+ }
1098
+
1099
+ //---------------------------------------------------------------------------
1100
+ // Returns the Oracle Database name associated with the connection.
1101
+ //---------------------------------------------------------------------------
1102
+ getDbName() {
1103
+ return this.dbName;
1104
+ }
1105
+
1106
+ //---------------------------------------------------------------------------
1107
+ // Returns maximum number of cursors that can be opened in one session.
1108
+ //---------------------------------------------------------------------------
1109
+ getMaxOpenCursors() {
1110
+ return this.maxOpenCursors;
1111
+ }
1112
+
1113
+ //---------------------------------------------------------------------------
1114
+ // Returns the Oracle Database service name associated with the connection.
1115
+ //---------------------------------------------------------------------------
1116
+ getServiceName() {
1117
+ return this.serviceName;
1118
+ }
1119
+
1120
+ //---------------------------------------------------------------------------
1121
+ // Returns boolean based on this._protocol.txnInProgress value.
1122
+ //---------------------------------------------------------------------------
1123
+ getTransactionInProgress() {
1124
+ return this._protocol.txnInProgress === constants.TNS_TXN_IN_PROGRESS;
1125
+ }
1126
+
1127
+ //---------------------------------------------------------------------------
1128
+ // Returns the warning object.
1129
+ //---------------------------------------------------------------------------
1130
+ getWarning() {
1131
+ return this.warning;
1132
+ }
1133
+ }
1105
1134
  module.exports = ThinConnectionImpl;