oracledb 6.1.0 → 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 (43) 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/lib/connection.js +1 -1
  13. package/lib/dbObject.js +9 -0
  14. package/lib/errors.js +7 -7
  15. package/lib/oracledb.js +11 -6
  16. package/lib/sodaCollection.js +11 -0
  17. package/lib/sodaOperation.js +16 -0
  18. package/lib/thin/connection.js +138 -153
  19. package/lib/thin/dbObject.js +4 -1
  20. package/lib/thin/protocol/buffer.js +64 -63
  21. package/lib/thin/protocol/messages/base.js +7 -0
  22. package/lib/thin/protocol/messages/withData.js +9 -4
  23. package/lib/thin/protocol/oson.js +13 -10
  24. package/lib/thin/protocol/packet.js +6 -5
  25. package/lib/thin/protocol/utils.js +1 -1
  26. package/lib/thin/sqlnet/ezConnectResolver.js +10 -43
  27. package/lib/thin/sqlnet/navNodes.js +2 -2
  28. package/lib/thin/sqlnet/networkSession.js +13 -19
  29. package/lib/thin/sqlnet/packet.js +1 -1
  30. package/lib/thin/statement.js +345 -113
  31. package/lib/thin/util.js +20 -82
  32. package/lib/util.js +4 -0
  33. package/lib/version.js +1 -1
  34. package/package.json +1 -1
  35. package/build/Release/oracledb-6.1.0-darwin-x64.node +0 -0
  36. package/build/Release/oracledb-6.1.0-darwin-x64.node-buildinfo.txt +0 -1
  37. package/build/Release/oracledb-6.1.0-js-buildinfo.txt +0 -1
  38. package/build/Release/oracledb-6.1.0-linux-arm64.node +0 -0
  39. package/build/Release/oracledb-6.1.0-linux-arm64.node-buildinfo.txt +0 -1
  40. package/build/Release/oracledb-6.1.0-linux-x64.node +0 -0
  41. package/build/Release/oracledb-6.1.0-linux-x64.node-buildinfo.txt +0 -1
  42. package/build/Release/oracledb-6.1.0-win32-x64.node +0 -0
  43. package/build/Release/oracledb-6.1.0-win32-x64.node-buildinfo.txt +0 -1
package/README.md CHANGED
@@ -1,10 +1,10 @@
1
- # node-oracledb version 6.1.0
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.1.0 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
 
package/lib/connection.js CHANGED
@@ -1074,7 +1074,7 @@ class Connection extends EventEmitter {
1074
1074
  //
1075
1075
  // Returns the health status of the connection. If this function returns
1076
1076
  // false, the caller should close the connection.
1077
- // ---------------------------------------------------------------------------
1077
+ //---------------------------------------------------------------------------
1078
1078
  isHealthy() {
1079
1079
  return (this._impl !== undefined && !this._closing &&
1080
1080
  this._impl.isHealthy());
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
@@ -466,7 +466,7 @@ function assertArgCount(args, minArgCount, maxArgCount) {
466
466
  //-----------------------------------------------------------------------------
467
467
  // assertParamPropBool()
468
468
  //
469
- // 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
470
470
  // undefined).
471
471
  //-----------------------------------------------------------------------------
472
472
  function assertParamPropBool(obj, parameterNum, propName) {
@@ -479,7 +479,7 @@ function assertParamPropBool(obj, parameterNum, propName) {
479
479
  //-----------------------------------------------------------------------------
480
480
  // assertParamPropFunction()
481
481
  //
482
- // 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).
483
483
  //-----------------------------------------------------------------------------
484
484
  function assertParamPropFunction(obj, parameterNum, propName) {
485
485
  if (obj[propName] !== undefined) {
@@ -491,7 +491,7 @@ function assertParamPropFunction(obj, parameterNum, propName) {
491
491
  //-----------------------------------------------------------------------------
492
492
  // assertParamPropInt()
493
493
  //
494
- // 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
495
495
  // undefined).
496
496
  //-----------------------------------------------------------------------------
497
497
  function assertParamPropInt(obj, parameterNum, propName) {
@@ -504,7 +504,7 @@ function assertParamPropInt(obj, parameterNum, propName) {
504
504
  //-----------------------------------------------------------------------------
505
505
  // assertParamPropUnsignedInt()
506
506
  //
507
- // 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
508
508
  // (or undefined).
509
509
  //-----------------------------------------------------------------------------
510
510
  function assertParamPropUnsignedInt(obj, parameterNum, propName) {
@@ -517,7 +517,7 @@ function assertParamPropUnsignedInt(obj, parameterNum, propName) {
517
517
  //-----------------------------------------------------------------------------
518
518
  // assertParamPropString()
519
519
  //
520
- // 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).
521
521
  //-----------------------------------------------------------------------------
522
522
  function assertParamPropString(obj, parameterNum, propName) {
523
523
  if (obj[propName] !== undefined) {
@@ -529,7 +529,7 @@ function assertParamPropString(obj, parameterNum, propName) {
529
529
  //-----------------------------------------------------------------------------
530
530
  // assertParamPropValue()
531
531
  //
532
- // Asserts that the property value of a parmeter passes the specified
532
+ // Asserts that the property value of a parameter passes the specified
533
533
  // condition.
534
534
  //-----------------------------------------------------------------------------
535
535
  function assertParamPropValue(condition, parameterNum, propName) {
@@ -540,7 +540,7 @@ function assertParamPropValue(condition, parameterNum, propName) {
540
540
  //-----------------------------------------------------------------------------
541
541
  // assertParamValue()
542
542
  //
543
- // Asserts that the parmeter value passes the specified condition.
543
+ // Asserts that the parameter value passes the specified condition.
544
544
  //-----------------------------------------------------------------------------
545
545
  function assertParamValue(condition, parameterNum) {
546
546
  assert(condition, ERR_INVALID_PARAMETER_VALUE, parameterNum);
package/lib/oracledb.js CHANGED
@@ -69,22 +69,26 @@ const defaultPoolAlias = 'default';
69
69
  let _initOracleClientArgs;
70
70
 
71
71
  // Load the Oracledb binary
72
- function _initCLib() {
72
+ function _initCLib(options) {
73
73
  /*global __non_webpack_require__*/ // quieten eslint
74
74
  const requireBinary = (typeof __non_webpack_require__ === 'function') ? __non_webpack_require__ : require; // See Issue 1156
75
-
76
75
  const binaryLocations = [
77
76
  '../' + 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
77
+ '../' + nodbUtil.RELEASE_DIR + '/' + nodbUtil.BUILD_FILE, // binary built from source
78
+ '../build/Debug/' + nodbUtil.BUILD_FILE, // debug binary
80
79
  // Paths for Webpack.
81
80
  // Note: to use node-oracledb Thick mode, you will need a Webpack copy plugin to
82
81
  // copy 'node_modules/oracledb/build/' to the output directory,
83
82
  // see https://github.com/oracle/node-oracledb/issues/1156
84
83
  // If you want to use only node-oracledb Thin mode, a copy plugin is not needed.
85
84
  './node_modules/oracledb/' + nodbUtil.RELEASE_DIR + '/' + nodbUtil.BINARY_FILE,
86
- './node_modules/oracledb/' + nodbUtil.RELEASE_DIR + '/' + 'oracledb.node'
85
+ './node_modules/oracledb/' + nodbUtil.RELEASE_DIR + '/' + nodbUtil.BUILD_FILE
87
86
  ];
87
+
88
+ if (options.binaryDir !== undefined) {
89
+ binaryLocations.splice(0, 0, options.binaryDir + '/' + nodbUtil.BINARY_FILE,
90
+ options.binaryDir + '/' + nodbUtil.BUILD_FILE);
91
+ }
88
92
  let oracledbCLib;
89
93
  for (let i = 0; i < binaryLocations.length; i++) {
90
94
  try {
@@ -682,12 +686,13 @@ function initOracleClient(arg1) {
682
686
  errors.assertParamPropString(options, 1, "configDir");
683
687
  errors.assertParamPropString(options, 1, "errorUrl");
684
688
  errors.assertParamPropString(options, 1, "driverName");
689
+ errors.assertParamPropString(options, 1, "binaryDir");
685
690
  }
686
691
  if (settings.thinDriverInitialized) {
687
692
  errors.throwErr(errors.ERR_THIN_CONNECTION_ALREADY_CREATED);
688
693
  }
689
694
  if (_initOracleClientArgs === undefined) {
690
- const oracledbCLib = _initCLib();
695
+ const oracledbCLib = _initCLib(options);
691
696
  if (options.driverName === undefined)
692
697
  options.driverName = constants.DEFAULT_DRIVER_NAME + " thk";
693
698
  if (options.errorUrl === undefined)
@@ -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
  //
@@ -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,98 @@ 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 (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
+
156
254
  //---------------------------------------------------------------------------
157
255
  // _parseElementType()
158
256
  //
@@ -772,26 +870,6 @@ class ThinConnectionImpl extends ConnectionImpl {
772
870
  return resultSet;
773
871
  }
774
872
 
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
873
  //---------------------------------------------------------------------------
796
874
  // Clears the statement cache for the connection
797
875
  //---------------------------------------------------------------------------
@@ -812,139 +890,46 @@ class ThinConnectionImpl extends ConnectionImpl {
812
890
  }
813
891
 
814
892
  //---------------------------------------------------------------------------
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.
893
+ // getStatementInfo()
894
+ //
895
+ // Parses the SQL statement and returns information about the statement.
818
896
  //---------------------------------------------------------------------------
819
897
  async getStatementInfo(sql) {
820
898
  const options = {};
821
899
  const result = {};
822
- const statement = await this._prepareAndBind(sql, null, options, true);
900
+ const statement = this._prepare(sql, options);
823
901
  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;
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);
888
907
  }
889
- if (statement.rowCount) {
890
- delete statement.rowCount;
908
+ if (statement.numQueryVars > 0) {
909
+ result.metaData = thinUtil.getMetadataMany(statement.queryVars);
891
910
  }
911
+ result.bindNames = Array.from(statement.bindInfoDict.keys());
912
+ result.statementType = statement.statementType;
913
+ return result;
914
+ } finally {
892
915
  this._returnStatement(statement);
893
916
  }
894
-
895
- return result;
896
917
  }
897
918
 
898
919
  //---------------------------------------------------------------------------
899
- // executeMany()
920
+ // execute()
900
921
  //
901
- // Prepares the sql given by the user, calls the OAL8 RPC that executes a SQL
902
- // statement multiple times and returns the results.
922
+ // Calls the RPC that executes a SQL statement and returns the results.
903
923
  //---------------------------------------------------------------------------
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;
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;
944
932
  }
945
- this._returnStatement(statement);
946
-
947
- return returnObj;
948
933
  }
949
934
 
950
935
  //---------------------------------------------------------------------------
@@ -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: