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
@@ -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, getConnectionInfo} = 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');
@@ -49,6 +49,8 @@ const finalizationRegistry = new global.FinalizationRegistry((heldValue) => {
49
49
  class TDSBuffer extends BaseBuffer {
50
50
  }
51
51
 
52
+ const connectionCookies = new Map();
53
+
52
54
  class ThinConnectionImpl extends ConnectionImpl {
53
55
 
54
56
  /**
@@ -57,23 +59,29 @@ class ThinConnectionImpl extends ConnectionImpl {
57
59
  * @return {Promise}
58
60
  */
59
61
  async close() {
60
- if (this._protocol.txnInProgress) {
61
- await this.rollback();
62
- }
63
- this._protocol.callTimeout = 0; // not applicable for close
64
- if (this._drcpEnabled) {
65
- await this._sessRelease();
66
- this._drcpEstablishSession = true;
67
- }
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
+ }
68
71
 
69
- if (this._pool && !this._dropSess) {
70
- await this._pool.release(this);
71
- } else {
72
- if (!this._drcpEnabled) {
73
- const message = new messages.LogOffMessage(this);
74
- 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();
75
80
  }
76
- 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);
77
85
  }
78
86
  }
79
87
 
@@ -151,6 +159,98 @@ class ThinConnectionImpl extends ConnectionImpl {
151
159
  }
152
160
  }
153
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 (statement.numQueryVars > 0) {
210
+ result.resultSet = message.resultSet;
211
+ } else {
212
+ statement.bufferRowIndex = 0;
213
+ const outBinds = thinUtil.getOutBinds(statement, numIters,
214
+ executeManyFlag);
215
+ if (outBinds) {
216
+ result.outBinds = outBinds;
217
+ }
218
+ if (executeManyFlag) {
219
+ if (!statement.isPlSql) {
220
+ result.rowsAffected = statement.rowCount;
221
+ delete statement.rowCount;
222
+ }
223
+ if (options.dmlRowCounts) {
224
+ result.dmlRowCounts = options.dmlRowCounts;
225
+ }
226
+ if (options.batchErrors) {
227
+ result.batchErrors = options.batchErrors;
228
+ }
229
+ } else {
230
+ if (statement.isPlSql && options.implicitResultSet) {
231
+ result.implicitResults = options.implicitResultSet;
232
+ }
233
+ if (statement.lastRowid) {
234
+ result.lastRowid = statement.lastRowid;
235
+ delete statement.lastRowid;
236
+ }
237
+ if (statement.isPlSql) {
238
+ if (statement.rowCount) {
239
+ result.rowsAffected = statement.rowCount;
240
+ }
241
+ } else {
242
+ result.rowsAffected = statement.rowCount || 0;
243
+ }
244
+ if (statement.rowCount) {
245
+ delete statement.rowCount;
246
+ }
247
+ }
248
+ this._returnStatement(statement);
249
+ }
250
+
251
+ return result;
252
+ }
253
+
154
254
  //---------------------------------------------------------------------------
155
255
  // _parseElementType()
156
256
  //
@@ -443,10 +543,6 @@ class ThinConnectionImpl extends ConnectionImpl {
443
543
  await this._protocol.breakMessage();
444
544
  }
445
545
 
446
- _healthStatus() {
447
- return this.nscon.recvInbandNotif();
448
- }
449
-
450
546
  isHealthy() {
451
547
  try {
452
548
  if (this.nscon.recvInbandNotif() === 0)
@@ -461,6 +557,26 @@ class ThinConnectionImpl extends ConnectionImpl {
461
557
  return (this._pool) ? true : false;
462
558
  }
463
559
 
560
+ //---------------------------------------------------------------------------
561
+ // getConnectionCookieByUUID()
562
+ //
563
+ // It fetches from map which keeps keyname as UUID+ServiceName.
564
+ // UUID identifies the CDB instance and ServiceName identifies the
565
+ // entity within a PDB which uniquely identifies a pdb instance.
566
+ //---------------------------------------------------------------------------
567
+ getConnectionCookieByUUID(uuid) {
568
+ let cookie;
569
+ if (uuid) {
570
+ const key = uuid + ((this.serviceName) ? this.serviceName : this.sid);
571
+ cookie = connectionCookies.get(key);
572
+ if (!cookie) {
573
+ cookie = {};
574
+ connectionCookies.set(key, cookie);
575
+ }
576
+ }
577
+ return cookie;
578
+ }
579
+
464
580
  /**
465
581
  *
466
582
  * @param {object} params Configuration of the connection
@@ -499,22 +615,32 @@ class ThinConnectionImpl extends ConnectionImpl {
499
615
  this._clientInfoModified = false;
500
616
  this._module = "";
501
617
  this._moduleModified = false;
618
+ this._drcpEnabled = false;
502
619
  this.serviceName = '';
503
620
  this.remoteAddress = '';
504
- this.privilege = params.privilege;
505
621
  this.comboKey = null; // used in changePassword API
506
622
 
507
623
  this.nscon = new nsi();
508
624
  finalizationRegistry.register(this, this.nscon);
509
625
  await this.nscon.connect(params);
510
626
 
511
- this._connInfo = (this.isPooled()) ? params._connInfo.map((x) => x) :
512
- await getConnectionInfo(params);
513
- this._drcpEnabled = String(this._connInfo[0]).toLowerCase() === 'pooled';
514
- this.serviceName = this._connInfo[2];
515
- this.purity = this._connInfo[3] | constants.PURITY_DEFAULT;
627
+ let serverType;
628
+ if (this.isPooled()) {
629
+ serverType = params._connInfo[0];
630
+ this.serviceName = params._connInfo[2];
631
+ this.purity = params._connInfo[3] | constants.PURITY_DEFAULT;
632
+ this.sid = params._connInfo[4];
633
+ } else {
634
+ serverType = this.nscon.getOption(sqlNetConstants.SERVERTYPE);
635
+ this.serviceName = this.nscon.getOption(sqlNetConstants.SVCNAME);
636
+ this.sid = this.nscon.getOption(sqlNetConstants.SID);
637
+ this.purity = this.nscon.getOption(sqlNetConstants.PURITY) | constants.PURITY_DEFAULT;
638
+ }
639
+ if (serverType) {
640
+ this._drcpEnabled = serverType.toLowerCase() === 'pooled';
641
+ }
516
642
  this.remoteAddress = this.nscon.getOption(sqlNetConstants.REMOTEADDR);
517
- this.connClass = params.connectionClass;
643
+ this.connectionClass = params.connectionClass;
518
644
 
519
645
  /*
520
646
  * if drcp is used, use purity = NEW as the default purity for
@@ -538,13 +664,41 @@ class ThinConnectionImpl extends ConnectionImpl {
538
664
  }
539
665
 
540
666
  try {
541
- let message = new messages.ProtocolMessage(this);
542
- await this._protocol._processMessage(message);
543
- message = new messages.DataTypeMessage(this);
544
- await this._protocol._processMessage(message);
545
- message = new messages.AuthMessage(this, params);
546
- await this._protocol._processMessage(message); // OSESSKEY
547
- await this._protocol._processMessage(message); // OAUTH
667
+ const cookie = this.getConnectionCookieByUUID(this.nscon.dbUUID);
668
+ this.nscon.dbUUID = null;
669
+ const protocolMessage = new messages.ProtocolMessage(this);
670
+ const dataTypeMessage = new messages.DataTypeMessage(this);
671
+ const authMessage = new messages.AuthMessage(this, params);
672
+ let sentCookie = false;
673
+ if (cookie && cookie.populated) {
674
+ const cookieMessage = new messages.ConnectionCookieMessage(this);
675
+ cookieMessage.cookie = cookie;
676
+ cookieMessage.protocolMessage = protocolMessage;
677
+ cookieMessage.dataTypeMessage = dataTypeMessage;
678
+ cookieMessage.authMessage = authMessage;
679
+ await this._protocol._processMessage(cookieMessage);
680
+ sentCookie = true;
681
+ } else {
682
+ await this._protocol._processMessage(protocolMessage);
683
+ }
684
+ if (!sentCookie || !cookie.populated) {
685
+ await this._protocol._processMessage(dataTypeMessage);
686
+ // Does OSESSKEY for non-token Authentication else OAUTH
687
+ await this._protocol._processMessage(authMessage);
688
+ if (cookie && !cookie.populated) {
689
+ cookie.protocolVersion = protocolMessage.serverVersion;
690
+ cookie.serverBanner = protocolMessage.serverBanner;
691
+ cookie.charsetID = this._protocol.caps.charSetID;
692
+ cookie.ncharsetID = this._protocol.caps.nCharsetId;
693
+ cookie.flags = protocolMessage.serverFlags;
694
+ cookie.compileCaps = Buffer.from(protocolMessage.serverCompileCaps);
695
+ cookie.runtimeCaps = Buffer.from(protocolMessage.serverRunTimeCaps);
696
+ cookie.populated = true;
697
+ }
698
+ }
699
+ if (!params.token) { // non-token Authentication
700
+ await this._protocol._processMessage(authMessage); // OAUTH
701
+ }
548
702
  } catch (err) {
549
703
  this.nscon.disconnect();
550
704
  throw err;
@@ -614,7 +768,7 @@ class ThinConnectionImpl extends ConnectionImpl {
614
768
  // option is true
615
769
  //---------------------------------------------------------------------------
616
770
  _prepare(sql, options) {
617
- let statement = this._getStatement(sql, options.keepInStmtCache);
771
+ const statement = this._getStatement(sql, options.keepInStmtCache);
618
772
  statement.bufferRowIndex = 0;
619
773
  statement.bufferRowCount = 0;
620
774
  statement.lastRowIndex = 0;
@@ -626,8 +780,8 @@ class ThinConnectionImpl extends ConnectionImpl {
626
780
  // Binds the values by user to the statement object
627
781
  //---------------------------------------------------------------------------
628
782
  async _bind(stmt, variable, pos = 0) {
629
- let bindInfoDict = stmt.bindInfoDict;
630
- let bindInfoList = stmt.bindInfoList;
783
+ const bindInfoDict = stmt.bindInfoDict;
784
+ const bindInfoList = stmt.bindInfoList;
631
785
 
632
786
  /*
633
787
  * For PL/SQL blocks, if the size of a string or bytes object exceeds
@@ -650,8 +804,8 @@ class ThinConnectionImpl extends ConnectionImpl {
650
804
  if (val === null) {
651
805
  return null;
652
806
  }
653
- let data = await val.getData();
654
- let len = val._length;
807
+ const data = await val.getData();
808
+ const len = val._length;
655
809
  if (data && len > maxSize) {
656
810
  errors.throwErr(errors.ERR_INSUFFICIENT_BUFFER_FOR_BINDS);
657
811
  }
@@ -662,7 +816,7 @@ class ThinConnectionImpl extends ConnectionImpl {
662
816
  if (variable.type === types.DB_TYPE_CLOB ||
663
817
  variable.type === types.DB_TYPE_NCLOB ||
664
818
  variable.type === types.DB_TYPE_BLOB) {
665
- for (let [index, val] of variable.values.entries()) {
819
+ for (const [index, val] of variable.values.entries()) {
666
820
  if (!(val instanceof ThinLobImpl)) {
667
821
  if (val && val.length > 0) {
668
822
  const lobImpl = new ThinLobImpl();
@@ -693,7 +847,7 @@ class ThinConnectionImpl extends ConnectionImpl {
693
847
  stmt._setVariable(bindInfo, variable);
694
848
  });
695
849
  } else {
696
- let bindInfo = bindInfoList[pos - 1];
850
+ const bindInfo = bindInfoList[pos - 1];
697
851
  stmt._setVariable(bindInfo, variable);
698
852
  }
699
853
  }
@@ -716,30 +870,10 @@ class ThinConnectionImpl extends ConnectionImpl {
716
870
  return resultSet;
717
871
  }
718
872
 
719
- //---------------------------------------------------------------------------
720
- // Prepares the sql given by user and binds the value to the statement object
721
- //---------------------------------------------------------------------------
722
- async _prepareAndBind(sql, binds, options, isParse = false) {
723
- const stmt = this._prepare(sql, options);
724
- let position = 0;
725
- if (!isParse) {
726
- const numBinds = stmt.bindInfoList.length;
727
- const numVars = binds.length;
728
- if (numBinds !== numVars && (numVars === 0 || !binds[0].name)) {
729
- errors.throwErr(errors.ERR_WRONG_NUMBER_OF_POSITIONAL_BINDS, numBinds, numVars);
730
- }
731
- for (const variable of binds) {
732
- await this._bind(stmt, variable, position + 1);
733
- position += 1;
734
- }
735
- }
736
- return stmt;
737
- }
738
-
739
873
  //---------------------------------------------------------------------------
740
874
  // Clears the statement cache for the connection
741
875
  //---------------------------------------------------------------------------
742
- resetStatmentCache() {
876
+ resetStatementCache() {
743
877
  this.statementCache.clear();
744
878
  this._cursorsToClose.clear();
745
879
  }
@@ -756,139 +890,46 @@ class ThinConnectionImpl extends ConnectionImpl {
756
890
  }
757
891
 
758
892
  //---------------------------------------------------------------------------
759
- // Parses the sql given by User
760
- // calls the OAL8 RPC that parses the SQL statement and returns the metadata
761
- // information for a statment.
893
+ // getStatementInfo()
894
+ //
895
+ // Parses the SQL statement and returns information about the statement.
762
896
  //---------------------------------------------------------------------------
763
897
  async getStatementInfo(sql) {
764
- let options = {};
765
- let result = {};
766
- let statement = await this._prepareAndBind(sql, null, options, true);
767
- options.connection = this;
768
- // parse the statement (but not for DDL which doesn't support it)
769
- if (!statement.isDdl) {
770
- const message = new messages.ExecuteMessage(this, statement, options);
771
- message.parseOnly = true;
772
- await this._protocol._processMessage(message);
773
- }
774
- if (statement.numQueryVars > 0) {
775
- result.metaData = thinUtil.getMetadataMany(statement.queryVars);
776
- }
777
- result.bindNames = Array.from(statement.bindInfoDict.keys());
778
- result.statementType = statement.statementType;
779
- return result;
780
- }
781
-
782
- //---------------------------------------------------------------------------
783
- // Prepares the sql given by the user,
784
- // calls the OAL8 RPC that executes a SQL statement and returns the results.
785
- //---------------------------------------------------------------------------
786
- async execute(sql, numIters, binds, options, executeManyFlag) {
898
+ const options = {};
787
899
  const result = {};
788
- if (executeManyFlag) {
789
- return await this.executeMany(sql, numIters, binds, options);
790
- }
791
- const statement = await this._prepareAndBind(sql, binds, options);
792
-
793
- // send the initial request to the database
794
- const message = new messages.ExecuteMessage(this, statement, options);
795
- message.numExecs = 1;
796
- await this._protocol._processMessage(message);
797
- statement.requiresFullExecute = false;
798
-
799
- // if a define is required, send an additional request to the database
800
- if (statement.requiresDefine && statement.sql) {
801
- statement.requiresFullExecute = true;
802
- await this._protocol._processMessage(message);
803
- statement.requiresFullExecute = false;
804
- statement.requiresDefine = false;
805
- }
806
-
807
- // process message results
808
- if (statement.numQueryVars > 0) {
809
- result.resultSet = message.resultSet;
810
- } else {
811
- statement.bufferRowIndex = 0;
812
- const bindVars = thinUtil.getBindVars(statement);
813
- const outBinds = thinUtil.getExecuteOutBinds(bindVars);
814
- if (outBinds) {
815
- result.outBinds = outBinds;
816
- }
817
- if (statement.isPlSql) {
818
- if (options.implicitResultSet) {
819
- result.implicitResults = options.implicitResultSet;
820
- }
821
- }
822
- if (statement.lastRowid) {
823
- result.lastRowid = statement.lastRowid;
824
- delete statement.lastRowid;
825
- }
826
- if (statement.isPlSql) {
827
- if (statement.rowCount) {
828
- result.rowsAffected = statement.rowCount;
829
- }
830
- } else {
831
- result.rowsAffected = statement.rowCount || 0;
900
+ const statement = this._prepare(sql, options);
901
+ options.connection = this;
902
+ try {
903
+ if (!statement.isDdl) {
904
+ const message = new messages.ExecuteMessage(this, statement, options);
905
+ message.parseOnly = true;
906
+ await this._protocol._processMessage(message);
832
907
  }
833
- if (statement.rowCount) {
834
- delete statement.rowCount;
908
+ if (statement.numQueryVars > 0) {
909
+ result.metaData = thinUtil.getMetadataMany(statement.queryVars);
835
910
  }
911
+ result.bindNames = Array.from(statement.bindInfoDict.keys());
912
+ result.statementType = statement.statementType;
913
+ return result;
914
+ } finally {
836
915
  this._returnStatement(statement);
837
916
  }
838
-
839
- return result;
840
917
  }
841
918
 
842
919
  //---------------------------------------------------------------------------
843
- // executeMany()
920
+ // execute()
844
921
  //
845
- // Prepares the sql given by the user, calls the OAL8 RPC that executes a SQL
846
- // statement multiple times and returns the results.
922
+ // Calls the RPC that executes a SQL statement and returns the results.
847
923
  //---------------------------------------------------------------------------
848
- async executeMany(sql, numIters, binds, options) {
849
- const statement = await this._prepareAndBind(sql, binds, options);
850
- if (statement.isPlSql && (options.batchErrors || options.dmlRowCounts)) {
851
- errors.throwErr(errors.ERR_EXEC_MODE_ONLY_FOR_DML);
852
- }
853
-
854
- // send database request
855
- const message = new messages.ExecuteMessage(this, statement, options);
856
- message.numExecs = numIters;
857
- message.arrayDmlRowCounts = options.dmlRowCounts;
858
- message.batchErrors = options.batchErrors;
859
- if (statement.isPlSql && statement.requiresFullExecute) {
860
- message.numExecs = 1;
861
- await this._protocol._processMessage(message);
862
- statement.requiresFullExecute = false;
863
- message.numExecs = numIters - 1;
864
- message.offset = 1;
865
- }
866
- if (message.numExecs > 0) {
867
- await this._protocol._processMessage(message);
868
- }
869
-
870
- // process results
871
- const returnObj = {};
872
- statement.bufferRowIndex = 0;
873
- const bindVars = thinUtil.getBindVars(statement);
874
- const outBinds = thinUtil.getExecuteManyOutBinds(bindVars, numIters);
875
- if (outBinds) {
876
- returnObj.outBinds = outBinds;
877
- }
878
- const rowsAffected = !statement.isPlSql ? statement.rowCount : undefined;
879
- if (rowsAffected) {
880
- returnObj.rowsAffected = rowsAffected;
881
- delete statement.rowCount;
882
- }
883
- if (options.dmlRowCounts) {
884
- returnObj.dmlRowCounts = options.dmlRowCounts;
885
- }
886
- if (options.batchErrors) {
887
- returnObj.batchErrors = options.batchErrors;
924
+ async execute(sql, numIters, binds, options, executeManyFlag) {
925
+ const statement = this._prepare(sql, options);
926
+ try {
927
+ return await this._execute(statement, numIters, binds, options,
928
+ executeManyFlag);
929
+ } catch (err) {
930
+ this._returnStatement(statement);
931
+ throw err;
888
932
  }
889
- this._returnStatement(statement);
890
-
891
- return returnObj;
892
933
  }
893
934
 
894
935
  //---------------------------------------------------------------------------
@@ -1038,6 +1079,12 @@ class ThinConnectionImpl extends ConnectionImpl {
1038
1079
  return '';
1039
1080
  }
1040
1081
 
1082
+ //---------------------------------------------------------------------------
1083
+ // Returns the Oracle Database instance name associated with the connection.
1084
+ //---------------------------------------------------------------------------
1085
+ getInstanceName() {
1086
+ return this.instanceName;
1087
+ }
1041
1088
  }
1042
1089
 
1043
1090
  module.exports = ThinConnectionImpl;
@@ -367,7 +367,10 @@ class ThinDbObjectImpl extends DbObjectImpl {
367
367
  case types.DB_TYPE_NCHAR:
368
368
  return buf.readStr(constants.CSFRM_NCHAR);
369
369
  case types.DB_TYPE_RAW:
370
- return Buffer.from(buf.readBytesWithLength());
370
+ value = buf.readBytesWithLength();
371
+ if (value !== null)
372
+ value = Buffer.from(value);
373
+ return value;
371
374
  case types.DB_TYPE_BINARY_DOUBLE:
372
375
  return buf.readBinaryDouble();
373
376
  case types.DB_TYPE_BINARY_FLOAT: