oracledb 5.5.0 → 6.0.1

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 (107) hide show
  1. package/CHANGELOG.md +1 -1875
  2. package/LICENSE.txt +8 -222
  3. package/NOTICE.txt +1 -1
  4. package/README.md +38 -30
  5. package/SECURITY.md +38 -0
  6. package/build/Release/oracledb-6.0.1-darwin-x64.node +0 -0
  7. package/build/Release/oracledb-6.0.1-darwin-x64.node-buildinfo.txt +1 -0
  8. package/build/Release/oracledb-6.0.1-js-buildinfo.txt +1 -0
  9. package/build/Release/oracledb-6.0.1-linux-arm64.node +0 -0
  10. package/build/Release/oracledb-6.0.1-linux-arm64.node-buildinfo.txt +1 -0
  11. package/build/Release/oracledb-6.0.1-linux-x64.node +0 -0
  12. package/build/Release/oracledb-6.0.1-linux-x64.node-buildinfo.txt +1 -0
  13. package/build/Release/oracledb-6.0.1-win32-x64.node +0 -0
  14. package/build/Release/oracledb-6.0.1-win32-x64.node-buildinfo.txt +1 -0
  15. package/examples/README.md +113 -0
  16. package/examples/dbconfig.js +100 -0
  17. package/examples/example.js +156 -0
  18. package/index.js +26 -0
  19. package/lib/aqDeqOptions.js +148 -8
  20. package/lib/aqEnqOptions.js +59 -7
  21. package/lib/aqMessage.js +118 -7
  22. package/lib/aqQueue.js +243 -53
  23. package/lib/connection.js +1326 -465
  24. package/lib/constants.js +203 -0
  25. package/lib/dbObject.js +346 -32
  26. package/lib/errors.js +785 -0
  27. package/lib/impl/aqDeqOptions.js +197 -0
  28. package/lib/impl/aqEnqOptions.js +89 -0
  29. package/lib/impl/aqMessage.js +134 -0
  30. package/lib/impl/aqQueue.js +81 -0
  31. package/lib/impl/connection.js +529 -0
  32. package/lib/impl/dbObject.js +159 -0
  33. package/lib/impl/index.js +59 -0
  34. package/lib/impl/lob.js +85 -0
  35. package/lib/impl/pool.js +195 -0
  36. package/lib/impl/resultset.js +223 -0
  37. package/lib/impl/sodaCollection.js +174 -0
  38. package/lib/impl/sodaDatabase.js +81 -0
  39. package/lib/impl/sodaDocCursor.js +63 -0
  40. package/lib/impl/sodaDocument.js +98 -0
  41. package/lib/impl/sodaOperation.js +109 -0
  42. package/lib/lob.js +157 -68
  43. package/lib/oracledb.js +1047 -345
  44. package/lib/pool.js +654 -465
  45. package/lib/poolStatistics.js +24 -9
  46. package/lib/queryStream.js +16 -8
  47. package/lib/resultset.js +291 -183
  48. package/lib/settings.js +191 -0
  49. package/lib/sodaCollection.js +214 -201
  50. package/lib/sodaDatabase.js +108 -71
  51. package/lib/sodaDocCursor.js +44 -32
  52. package/lib/sodaDocument.js +76 -14
  53. package/lib/sodaOperation.js +131 -118
  54. package/lib/thin/connection.js +1043 -0
  55. package/lib/thin/dbObject.js +630 -0
  56. package/lib/thin/index.js +40 -0
  57. package/lib/thin/lob.js +189 -0
  58. package/lib/thin/pool.js +481 -0
  59. package/lib/thin/protocol/buffer.js +1043 -0
  60. package/lib/thin/protocol/capabilities.js +121 -0
  61. package/lib/thin/protocol/constants.js +765 -0
  62. package/lib/thin/protocol/encryptDecrypt.js +185 -0
  63. package/lib/thin/protocol/messages/auth.js +349 -0
  64. package/lib/thin/protocol/messages/base.js +476 -0
  65. package/lib/thin/protocol/messages/commit.js +56 -0
  66. package/lib/thin/protocol/messages/dataType.js +391 -0
  67. package/lib/thin/protocol/messages/execute.js +312 -0
  68. package/lib/thin/protocol/messages/fetch.js +60 -0
  69. package/lib/thin/protocol/messages/index.js +53 -0
  70. package/lib/thin/protocol/messages/lobOp.js +201 -0
  71. package/lib/thin/protocol/messages/logOff.js +53 -0
  72. package/lib/thin/protocol/messages/ping.js +56 -0
  73. package/lib/thin/protocol/messages/protocol.js +78 -0
  74. package/lib/thin/protocol/messages/rollback.js +56 -0
  75. package/lib/thin/protocol/messages/sessionRelease.js +60 -0
  76. package/lib/thin/protocol/messages/withData.js +812 -0
  77. package/lib/thin/protocol/oson.js +661 -0
  78. package/lib/thin/protocol/packet.js +519 -0
  79. package/lib/thin/protocol/protocol.js +202 -0
  80. package/lib/thin/protocol/utils.js +89 -0
  81. package/lib/thin/resultSet.js +122 -0
  82. package/lib/thin/sqlnet/connStrategy.js +175 -0
  83. package/lib/thin/sqlnet/constants.js +199 -0
  84. package/lib/thin/sqlnet/ezConnectResolver.js +488 -0
  85. package/lib/thin/sqlnet/navNodes.js +870 -0
  86. package/lib/thin/sqlnet/networkSession.js +621 -0
  87. package/lib/thin/sqlnet/ntTcp.js +527 -0
  88. package/lib/thin/sqlnet/nvStrToNvPair.js +783 -0
  89. package/lib/thin/sqlnet/packet.js +405 -0
  90. package/lib/thin/sqlnet/paramParser.js +206 -0
  91. package/lib/thin/sqlnet/sessionAtts.js +160 -0
  92. package/lib/thin/statement.js +300 -0
  93. package/lib/thin/util.js +289 -0
  94. package/lib/transformer.js +252 -0
  95. package/lib/types.js +357 -0
  96. package/lib/util.js +196 -110
  97. package/lib/version.js +36 -0
  98. package/package/README.md +33 -30
  99. package/package/install.js +89 -64
  100. package/package/prunebinaries.js +60 -12
  101. package/package.json +3 -3
  102. package/build/Release/oracledb-5.5.0-darwin-x64.node +0 -0
  103. package/build/Release/oracledb-5.5.0-darwin-x64.node-buildinfo.txt +0 -1
  104. package/build/Release/oracledb-5.5.0-linux-x64.node +0 -0
  105. package/build/Release/oracledb-5.5.0-linux-x64.node-buildinfo.txt +0 -1
  106. package/build/Release/oracledb-5.5.0-win32-x64.node +0 -0
  107. package/build/Release/oracledb-5.5.0-win32-x64.node-buildinfo.txt +0 -1
package/lib/connection.js CHANGED
@@ -1,17 +1,24 @@
1
- // Copyright (c) 2016, 2022, Oracle and/or its affiliates.
1
+ // Copyright (c) 2016, 2023, Oracle and/or its affiliates.
2
2
 
3
3
  //-----------------------------------------------------------------------------
4
4
  //
5
- // You may not use the identified files except in compliance with the Apache
6
- // License, Version 2.0 (the "License.")
5
+ // This software is dual-licensed to you under the Universal Permissive License
6
+ // (UPL) 1.0 as shown at https://oss.oracle.com/licenses/upl and Apache License
7
+ // 2.0 as shown at http://www.apache.org/licenses/LICENSE-2.0. You may choose
8
+ // either license.
7
9
  //
10
+ // If you elect to accept the software under the Apache License, Version 2.0,
11
+ // the following applies:
12
+ //
13
+ // Licensed under the Apache License, Version 2.0 (the "License");
14
+ // you may not use this file except in compliance with the License.
8
15
  // You may obtain a copy of the License at
9
- // http://www.apache.org/licenses/LICENSE-2.0.
10
16
  //
11
- // Unless required by applicable law or agreed to in writing, software
12
- // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
13
- // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
+ // https://www.apache.org/licenses/LICENSE-2.0
14
18
  //
19
+ // Unless required by applicable law or agreed to in writing, software
20
+ // distributed under the License is distributed on an "AS IS" BASIS,
21
+ // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15
22
  // See the License for the specific language governing permissions and
16
23
  // limitations under the License.
17
24
  //
@@ -19,589 +26,1121 @@
19
26
 
20
27
  'use strict';
21
28
 
29
+ const AqQueue = require('./aqQueue.js');
22
30
  const BaseDbObject = require('./dbObject.js');
31
+ const { Buffer } = require('buffer');
32
+ const Lob = require('./lob.js');
33
+ const ResultSet = require('./resultset.js');
34
+ const SodaDatabase = require('./sodaDatabase.js');
23
35
  const EventEmitter = require('events');
24
36
  const QueryStream = require('./queryStream.js');
37
+ const errors = require('./errors.js');
25
38
  const nodbUtil = require('./util.js');
39
+ const impl = require('./impl');
40
+ const process = require('process');
26
41
  const util = require('util');
42
+ const constants = require('./constants.js');
43
+ const settings = require('./settings.js');
44
+ const transformer = require('./transformer.js');
45
+ const types = require('./types.js');
27
46
 
28
- //-----------------------------------------------------------------------------
29
- // execute()
30
- // Executes a SQL statement and returns the results.
31
- //-----------------------------------------------------------------------------
32
- async function execute(sql, a2, a3) {
33
- let binds = [];
34
- let executeOpts = {};
35
-
36
- nodbUtil.checkArgCount(arguments, 1, 3);
37
- nodbUtil.assert(typeof sql === 'string', 'NJS-005', 1);
38
-
39
- switch (arguments.length) {
40
- case 2:
41
- nodbUtil.assert(nodbUtil.isObjectOrArray(a2), 'NJS-005', 2);
42
- binds = a2;
43
- break;
44
- case 3:
45
- nodbUtil.assert(nodbUtil.isObjectOrArray(a2), 'NJS-005', 2);
46
- nodbUtil.assert(nodbUtil.isObject(a3), 'NJS-005', 3);
47
- binds = a2;
48
- executeOpts = a3;
49
- break;
50
- }
51
-
52
- const result = await this._execute(sql, binds, executeOpts);
53
-
54
- // process queries; if a result set is not desired, fetch all of the rows
55
- // from the result set and then destroy the result set
56
- if (result.resultSet && !executeOpts.resultSet) {
57
- result.rows = await result.resultSet._getAllRows(executeOpts, result);
58
- delete result.resultSet;
59
- }
60
-
61
- // process implicit results; ensure all implicit results have their fetch
62
- // array size fixed, or, if a result set is not requested, that all rows are
63
- // fetched
64
- if (result.implicitResults) {
65
- for (const key in result.implicitResults) {
66
- const implicitResult = result.implicitResults[key];
67
- if (!executeOpts.resultSet) {
68
- result.implicitResults[key] =
69
- await implicitResult._getAllRows(executeOpts);
47
+ // global mapping of subscriptions; these cannot be tied to a particular
48
+ // connection or pool since subscriptions can be created with one connection
49
+ // and destroyed with another!
50
+ const _subscriptions = new Map();
51
+
52
+ // define class
53
+ class Connection extends EventEmitter {
54
+
55
+ constructor() {
56
+ super();
57
+ this._dbObjectClasses = new Map();
58
+ this._closing = false;
59
+ }
60
+
61
+ //---------------------------------------------------------------------------
62
+ // _addDefaultsToExecOpts()
63
+ //
64
+ // Add values to the execute options from the global settings, if needed.
65
+ //---------------------------------------------------------------------------
66
+ _addDefaultsToExecOpts(options) {
67
+ options.connection = this;
68
+ if (options.keepInStmtCache === undefined)
69
+ options.keepInStmtCache = true;
70
+ settings.addToOptions(options,
71
+ "autoCommit",
72
+ "dbObjectAsPojo",
73
+ "fetchArraySize",
74
+ "fetchTypeHandler",
75
+ "maxRows",
76
+ "outFormat",
77
+ "prefetchRows");
78
+ }
79
+
80
+ //---------------------------------------------------------------------------
81
+ // _buildDbObjectClass()
82
+ //
83
+ // Builds and returns a database object class given the object type
84
+ // information supplied by the implementation.
85
+ //---------------------------------------------------------------------------
86
+ _buildDbObjectClass(objType) {
87
+ const DbObject = function(initialValue) {
88
+ this._impl = new impl.DbObjectImpl(objType);
89
+ if (this.isCollection) {
90
+ const proxy = new Proxy(this, BaseDbObject._collectionProxyHandler);
91
+ if (initialValue !== undefined) {
92
+ for (let i = 0; i < initialValue.length; i++) {
93
+ this.append(initialValue[i]);
94
+ }
95
+ }
96
+ return (proxy);
97
+ } else if (initialValue !== undefined) {
98
+ Object.assign(this, initialValue);
99
+ }
100
+ };
101
+ DbObject.prototype = Object.create(BaseDbObject.prototype);
102
+ DbObject.prototype.constructor = DbObject;
103
+ DbObject.prototype._objType = objType;
104
+ if (objType.elementTypeClass) {
105
+ const cls = this._getDbObjectClass(objType.elementTypeClass);
106
+ objType.elementTypeClass = cls;
107
+ }
108
+ nodbUtil.addTypeProperties(objType, "elementType");
109
+ if (objType.attributes) {
110
+ const props = {};
111
+ for (const attr of objType.attributes) {
112
+ if (attr.typeClass) {
113
+ attr.typeClass = this._getDbObjectClass(attr.typeClass);
114
+ }
115
+ nodbUtil.addTypeProperties(attr, "type");
116
+ const prop = {
117
+ get() {
118
+ return this._getAttrValue(attr);
119
+ },
120
+ set(value) {
121
+ this._setAttrValue(attr, value);
122
+ }
123
+ };
124
+ props[attr.name] = prop;
70
125
  }
126
+ Object.defineProperties(DbObject.prototype, props);
71
127
  }
128
+ DbObject.toString = function() {
129
+ return ('DbObjectClass [' + objType.fqn + ']');
130
+ };
131
+ return (DbObject);
72
132
  }
73
133
 
74
- return (result);
75
- }
76
-
134
+ //---------------------------------------------------------------------------
135
+ // _getDbObjectClass()
136
+ //
137
+ // Returns the database object class given the object type information
138
+ // supplied by the implementation. The cache is searched first to see if an
139
+ // object class has already been built.
140
+ //---------------------------------------------------------------------------
141
+ _getDbObjectClass(objType) {
142
+ if (objType.prototype instanceof BaseDbObject)
143
+ return objType;
144
+ let cls = this._dbObjectClasses.get(objType);
145
+ if (!cls) {
146
+ cls = this._buildDbObjectClass(objType);
147
+ cls._connection = this;
148
+ cls._objType = objType;
149
+ this._dbObjectClasses.set(objType, cls);
150
+ }
151
+ return (cls);
152
+ }
77
153
 
78
- //-----------------------------------------------------------------------------
79
- // executeMany()
80
- // Executes a SQL statement multiple times and returns the results.
81
- //-----------------------------------------------------------------------------
82
- async function executeMany(sql, bindsOrNumIters, a3) {
83
- let options = {};
154
+ //---------------------------------------------------------------------------
155
+ // _getDbObjectClassForName()
156
+ //
157
+ // Returns the database object class given the name of the database object
158
+ // type. The cache is searched first to see if an object class has already
159
+ // been built.
160
+ //---------------------------------------------------------------------------
161
+ async _getDbObjectClassForName(name) {
162
+ let cls = this._dbObjectClasses.get(name);
163
+ if (!cls) {
164
+ const objType = await this._impl.getDbObjectClass(name);
165
+ cls = this._getDbObjectClass(objType);
166
+ this._dbObjectClasses.set(name, cls);
167
+ }
168
+ return cls;
169
+ }
84
170
 
85
- nodbUtil.checkArgCount(arguments, 2, 3);
86
- nodbUtil.assert(typeof sql === 'string', 'NJS-005', 1);
87
- if (typeof bindsOrNumIters === 'number') {
88
- nodbUtil.assert(Number.isInteger(bindsOrNumIters), 'NJS-005', 2);
89
- nodbUtil.assert(bindsOrNumIters > 0, 'NJS-005', 2);
90
- } else {
91
- nodbUtil.assert(Array.isArray(bindsOrNumIters), 'NJS-005', 2);
92
- nodbUtil.assert(bindsOrNumIters.length > 0, 'NJS-005', 2);
171
+ //---------------------------------------------------------------------------
172
+ // _isBindDir()
173
+ //
174
+ // Returns a boolean indicating if the supplied value is a valid bind
175
+ // direction.
176
+ //---------------------------------------------------------------------------
177
+ _isBindDir(value) {
178
+ return (
179
+ value === constants.BIND_IN ||
180
+ value === constants.BIND_OUT ||
181
+ value === constants.BIND_INOUT
182
+ );
93
183
  }
94
184
 
95
- if (arguments.length == 3) {
96
- nodbUtil.assert(nodbUtil.isObject(a3), 'NJS-005', 3);
97
- options = a3;
185
+ //---------------------------------------------------------------------------
186
+ // _isBindValue()
187
+ //
188
+ // Returns a boolean indicating if the supplied value is one that can be
189
+ // bound.
190
+ //---------------------------------------------------------------------------
191
+ _isBindValue(value) {
192
+ return (
193
+ value === null ||
194
+ value === undefined ||
195
+ typeof value === 'number' ||
196
+ typeof value === 'string' ||
197
+ typeof value === 'boolean' ||
198
+ Array.isArray(value) ||
199
+ Buffer.isBuffer(value) ||
200
+ util.isDate(value) ||
201
+ value instanceof Lob ||
202
+ value instanceof ResultSet ||
203
+ value instanceof BaseDbObject
204
+ );
98
205
  }
99
206
 
100
- return (await this._executeMany(sql, bindsOrNumIters, options));
101
- }
207
+ //---------------------------------------------------------------------------
208
+ // _processBindUnit()
209
+ //
210
+ // Processes a bind unit (object) supplied by the user and returns the value
211
+ // stored in it (if one is).
212
+ //---------------------------------------------------------------------------
213
+ async _processBindUnit(bindInfo, bindUnit, inExecuteMany) {
214
+ let okBindUnit = false;
102
215
 
216
+ // get and validate bind direction; if not specified, IN is assumed
217
+ if (bindUnit.dir === undefined) {
218
+ bindInfo.dir = constants.BIND_IN;
219
+ } else {
220
+ errors.assert(this._isBindDir(bindUnit.dir),
221
+ errors.ERR_INVALID_BIND_DIRECTION);
222
+ bindInfo.dir = bindUnit.dir;
223
+ okBindUnit = true;
224
+ }
103
225
 
104
- //-----------------------------------------------------------------------------
105
- // getDbObjectClass()
106
- // Returns a database object class given its name. The cache is searched
107
- // first, but if not found, the database is queried and the result is cached
108
- // using the fully qualified name.
109
- //-----------------------------------------------------------------------------
110
- async function getDbObjectClass(name) {
111
- nodbUtil.checkArgCount(arguments, 1, 1);
112
- nodbUtil.assert(typeof name === 'string', 'NJS-005', 1);
226
+ // get and validate bind type; it must be one of the integer constants
227
+ // identifying types, a string identifying an object type or a constructor
228
+ // function identifying an object type
229
+ if (bindUnit.type !== undefined) {
230
+ if (typeof bindUnit.type === 'string') {
231
+ bindInfo.type = types.DB_TYPE_OBJECT;
232
+ bindInfo.typeClass = await this._getDbObjectClassForName(bindUnit.type);
233
+ bindInfo.objType = bindInfo.typeClass._objType;
234
+ } else if (bindUnit.type.prototype instanceof BaseDbObject) {
235
+ bindInfo.type = types.DB_TYPE_OBJECT;
236
+ bindInfo.typeClass = bindUnit.type;
237
+ bindInfo.objType = bindInfo.typeClass._objType;
238
+ } else {
239
+ errors.assert(bindUnit.type instanceof types.DbType,
240
+ errors.ERR_INVALID_BIND_DATA_TYPE, 2);
241
+ bindInfo.type = bindUnit.type;
242
+ }
243
+ okBindUnit = true;
113
244
 
114
- let cls = this._dbObjectClasses[name];
115
- if (cls) {
116
- return cls;
117
- }
118
- return (await this._getDbObjectClass(name));
119
- }
245
+ // when calling executeMany(), bind type is mandatory
246
+ } else if (inExecuteMany) {
247
+ if (bindInfo.name)
248
+ errors.throwErr(errors.ERR_MISSING_TYPE_BY_NAME, bindInfo.name);
249
+ errors.throwErr(errors.ERR_MISSING_TYPE_BY_POS, bindInfo.pos);
250
+ }
120
251
 
252
+ // get and validate the maximum size for strings/buffers; this value is
253
+ // used for IN/OUT and OUT binds in execute() and at all times for
254
+ // executeMany()
255
+ if (bindInfo.dir !== constants.BIND_IN || inExecuteMany) {
256
+ if (bindUnit.maxSize !== undefined) {
257
+ errors.assertParamPropValue(Number.isInteger(bindUnit.maxSize) &&
258
+ bindUnit.maxSize > 0, 2, "maxSize");
259
+ bindInfo.maxSize = bindUnit.maxSize;
260
+ bindInfo.checkSize = true;
261
+ okBindUnit = true;
262
+ } else if (inExecuteMany) {
263
+ if (bindInfo.type === types.DB_TYPE_VARCHAR ||
264
+ bindInfo.type === types.DB_TYPE_RAW) {
265
+ if (bindInfo.name)
266
+ errors.throwErr(errors.ERR_MISSING_MAX_SIZE_BY_NAME, bindInfo.name);
267
+ errors.throwErr(errors.ERR_MISSING_MAX_SIZE_BY_POS, bindInfo.pos);
268
+ }
269
+ } else {
270
+ bindInfo.maxSize = constants.DEFAULT_MAX_SIZE_FOR_OUT_BINDS;
271
+ }
272
+ }
121
273
 
122
- //-----------------------------------------------------------------------------
123
- // getStatementInfo()
124
- // Returns information about the statement.
125
- //-----------------------------------------------------------------------------
126
- async function getStatementInfo(sql) {
127
- nodbUtil.checkArgCount(arguments, 1, 1);
128
- return (await this._getStatementInfo(sql));
129
- }
274
+ // get max array size (for array binds, not possible in executeMany())
275
+ bindInfo.isArray = false;
276
+ if (!inExecuteMany) {
277
+ if (bindUnit.maxArraySize !== undefined) {
278
+ errors.assertParamPropValue(Number.isInteger(bindUnit.maxArraySize) &&
279
+ bindUnit.maxArraySize > 0, 2, "maxArraySize");
280
+ bindInfo.maxArraySize = bindUnit.maxArraySize;
281
+ bindInfo.isArray = true;
282
+ }
283
+ }
130
284
 
285
+ // get the value, if specified (not used in executeMany())
286
+ if (!inExecuteMany && bindUnit.val !== undefined) {
287
+ return bindUnit.val;
288
+ }
131
289
 
132
- //-----------------------------------------------------------------------------
133
- // commit()
134
- // Commits the current transaction.
135
- //-----------------------------------------------------------------------------
136
- async function commit() {
137
- nodbUtil.checkArgCount(arguments, 0, 0);
138
- await this._commit();
139
- }
290
+ if (!okBindUnit)
291
+ errors.throwErr(errors.ERR_INVALID_BIND_UNIT);
292
+ }
140
293
 
294
+ //---------------------------------------------------------------------------
295
+ // _processBindValue()
296
+ //
297
+ // Processes the bind value supplied by the caller. This performs all checks
298
+ // on the value and normalizes it for use by the implementation class. If no
299
+ // bind info has been defined yet, the value defines that.
300
+ //---------------------------------------------------------------------------
301
+ async _processBindValue(bindInfo, value, options) {
302
+ const transformed = transformer.transformValueIn(bindInfo, value, options);
303
+ if (bindInfo.isArray) {
304
+ bindInfo.values = transformed.concat(bindInfo.values.slice(transformed.length));
305
+ } else {
306
+ bindInfo.values[options.pos] = transformed;
307
+ }
308
+ if (bindInfo.type === types.DB_TYPE_OBJECT &&
309
+ bindInfo.typeClass === undefined) {
310
+ bindInfo.typeClass = await this._getDbObjectClass(value._objType);
311
+ bindInfo.objType = bindInfo.typeClass._objType;
312
+ }
313
+ }
141
314
 
142
- //-----------------------------------------------------------------------------
143
- // createLob()
144
- // Creates a temporary LOB and returns it to the caller.
145
- //-----------------------------------------------------------------------------
146
- async function createLob(type) {
147
- nodbUtil.checkArgCount(arguments, 1, 1);
148
- nodbUtil.assert(typeof type === 'number', 'NJS-005', 1);
149
- return (await this._createLob(type));
150
- }
315
+ //---------------------------------------------------------------------------
316
+ // _processExecuteBind()
317
+ //
318
+ // Processes a single execute bind supplied by the caller. This performs all
319
+ // checks on the bind and normalizes it for use by the implementation class.
320
+ //---------------------------------------------------------------------------
321
+ async _processExecuteBind(bindInfo, bindData) {
151
322
 
323
+ // setup defaults
324
+ bindInfo.isArray = false;
152
325
 
153
- //-----------------------------------------------------------------------------
154
- // rollback()
155
- // Rolls back the current transaction.
156
- //-----------------------------------------------------------------------------
157
- async function rollback() {
158
- nodbUtil.checkArgCount(arguments, 0, 0);
159
- await this._rollback();
160
- }
326
+ // if bind data is a value that can be bound directly, use it; otherwise,
327
+ // scan the bind unit for bind information and its value
328
+ let bindValue;
329
+ if (this._isBindValue(bindData)) {
330
+ bindInfo.dir = constants.BIND_IN;
331
+ bindValue = bindData;
332
+ } else {
333
+ bindValue = await this._processBindUnit(bindInfo, bindData, false);
334
+ }
161
335
 
336
+ // for IN and IN/OUT binds, process the value
337
+ if (bindInfo.dir !== constants.BIND_OUT) {
338
+ const options = {pos: 0, allowArray: true};
339
+ await this._processBindValue(bindInfo, bindValue, options);
340
+ }
162
341
 
163
- //-----------------------------------------------------------------------------
164
- // close()
165
- // Closes the connection and makes it unusable for further work.
166
- //-----------------------------------------------------------------------------
167
- async function close(a1) {
168
- let options = {};
342
+ // if only null values were found (or an OUT bind was specified), type
343
+ // information may not be set, so complete bind information as a string
344
+ // and set the maxSize to 1 if it has not already been set
345
+ if (bindInfo.type === undefined) {
346
+ bindInfo.type = types.DB_TYPE_VARCHAR;
347
+ if (bindInfo.maxSize === undefined)
348
+ bindInfo.maxSize = 1;
349
+ }
169
350
 
170
- nodbUtil.checkArgCount(arguments, 0, 1);
171
- if (arguments.length == 1) {
172
- nodbUtil.assert(nodbUtil.isObject(a1), 'NJS-005', 1);
173
- options = a1;
174
- }
351
+ // check valid bind type for array binds
352
+ if (bindInfo.isArray &&
353
+ bindInfo.type !== types.DB_TYPE_VARCHAR &&
354
+ bindInfo.type !== types.DB_TYPE_NVARCHAR &&
355
+ bindInfo.type !== types.DB_TYPE_CHAR &&
356
+ bindInfo.type !== types.DB_TYPE_NCHAR &&
357
+ bindInfo.type !== types.DB_TYPE_NUMBER &&
358
+ bindInfo.type !== types.DB_TYPE_BINARY_FLOAT &&
359
+ bindInfo.type !== types.DB_TYPE_BINARY_DOUBLE &&
360
+ bindInfo.type !== types.DB_TYPE_DATE &&
361
+ bindInfo.type !== types.DB_TYPE_TIMESTAMP &&
362
+ bindInfo.type !== types.DB_TYPE_TIMESTAMP_LTZ &&
363
+ bindInfo.type !== types.DB_TYPE_TIMESTAMP_TZ &&
364
+ bindInfo.type !== types.DB_TYPE_RAW) {
365
+ errors.throwErr(errors.ERR_INVALID_TYPE_FOR_ARRAY_BIND);
366
+ }
175
367
 
176
- // If already in the process of closing, throw an error instead of doing
177
- // a roundtrip
178
- if (this._closing) {
179
- throw new Error (nodbUtil.getErrorMessage('NJS-003'));
180
368
  }
181
369
 
182
- this._closing = true;
183
- try {
184
- await this._close(options);
185
- } finally {
186
- this._closing = false;
370
+ //---------------------------------------------------------------------------
371
+ // _processExecuteBinds()
372
+ //
373
+ // Processes the binds supplied by the caller. This performs all checks on
374
+ // the binds and normalizes them for use by the implementation class.
375
+ //---------------------------------------------------------------------------
376
+ async _processExecuteBinds(binds) {
377
+ const normBinds = [];
378
+ if (Array.isArray(binds)) {
379
+ for (let i = 0; i < binds.length; i++) {
380
+ const bindInfo = normBinds[i] = {pos: i + 1, values: []};
381
+ await this._processExecuteBind(bindInfo, binds[i]);
382
+ }
383
+ } else {
384
+ errors.assertParamValue(nodbUtil.isObject(binds), 2);
385
+ const bindNames = Object.getOwnPropertyNames(binds);
386
+ for (let i = 0; i < bindNames.length; i++) {
387
+ const bindInfo = normBinds[i] = {name: bindNames[i], values: []};
388
+ await this._processExecuteBind(bindInfo, binds[bindNames[i]]);
389
+ }
390
+ }
391
+ return normBinds;
187
392
  }
188
393
 
189
- for (const cls of Object.values(this._dbObjectClasses)) {
190
- cls.prototype.constructor = Object;
191
- cls.prototype = null;
192
- }
193
- this.emit('_afterConnClose');
194
- }
394
+ //---------------------------------------------------------------------------
395
+ // _processExecuteManyBinds()
396
+ //
397
+ // Processes the binds supplied by the caller. This performs all checks on
398
+ // the binds and normalizes them for use by the implementation class.
399
+ //---------------------------------------------------------------------------
400
+ async _processExecuteManyBinds(binds, bindDefs) {
401
+ const normBinds = [];
402
+ let byPosition;
403
+
404
+ // transform bindDefs into normalized binds, if available
405
+ if (bindDefs !== undefined) {
406
+ if (Array.isArray(bindDefs)) {
407
+ byPosition = true;
408
+ for (let i = 0; i < bindDefs.length; i++) {
409
+ const bindInfo = normBinds[i] = {pos: i + 1, values: []};
410
+ await this._processBindUnit(bindInfo, bindDefs[i], true);
411
+ }
412
+ } else {
413
+ byPosition = false;
414
+ const bindNames = Object.getOwnPropertyNames(bindDefs);
415
+ for (let i = 0; i < bindNames.length; i++) {
416
+ const bindInfo = normBinds[i] = {name: bindNames[i], values: []};
417
+ await this._processBindUnit(bindInfo, bindDefs[bindNames[i]], true);
418
+ }
419
+ }
195
420
 
421
+ // otherwise, use the first row to determine the binds to use
422
+ } else {
423
+ const row = binds[0];
424
+ errors.assertParamValue(nodbUtil.isObjectOrArray(row), 2);
425
+ if (Array.isArray(row)) {
426
+ byPosition = true;
427
+ for (let i = 0; i < row.length; i++) {
428
+ normBinds[i] = {pos: i + 1};
429
+ }
430
+ } else {
431
+ byPosition = false;
432
+ const bindNames = Object.getOwnPropertyNames(row);
433
+ for (let i = 0; i < bindNames.length; i++) {
434
+ normBinds[i] = {name: bindNames[i]};
435
+ }
436
+ }
437
+ for (let i = 0; i < normBinds.length; i++) {
438
+ normBinds[i].dir = constants.BIND_IN;
439
+ normBinds[i].isArray = false;
440
+ normBinds[i].values = [];
441
+ }
442
+ }
196
443
 
197
- //-----------------------------------------------------------------------------
198
- // break()
199
- // Breaks the execution of the statement.
200
- //-----------------------------------------------------------------------------
201
- module.break = async function() {
202
- nodbUtil.checkArgCount(arguments, 0, 0);
203
- await this._break();
204
- };
444
+ // process each of the rows
445
+ for (let i = 0; i < binds.length; i++) {
446
+ const row = binds[i];
447
+ const options = {pos: i, allowArray: false};
448
+ errors.assert((byPosition && Array.isArray(row)) ||
449
+ (!byPosition && nodbUtil.isObject(row)), errors.ERR_MIXED_BIND);
450
+ for (let j = 0; j < normBinds.length; j++) {
451
+ const bindInfo = normBinds[j];
452
+ const value = (byPosition) ? row[j] : row[bindInfo.name];
453
+ await this._processBindValue(bindInfo, value, options);
454
+ }
455
+ }
205
456
 
457
+ // set bind type and size to a string of size 1 if no bind type was
458
+ // specified (and all values are null)
459
+ for (let i = 0; i < normBinds.length; i++) {
460
+ const bindInfo = normBinds[i];
461
+ if (bindInfo.type === undefined) {
462
+ bindInfo.type = types.DB_TYPE_VARCHAR;
463
+ bindInfo.maxSize = 1;
464
+ }
465
+ }
206
466
 
207
- //-----------------------------------------------------------------------------
208
- // changePassword()
209
- // Changes the password of the specified user.
210
- //-----------------------------------------------------------------------------
211
- async function changePassword(user, password, newPassword) {
212
- nodbUtil.checkArgCount(arguments, 3, 3);
213
- nodbUtil.assert(typeof user === 'string', 'NJS-005', 1);
214
- nodbUtil.assert(typeof password === 'string', 'NJS-005', 2);
215
- nodbUtil.assert(typeof newPassword === 'string', 'NJS-005', 3);
216
- await this._changePassword(user, password, newPassword);
217
- }
467
+ return normBinds;
468
+ }
218
469
 
470
+ //---------------------------------------------------------------------------
471
+ // _transformOutBind()
472
+ //
473
+ // Transform an output bind value from an implementation value to a user
474
+ // facing value (for result sets and LOBs). DML returning output variables
475
+ // are always an array of values.
476
+ //---------------------------------------------------------------------------
477
+ _transformOutBind(val, options) {
478
+ let outVal = val;
479
+ if (Array.isArray(val)) {
480
+ outVal = [];
481
+ for (let i = 0; i < val.length; i++)
482
+ outVal.push(this._transformOutBind(val[i], options));
483
+ } else if (val instanceof impl.ResultSetImpl) {
484
+ outVal = new ResultSet();
485
+ outVal._setup(this, val);
486
+ } else if (val instanceof impl.LobImpl) {
487
+ outVal = new Lob();
488
+ outVal._setup(val, true);
489
+ } else if (val instanceof impl.DbObjectImpl) {
490
+ const cls = this._dbObjectClasses.get(val._objType);
491
+ outVal = Object.create(cls.prototype);
492
+ outVal._impl = val;
493
+ if (options.dbObjectAsPojo) {
494
+ outVal = outVal._toPojo();
495
+ } else if (outVal.isCollection) {
496
+ outVal = new Proxy(outVal, BaseDbObject._collectionProxyHandler);
497
+ }
498
+ }
499
+ return outVal;
500
+ }
219
501
 
220
- //-----------------------------------------------------------------------------
221
- // getQueue()
222
- // Returns a queue with the specified name.
223
- //-----------------------------------------------------------------------------
224
- async function getQueue(name, a2) {
225
- let options = {};
502
+ //---------------------------------------------------------------------------
503
+ // _verifyExecOpts
504
+ //
505
+ // Verify that the value passed by the user for binds is acceptable. Perform
506
+ // any transformations necessary.
507
+ //---------------------------------------------------------------------------
508
+ _verifyExecOpts(options, inExecuteMany) {
226
509
 
227
- nodbUtil.checkArgCount(arguments, 1, 2);
228
- nodbUtil.assert(typeof name === 'string', 'NJS-005', 1);
229
- if (arguments.length == 2) {
230
- nodbUtil.assert(nodbUtil.isObject(a2), 'NJS-005', 2);
231
- options = a2;
232
- }
233
- return (await this._getQueue(name, options));
234
- }
510
+ // define normalized options (value returned to caller)
511
+ const outOptions = {};
235
512
 
513
+ // handle common options
514
+ errors.assertParamValue(nodbUtil.isObject(options), 3);
236
515
 
237
- //-----------------------------------------------------------------------------
238
- // ping()
239
- // Sends a "ping" to the database to see if it is "alive".
240
- //-----------------------------------------------------------------------------
241
- async function ping() {
242
- nodbUtil.checkArgCount(arguments, 0, 0);
243
- await this._ping();
244
- }
516
+ // autoCommit must be a boolean value
517
+ if (options.autoCommit !== undefined) {
518
+ errors.assertParamPropValue(typeof options.autoCommit === 'boolean', 3,
519
+ "autoCommit");
520
+ outOptions.autoCommit = options.autoCommit;
521
+ }
245
522
 
523
+ // dbObjectAsPojo must be a boolean value
524
+ if (options.dbObjectAsPojo !== undefined) {
525
+ errors.assertParamPropValue(typeof options.dbObjectAsPojo === 'boolean',
526
+ 3, "dbObjectAsPojo");
527
+ outOptions.dbObjectAsPojo = options.dbObjectAsPojo;
528
+ }
246
529
 
247
- //-----------------------------------------------------------------------------
248
- // shutdown()
249
- // Shuts down the database instance.
250
- //-----------------------------------------------------------------------------
251
- async function shutdown(a1) {
252
- let mode = this._oracledb.SHUTDOWN_MODE_DEFAULT;
530
+ // keepInStmtCache must be a boolean value
531
+ if (options.keepInStmtCache !== undefined) {
532
+ errors.assertParamPropValue(typeof options.keepInStmtCache === 'boolean',
533
+ 3, "keepInStmtCache");
534
+ outOptions.keepInStmtCache = options.keepInStmtCache;
535
+ }
253
536
 
254
- nodbUtil.checkArgCount(arguments, 0, 1);
255
- if (a1 !== undefined) {
256
- nodbUtil.assert(typeof mode === 'number', 'NJS-005', 1);
257
- mode = a1;
258
- }
537
+ // handle options specific to executeMany()
538
+ if (inExecuteMany) {
259
539
 
260
- await this._shutdown(mode);
261
- }
540
+ // bindDefs must be an object or array
541
+ if (options.bindDefs !== undefined) {
542
+ errors.assertParamPropValue(nodbUtil.isObjectOrArray(options.bindDefs),
543
+ 3, "bindDefs");
544
+ outOptions.bindDefs = options.bindDefs;
545
+ }
262
546
 
547
+ // batchErrors must be a boolean value
548
+ if (options.batchErrors !== undefined) {
549
+ errors.assertParamPropValue(typeof options.batchErrors === 'boolean',
550
+ 3, "batchErrors");
551
+ outOptions.batchErrors = options.batchErrors;
552
+ }
263
553
 
264
- //-----------------------------------------------------------------------------
265
- // startup()
266
- // Starts up the database instance.
267
- //-----------------------------------------------------------------------------
268
- async function startup(a1) {
269
- let opts = {};
554
+ // dmlRowCounts must be a boolean value
555
+ if (options.dmlRowCounts !== undefined) {
556
+ errors.assertParamPropValue(typeof options.dmlRowCounts === 'boolean',
557
+ 3, "dmlRowCounts");
558
+ outOptions.dmlRowCounts = options.dmlRowCounts;
559
+ }
270
560
 
271
- nodbUtil.checkArgCount(arguments, 0, 1);
272
- if (arguments.length == 1) {
273
- nodbUtil.assert(typeof opts === 'object', 'NJS-005', 1);
274
- opts = a1;
275
- }
561
+ // handle options specific to execute()
562
+ } else {
276
563
 
277
- await this._startup(opts);
278
- }
564
+ // fetchArraySize must be a positive integer
565
+ if (options.fetchArraySize !== undefined) {
566
+ errors.assertParamPropValue(Number.isInteger(options.fetchArraySize) &&
567
+ options.fetchArraySize > 0, 3, "fetchArraySize");
568
+ outOptions.fetchArraySize = options.fetchArraySize;
569
+ }
279
570
 
571
+ // fetchInfo must be an object with keys containing an object with a
572
+ // "type" property; these are converted to an array of objects for ease
573
+ // of processing by the implementation
574
+ if (options.fetchInfo !== undefined) {
575
+ errors.assertParamPropValue(nodbUtil.isObject(options.fetchInfo), 3,
576
+ "fetchInfo");
577
+ const names = Object.getOwnPropertyNames(options.fetchInfo);
578
+ const map = new Map(settings.fetchTypeMap);
579
+ for (const name of names) {
580
+ const info = options.fetchInfo[name];
581
+ if (info.type === undefined)
582
+ errors.throwErr(errors.ERR_NO_TYPE_FOR_CONVERSION);
583
+ if (info.type !== constants.DEFAULT &&
584
+ info.type !== types.DB_TYPE_VARCHAR &&
585
+ info.type !== types.DB_TYPE_RAW) {
586
+ errors.throwErr(errors.ERR_INVALID_TYPE_FOR_CONVERSION);
587
+ }
588
+ map.set(name, info.type);
589
+ }
590
+ outOptions.fetchTypeMap = map;
591
+ }
280
592
 
281
- //-----------------------------------------------------------------------------
282
- // subscribe()
283
- // Creates a subscription which can be used to get notifications of database
284
- // changes or of AQ messages available to dequeue.
285
- //-----------------------------------------------------------------------------
286
- async function subscribe(name, options) {
287
- nodbUtil.checkArgCount(arguments, 2, 2);
288
- nodbUtil.assert(typeof name === 'string', 'NJS-005', 1);
289
- nodbUtil.assert(nodbUtil.isObject(options), 'NJS-005', 2);
290
- await this._subscribe(name, options);
291
- }
593
+ // fetchTypeHandler must be a function which is called for each column to
594
+ // be fetched and accepts the metadata for a column
595
+ if (options.fetchTypeHandler !== undefined) {
596
+ const type = (typeof options.fetchTypeHandler);
597
+ errors.assertParamPropValue(type === 'function', 3, "fetchTypeHandler");
598
+ outOptions.fetchTypeHandler = options.fetchTypeHandler;
599
+ }
292
600
 
601
+ // maxRows must be a positive integer (or 0)
602
+ if (options.maxRows !== undefined) {
603
+ errors.assertParamPropValue(Number.isInteger(options.maxRows) &&
604
+ options.maxRows >= 0, 3, "maxRows");
605
+ outOptions.maxRows = options.maxRows;
606
+ }
293
607
 
294
- //-----------------------------------------------------------------------------
295
- // unsubscribe()
296
- // Destroy a subscription which was earlier created using subscribe().
297
- //-----------------------------------------------------------------------------
298
- async function unsubscribe(name) {
299
- nodbUtil.checkArgCount(arguments, 1, 1);
300
- nodbUtil.assert(typeof name === 'string', 'NJS-005', 1);
301
- await this._unsubscribe(name);
302
- }
608
+ // outFormat must be one of the two possible constants
609
+ if (options.outFormat !== undefined) {
610
+ errors.assertParamPropValue(
611
+ options.outFormat === constants.OUT_FORMAT_ARRAY ||
612
+ options.outFormat === constants.OUT_FORMAT_OBJECT, 3, "outFormat");
613
+ outOptions.outFormat = options.outFormat;
614
+ }
303
615
 
304
- // build a database object class
305
- function buildDbObjectClass(schema, name, fqn) {
306
- const DbObject = function(initialValue) {
307
- if (this.isCollection) {
308
- const proxy = new Proxy(this, BaseDbObject._collectionProxyHandler);
309
- if (initialValue !== undefined) {
310
- for (let i = 0; i < initialValue.length; i++) {
311
- this.append(initialValue[i]);
312
- }
616
+ // prefetchRows must be a positive integer (or 0)
617
+ if (options.prefetchRows !== undefined) {
618
+ errors.assertParamPropValue(Number.isInteger(options.prefetchRows) &&
619
+ options.prefetchRows >= 0, 3, "prefetchRows");
620
+ outOptions.prefetchRows = options.prefetchRows;
313
621
  }
314
- return (proxy);
315
- } else if (initialValue !== undefined) {
316
- Object.assign(this, initialValue);
317
- }
318
- };
319
- DbObject.prototype = Object.create(BaseDbObject.prototype);
320
- DbObject.prototype.constructor = DbObject;
321
- DbObject.prototype.schema = schema;
322
- DbObject.prototype.name = name;
323
- DbObject.prototype.fqn = fqn;
324
- DbObject.toString = function() {
325
- return ('DbObjectClass [' + fqn + ']');
326
- };
327
- return (DbObject);
328
- }
329
622
 
330
- //-----------------------------------------------------------------------------
331
- // tpcBegin()
332
- // Starts a two-phase-commit transaction
333
- //----------------------------------------------------------------------------
334
- async function tpcBegin(xid, flag, timeout) {
335
- nodbUtil.checkArgCount(arguments, 1, 3);
336
- nodbUtil.assert(nodbUtil.isXid(xid), 'NJS-005', 1);
623
+ // resultSet must be a boolean value
624
+ if (options.resultSet !== undefined) {
625
+ errors.assertParamPropValue(typeof options.resultSet === 'boolean', 3,
626
+ "resultSet");
627
+ outOptions.resultSet = options.resultSet;
628
+ }
629
+
630
+ }
337
631
 
338
- if (arguments.length < 3) {
339
- timeout = 60; // seconds
340
- } else {
341
- nodbUtil.assert(typeof timeout === 'number', 'NJS-005', 3);
632
+ return outOptions;
342
633
  }
343
634
 
344
- if (arguments.length < 2) {
345
- flag = this._oracledb.TPC_BEGIN_NEW;
346
- } else {
347
- nodbUtil.assert(typeof flag === 'number', 'NJS-005', 2);
635
+ //---------------------------------------------------------------------------
636
+ // action
637
+ //
638
+ // Property for end-to-end tracing attribute.
639
+ //---------------------------------------------------------------------------
640
+ get action() {
641
+ return null;
348
642
  }
349
- await this._tpcBegin(xid, flag, timeout);
350
- }
351
643
 
644
+ set action(value) {
645
+ errors.assertPropValue(typeof value === 'string', "action");
646
+ errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
647
+ this._impl.setAction(value);
648
+ }
352
649
 
353
- //-----------------------------------------------------------------------------
354
- // tpcCommit
355
- // Commit the two-phase-commit transaction
356
- //-----------------------------------------------------------------------------
357
- async function tpcCommit(xid, onePhase) {
358
- nodbUtil.checkArgCount(arguments, 0, 2);
650
+ //---------------------------------------------------------------------------
651
+ // breakExecution()
652
+ //
653
+ // Breaks execution of a running statement.
654
+ //---------------------------------------------------------------------------
655
+ async breakExecution() {
656
+ errors.assertArgCount(arguments, 0, 0);
657
+ errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
658
+ await this._impl.breakExecution();
659
+ }
359
660
 
360
- if (arguments.length < 2) {
361
- onePhase = false;
362
- } else {
363
- nodbUtil.assert(typeof onePhase === 'boolean', 'NJS-005', 2);
661
+ //---------------------------------------------------------------------------
662
+ // callTimeout
663
+ //
664
+ // Property for round-trip timeouts.
665
+ //---------------------------------------------------------------------------
666
+ get callTimeout() {
667
+ if (this._impl)
668
+ return this._impl.getCallTimeout();
669
+ return undefined;
364
670
  }
365
- if (arguments.length >= 1) {
366
- nodbUtil.assert(nodbUtil.isXid(xid), 'NJS-005', 1);
671
+
672
+ set callTimeout(value) {
673
+ errors.assertPropValue(Number.isInteger(value) && value >= 0,
674
+ "callTimeout");
675
+ errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
676
+ this._impl.setCallTimeout(value);
367
677
  }
368
- await this._tpcCommit(xid, onePhase);
369
- }
370
678
 
679
+ //---------------------------------------------------------------------------
680
+ // changePassword()
681
+ //
682
+ // Changes the password of the specified user.
683
+ //---------------------------------------------------------------------------
684
+ async changePassword(user, password, newPassword) {
685
+ errors.assertArgCount(arguments, 3, 3);
686
+ errors.assertParamValue(typeof user === 'string', 1);
687
+ errors.assertParamValue(typeof password === 'string', 2);
688
+ errors.assertParamValue(typeof newPassword === 'string', 3);
689
+ errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
690
+ await this._impl.changePassword(user, password, newPassword);
691
+ }
371
692
 
372
- //-----------------------------------------------------------------------------
373
- // tpcEnd
374
- // Ends the two-phase-commit transaction
375
- //-----------------------------------------------------------------------------
376
- async function tpcEnd(xid, flag) {
377
- nodbUtil.checkArgCount(arguments, 0, 2);
693
+ //---------------------------------------------------------------------------
694
+ // clientId
695
+ //
696
+ // Property for end-to-end tracing attribute.
697
+ //---------------------------------------------------------------------------
698
+ get clientId() {
699
+ return null;
700
+ }
378
701
 
379
- if (arguments.length < 2) {
380
- flag = this._oracledb.TPC_END_NORMAL;
381
- } else {
382
- nodbUtil.assert(typeof flag === 'number', 'NJS-005', 2);
702
+ set clientId(value) {
703
+ errors.assertPropValue(typeof value === 'string', "clientId");
704
+ errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
705
+ this._impl.setClientId(value);
383
706
  }
384
707
 
385
- if (arguments.length >= 1) {
386
- nodbUtil.assert(nodbUtil.isXid(xid), 'NJS-005', 1);
708
+ //---------------------------------------------------------------------------
709
+ // clientInfo
710
+ //
711
+ // Property for end-to-end tracing attribute.
712
+ //---------------------------------------------------------------------------
713
+ get clientInfo() {
714
+ return null;
387
715
  }
388
716
 
389
- await this._tpcEnd(xid, flag);
390
- }
717
+ set clientInfo(value) {
718
+ errors.assertPropValue(typeof value === 'string', "clientInfo");
719
+ errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
720
+ this._impl.setClientInfo(value);
721
+ }
391
722
 
723
+ //---------------------------------------------------------------------------
724
+ // close()
725
+ //
726
+ // Closes the connection and makes it unusable for further work.
727
+ //---------------------------------------------------------------------------
728
+ async close(a1) {
729
+ let options = {};
730
+
731
+ errors.assertArgCount(arguments, 0, 1);
732
+ if (arguments.length == 1) {
733
+ errors.assertParamValue(nodbUtil.isObject(a1), 1);
734
+ options = a1;
735
+ errors.assertParamPropBool(options, 1, "drop");
736
+ }
737
+ errors.assert(this._impl && !this._closing, errors.ERR_INVALID_CONNECTION);
392
738
 
393
- //-----------------------------------------------------------------------------
394
- // tpcForget
395
- // causes the server to forget a heuristically completed global transaction.
396
- //-----------------------------------------------------------------------------
397
- async function tpcForget(xid) {
739
+ this._closing = true;
740
+ try {
741
+ await this._impl.close(options);
742
+ } finally {
743
+ this._closing = false;
744
+ }
398
745
 
399
- nodbUtil.checkArgCount(arguments, 1, 1);
400
- nodbUtil.assert(nodbUtil.isXid(xid), 'NJS-005', 1);
746
+ delete this._impl;
747
+ this._dbObjectClasses.clear();
748
+ this.emit('_afterConnClose');
749
+ }
401
750
 
402
- await this._tpcForget(xid);
403
- }
751
+ //---------------------------------------------------------------------------
752
+ // commit()
753
+ //
754
+ // Commits the current transaction.
755
+ //---------------------------------------------------------------------------
756
+ async commit() {
757
+ errors.assertArgCount(arguments, 0, 0);
758
+ errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
759
+ await this._impl.commit();
760
+ }
404
761
 
762
+ //---------------------------------------------------------------------------
763
+ // createLob()
764
+ //
765
+ // Creates a temporary LOB and returns it to the caller.
766
+ //---------------------------------------------------------------------------
767
+ async createLob(type) {
768
+ errors.assertArgCount(arguments, 1, 1);
769
+ errors.assertParamValue(type === types.DB_TYPE_CLOB ||
770
+ type === types.DB_TYPE_BLOB ||
771
+ type === types.DB_TYPE_NCLOB, 1);
772
+ errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
773
+ const lob = new Lob();
774
+ lob._setup(await this._impl.createLob(type), false);
775
+ return lob;
776
+ }
405
777
 
406
- //-----------------------------------------------------------------------------
407
- // tpcPrepare
408
- // prepares a global transaction for commit.
409
- //-----------------------------------------------------------------------------
410
- async function tpcPrepare(xid) {
411
- nodbUtil.checkArgCount(arguments, 0, 1);
778
+ //---------------------------------------------------------------------------
779
+ // currentSchema
780
+ //
781
+ // Property for identifying the current schema to use in the database.
782
+ //---------------------------------------------------------------------------
783
+ get currentSchema() {
784
+ if (this._impl)
785
+ return this._impl.getCurrentSchema();
786
+ return undefined;
787
+ }
412
788
 
413
- if (arguments.length >= 1) {
414
- nodbUtil.assert(nodbUtil.isXid(xid), 'NJS-005', 1);
789
+ set currentSchema(value) {
790
+ errors.assertPropValue(typeof value === 'string', "currentSchema");
791
+ errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
792
+ this._impl.setCurrentSchema(value);
415
793
  }
416
794
 
417
- return await this._tpcPrepare(xid);
418
- }
795
+ //---------------------------------------------------------------------------
796
+ // dbOp
797
+ //
798
+ // Property for end-to-end tracing attribute.
799
+ //---------------------------------------------------------------------------
800
+ get dbOp() {
801
+ return null;
802
+ }
419
803
 
804
+ set dbOp(value) {
805
+ errors.assertPropValue(typeof value === 'string', "dbOp");
806
+ errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
807
+ this._impl.setDbOp(value);
808
+ }
420
809
 
421
- //-----------------------------------------------------------------------------
422
- // tpcRecover
423
- // Returns a list of pending transactions
424
- //-----------------------------------------------------------------------------
425
- async function tpcRecover(asString) {
426
- nodbUtil.checkArgCount(arguments, 0, 1);
427
-
428
- if (arguments.length == 1) {
429
- nodbUtil.assert(typeof asString === 'boolean', 'NJS-005', 1);
430
- } else {
431
- asString = true;
432
- }
433
-
434
- const sqlStr = `
435
- SELECT
436
- formatid as "formatId",
437
- UTL_RAW.CAST_TO_VARCHAR2(globalid) as "globalTransactionId",
438
- UTL_RAW.CAST_TO_VARCHAR2(branchid) as "branchQualifier"
439
- FROM DBA_PENDING_TRANSACTIONS`;
440
- const sqlBuf = `
441
- SELECT
442
- formatid as "formatId",
443
- globalid as "globalTransactionId",
444
- branchid as "branchQualifier"
445
- FROM DBA_PENDING_TRANSACTIONS`;
446
- const options = {
447
- outFormat: this._oracledb.OUT_FORMAT_OBJECT,
448
- };
449
-
450
- const result = await this._execute(asString ? sqlStr : sqlBuf, {}, options);
451
- return result.resultSet._getAllRows(options, result.metaData, false);
452
- }
810
+ //---------------------------------------------------------------------------
811
+ // thin()
812
+ //
813
+ // return true, if driver mode is thin while acquiring connection
814
+ // return false, if driver mode is thick while acquiring connection
815
+ //---------------------------------------------------------------------------
816
+ get thin() {
817
+ return settings.thin;
818
+ }
453
819
 
820
+ //---------------------------------------------------------------------------
821
+ // ecid
822
+ //
823
+ // Property for end-to-end tracing attribute.
824
+ //---------------------------------------------------------------------------
825
+ get ecid() {
826
+ return null;
827
+ }
454
828
 
455
- //-----------------------------------------------------------------------------
456
- // tpcRollback()
457
- // Rollbacks the current changes in two-phase-commit
458
- //-----------------------------------------------------------------------------
459
- async function tpcRollback(xid) {
460
- nodbUtil.checkArgCount(arguments, 0, 1);
461
- if (arguments.length == 1) {
462
- nodbUtil.assert(nodbUtil.isXid(xid), 'NJS-005', 1);
829
+ set ecid(value) {
830
+ errors.assertPropValue(typeof value === 'string', "ecid");
831
+ errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
832
+ this._impl.setECID(value);
463
833
  }
464
834
 
465
- await this._tpcRollback(xid);
466
- }
835
+ //---------------------------------------------------------------------------
836
+ // execute()
837
+ //
838
+ // Executes a SQL statement and returns the results.
839
+ //---------------------------------------------------------------------------
840
+ async execute(sql, a2, a3) {
841
+ const numIters = 1;
842
+ let binds = [];
843
+ let options = {};
844
+
845
+ // process arguments
846
+ errors.assertArgCount(arguments, 1, 3);
847
+ errors.assertParamValue(typeof sql === 'string', 1);
848
+ if (arguments.length >= 2) {
849
+ binds = await this._processExecuteBinds(a2);
850
+ }
851
+ if (arguments.length == 3) {
852
+ options = this._verifyExecOpts(a3, false);
853
+ }
854
+ this._addDefaultsToExecOpts(options);
855
+ errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
856
+
857
+ // perform actual execute
858
+ let result;
859
+ try {
860
+ result = await this._impl.execute(sql, numIters, binds, options, false);
861
+ } catch (err) {
862
+ if (err.errorNum === 1406)
863
+ errors.throwErr(errors.ERR_INSUFFICIENT_BUFFER_FOR_BINDS);
864
+ throw err;
865
+ }
467
866
 
867
+ // process queries; if a result set is not desired, fetch all of the rows
868
+ // from the result set and then destroy the result set
869
+ if (result.resultSet !== undefined) {
870
+ const resultSet = new ResultSet();
871
+ resultSet._setup(this, result.resultSet);
872
+ result.metaData = resultSet._impl.metaData;
873
+ if (options.resultSet) {
874
+ result.resultSet = resultSet;
875
+ } else {
876
+ result.rows = await resultSet._getAllRows();
877
+ delete result.resultSet;
878
+ }
879
+ }
468
880
 
469
- // define class
470
- class Connection extends EventEmitter {
881
+ // process output binds
882
+ if (result.outBinds !== undefined) {
883
+ for (const key in result.outBinds) {
884
+ const val = this._transformOutBind(result.outBinds[key], options);
885
+ result.outBinds[key] = val;
886
+ }
887
+ }
471
888
 
472
- constructor() {
473
- super();
474
- this._dbObjectClasses = {};
475
- this._requestQueue = [];
476
- this._inProgress = false;
477
- this._closing = false;
889
+ // process implicit results; ensure all implicit results have their fetch
890
+ // array size fixed, or, if a result set is not requested, that all rows
891
+ // are fetched
892
+ if (result.implicitResults) {
893
+ for (const key in result.implicitResults) {
894
+ const resultSetImpl = result.implicitResults[key];
895
+ const resultSet = new ResultSet();
896
+ resultSet._setup(this, resultSetImpl);
897
+ if (options.resultSet) {
898
+ result.implicitResults[key] = resultSet;
899
+ } else {
900
+ result.implicitResults[key] = await resultSet._getAllRows();
901
+ }
902
+ }
903
+ }
904
+
905
+ return (result);
478
906
  }
479
907
 
480
- // extend class with promisified functions
481
- _extend(oracledb) {
482
- this._oracledb = oracledb;
483
- this.break = nodbUtil.callbackify(module.break); // should not be serialized
484
- this.changePassword = nodbUtil.callbackify(nodbUtil.serialize(changePassword));
485
- this.close = nodbUtil.callbackify(nodbUtil.serialize(close));
486
- this.commit = nodbUtil.callbackify(nodbUtil.serialize(commit));
487
- this.createLob = nodbUtil.callbackify(nodbUtil.serialize(createLob));
488
- this.execute = nodbUtil.callbackify(nodbUtil.serialize(execute));
489
- this.executeMany = nodbUtil.callbackify(nodbUtil.serialize(executeMany));
490
- this.getDbObjectClass = nodbUtil.callbackify(nodbUtil.serialize(getDbObjectClass));
491
- this.getQueue = nodbUtil.callbackify(nodbUtil.serialize(getQueue));
492
- this.getStatementInfo = nodbUtil.callbackify(nodbUtil.serialize(getStatementInfo));
493
- this.ping = nodbUtil.callbackify(nodbUtil.serialize(ping));
494
- this.release = nodbUtil.callbackify(nodbUtil.serialize(close));
495
- this.rollback = nodbUtil.callbackify(nodbUtil.serialize(rollback));
496
- this.shutdown = nodbUtil.callbackify(nodbUtil.serialize(shutdown));
497
- this.startup = nodbUtil.callbackify(nodbUtil.serialize(startup));
498
- this.subscribe = nodbUtil.callbackify(nodbUtil.serialize(subscribe));
499
- this.tpcBegin = nodbUtil.callbackify(nodbUtil.serialize(tpcBegin));
500
- this.tpcCommit = nodbUtil.callbackify(nodbUtil.serialize(tpcCommit));
501
- this.tpcEnd = nodbUtil.callbackify(nodbUtil.serialize(tpcEnd));
502
- this.tpcForget = nodbUtil.callbackify(nodbUtil.serialize(tpcForget));
503
- this.tpcPrepare = nodbUtil.callbackify(nodbUtil.serialize(tpcPrepare));
504
- this.tpcRecover = nodbUtil.callbackify(nodbUtil.serialize(tpcRecover));
505
- this.tpcRollback = nodbUtil.callbackify(nodbUtil.serialize(tpcRollback));
506
- this.unsubscribe = nodbUtil.callbackify(nodbUtil.serialize(unsubscribe));
507
- }
508
-
509
- async _acquireLock() {
510
- if (this._inProgress) {
511
- if (this._oracledb.errorOnConcurrentExecute) {
512
- throw new Error(nodbUtil.getErrorMessage('NJS-081'));
908
+ //---------------------------------------------------------------------------
909
+ // executeMany()
910
+ //
911
+ // Executes a SQL statement multiple times and returns the results.
912
+ //---------------------------------------------------------------------------
913
+ async executeMany(sql, bindsOrNumIters, a3) {
914
+ let options = {};
915
+ let binds = [];
916
+ let numIters;
917
+
918
+ errors.assertArgCount(arguments, 2, 3);
919
+ errors.assertParamValue(typeof sql === 'string', 1);
920
+ if (arguments.length == 3) {
921
+ options = this._verifyExecOpts(a3, true);
922
+ }
923
+ this._addDefaultsToExecOpts(options);
924
+ if (typeof bindsOrNumIters === 'number') {
925
+ errors.assertParamValue(Number.isInteger(bindsOrNumIters) &&
926
+ bindsOrNumIters > 0, 2);
927
+ numIters = bindsOrNumIters;
928
+ if (options.bindDefs !== undefined) {
929
+ binds = await this._processExecuteManyBinds([], options.bindDefs);
513
930
  }
514
- await new Promise((resolve, reject) => {
515
- const payload = {resolve: resolve, reject: reject};
516
- this._requestQueue.push(payload);
517
- });
931
+ } else {
932
+ errors.assertParamValue(Array.isArray(bindsOrNumIters) &&
933
+ bindsOrNumIters.length > 0, 2);
934
+ numIters = bindsOrNumIters.length;
935
+ binds = await this._processExecuteManyBinds(bindsOrNumIters,
936
+ options.bindDefs);
518
937
  }
519
- this._inProgress = true;
938
+ errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
939
+
940
+ const result = await this._impl.execute(sql, numIters, binds, options,
941
+ true);
942
+
943
+ // process output binds
944
+ if (result.outBinds !== undefined) {
945
+ for (let i = 0; i < result.outBinds.length; i++) {
946
+ const outBind = result.outBinds[i];
947
+ for (const key in outBind) {
948
+ outBind[key] = this._transformOutBind(outBind[key], options);
949
+ }
950
+ }
951
+ }
952
+
953
+ return result;
520
954
  }
521
955
 
522
- _getConnection() {
523
- return this;
956
+ //---------------------------------------------------------------------------
957
+ // externalName
958
+ //
959
+ // Property for identifying the external name to use in TPC logging.
960
+ //---------------------------------------------------------------------------
961
+ get externalName() {
962
+ if (this._impl)
963
+ return this._impl.getExternalName();
964
+ return undefined;
524
965
  }
525
966
 
526
- _getDbObjectClassJS(schema, name) {
527
- const fqn = `${schema}.${name}`;
528
- let cls = this._dbObjectClasses[fqn];
529
- if (!cls) {
530
- cls = buildDbObjectClass(schema, name, fqn);
531
- cls._connection = this;
532
- this._dbObjectClasses[fqn] = cls;
533
- }
534
- return (cls);
967
+ set externalName(value) {
968
+ errors.assertPropValue(typeof value === 'string', "externalName");
969
+ errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
970
+ this._impl.setExternalName(value);
535
971
  }
536
972
 
537
- _isDate(val) {
538
- return (util.isDate(val));
973
+ //---------------------------------------------------------------------------
974
+ // getDbObjectClass()
975
+ //
976
+ // Returns a database object class given its name. The cache is searched
977
+ // first, but if not found, the database is queried and the result is cached
978
+ // using the type information (as well as the name for easier lookup later).
979
+ //---------------------------------------------------------------------------
980
+ async getDbObjectClass(name) {
981
+ errors.assertArgCount(arguments, 1, 1);
982
+ errors.assertParamValue(typeof name === 'string', 1);
983
+ errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
984
+ return await this._getDbObjectClassForName(name);
539
985
  }
540
986
 
541
- _releaseLock() {
542
- if (this._requestQueue.length > 0) {
543
- const payload = this._requestQueue.shift();
544
- payload.resolve();
545
- } else {
546
- this._inProgress = false;
987
+ //---------------------------------------------------------------------------
988
+ // getQueue()
989
+ //
990
+ // Returns a queue with the specified name.
991
+ //---------------------------------------------------------------------------
992
+ async getQueue(name, a2) {
993
+ let options = {};
994
+
995
+ errors.assertArgCount(arguments, 1, 2);
996
+ errors.assertParamValue(typeof name === 'string', 1);
997
+ if (arguments.length == 2) {
998
+ errors.assertParamValue(nodbUtil.isObject(a2), 2);
999
+ options = {...a2};
547
1000
  }
1001
+ errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
1002
+ const queue = new AqQueue();
1003
+ await queue.create(this, name, options);
1004
+ return queue;
548
1005
  }
549
1006
 
550
- // To obtain a SodaDatabase object (high-level SODA object associated with
551
- // current connection)
1007
+ //---------------------------------------------------------------------------
1008
+ // getSodaDatabase()
1009
+ //
1010
+ // Returns a SodaDatabase object (high-level SODA object associated with
1011
+ // the current connection).
1012
+ //---------------------------------------------------------------------------
552
1013
  getSodaDatabase() {
553
- nodbUtil.checkArgCount(arguments, 0, 0);
554
- return (this._getSodaDatabase());
1014
+ errors.assertArgCount(arguments, 0, 0);
1015
+ errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
1016
+ const sodaDb = new SodaDatabase();
1017
+ sodaDb._impl = this._impl.getSodaDatabase();
1018
+ return sodaDb;
555
1019
  }
556
1020
 
557
- //--------------------------------------------------------------------------
558
- // isHealthy()
559
- // To get the health status of the connection.
560
- // NOTE: if this function returns false, the application must close the
561
- // connection obect.
562
- // This is a synchronous call.
563
1021
  //---------------------------------------------------------------------------
564
- isHealthy() {
565
- return (!this._closing && this._isHealthy());
1022
+ // getStatementInfo()
1023
+ //
1024
+ // Returns information about the statement.
1025
+ //---------------------------------------------------------------------------
1026
+ async getStatementInfo(sql) {
1027
+ errors.assertArgCount(arguments, 1, 1);
1028
+ errors.assertParamValue(typeof sql === 'string', 1);
1029
+ errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
1030
+ const info = await this._impl.getStatementInfo(sql);
1031
+ if (info.metaData) {
1032
+ for (let i = 0; i < info.metaData.length; i++) {
1033
+ const m = info.metaData[i];
1034
+ nodbUtil.addTypeProperties(m, "dbType");
1035
+ m.fetchType = types.DB_TYPE_FETCH_TYPE_MAP.get(m.dbType);
1036
+ }
1037
+ }
1038
+ return info;
566
1039
  }
567
1040
 
1041
+ //---------------------------------------------------------------------------
1042
+ // internalName
1043
+ //
1044
+ // Property for identifying the internal name to use in TPC logging.
1045
+ //---------------------------------------------------------------------------
1046
+ get internalName() {
1047
+ if (this._impl)
1048
+ return this._impl.getInternalName();
1049
+ return undefined;
1050
+ }
568
1051
 
569
- // The queryStream function is similar to execute except that it immediately
570
- // returns a QueryStream.
571
- queryStream(sql, binding, options) {
1052
+ set internalName(value) {
1053
+ errors.assertPropValue(typeof value === 'string', "internalName");
1054
+ errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
1055
+ this._impl.setInternalName(value);
1056
+ }
572
1057
 
573
- nodbUtil.checkArgCount(arguments, 1, 3);
574
- nodbUtil.assert(typeof sql === 'string', 'NJS-005', 1);
1058
+ //--------------------------------------------------------------------------
1059
+ // isHealthy()
1060
+ //
1061
+ // Returns the health status of the connection. If this function returns
1062
+ // false, the caller should close the connection.
1063
+ // ---------------------------------------------------------------------------
1064
+ isHealthy() {
1065
+ return (this._impl !== undefined && !this._closing &&
1066
+ this._impl.isHealthy());
1067
+ }
575
1068
 
576
- if (binding) {
577
- nodbUtil.assert(nodbUtil.isObjectOrArray(binding), 'NJS-005', 2);
578
- }
1069
+ //---------------------------------------------------------------------------
1070
+ // module
1071
+ //
1072
+ // Property for end-to-end tracing attribute.
1073
+ //---------------------------------------------------------------------------
1074
+ get module() {
1075
+ return null;
1076
+ }
579
1077
 
580
- if (options) {
581
- nodbUtil.assert(nodbUtil.isObject(options), 'NJS-005', 3);
582
- }
1078
+ set module(value) {
1079
+ errors.assertPropValue(typeof value === 'string', "module");
1080
+ errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
1081
+ this._impl.setModule(value);
1082
+ }
1083
+
1084
+ //---------------------------------------------------------------------------
1085
+ // oracleServerVersion
1086
+ //
1087
+ // Returns an integer identifying the Oracle Server version.
1088
+ //---------------------------------------------------------------------------
1089
+ get oracleServerVersion() {
1090
+ if (this._impl)
1091
+ return this._impl.getOracleServerVersion();
1092
+ return undefined;
1093
+ }
1094
+
1095
+ //---------------------------------------------------------------------------
1096
+ // oracleServerVersionString
1097
+ //
1098
+ // Returns a string identifying the Oracle Server version.
1099
+ //---------------------------------------------------------------------------
1100
+ get oracleServerVersionString() {
1101
+ if (this._impl)
1102
+ return this._impl.getOracleServerVersionString();
1103
+ return undefined;
1104
+ }
583
1105
 
584
- binding = binding || [];
585
- options = options || {};
1106
+ //---------------------------------------------------------------------------
1107
+ // ping()
1108
+ //
1109
+ // Sends a "ping" to the database to see if it is "alive".
1110
+ //---------------------------------------------------------------------------
1111
+ async ping() {
1112
+ errors.assertArgCount(arguments, 0, 0);
1113
+ errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
1114
+ await this._impl.ping();
1115
+ }
586
1116
 
1117
+ //--------------------------------------------------------------------------
1118
+ // queryStream()
1119
+ //
1120
+ // Similar to execute() except that it immediately returns a QueryStream
1121
+ // object.
1122
+ // ---------------------------------------------------------------------------
1123
+ queryStream(sql, binds, options) {
1124
+ errors.assertArgCount(arguments, 1, 3);
1125
+ errors.assertParamValue(typeof sql === 'string', 1);
1126
+ if (arguments.length == 3) {
1127
+ errors.assertParamValue(nodbUtil.isObject(options), 3);
1128
+ options = {...options};
1129
+ } else {
1130
+ options = {};
1131
+ }
587
1132
  options.resultSet = true;
588
1133
 
589
1134
  const stream = new QueryStream();
590
1135
 
591
1136
  // calling execute() via nextTick to ensure that handlers are registered
592
1137
  // prior to the events being emitted
593
- process.nextTick(() => {
1138
+ process.nextTick(async () => {
594
1139
  try {
595
- const p = this._execute(sql, binding, options);
596
- p.then(function(result) {
597
- if (!result.resultSet) {
598
- stream.destroy(new Error(nodbUtil.getErrorMessage('NJS-019')));
599
- } else {
600
- stream._open(result.resultSet);
601
- }
602
- }, function(err) {
603
- stream.destroy(err);
604
- });
1140
+ const result = await this.execute(sql, binds || [], options);
1141
+ if (!result.resultSet)
1142
+ errors.throwErr(errors.ERR_NOT_A_QUERY);
1143
+ stream._open(result.resultSet);
605
1144
  } catch (err) {
606
1145
  stream.destroy(err);
607
1146
  return;
@@ -611,8 +1150,330 @@ class Connection extends EventEmitter {
611
1150
  return (stream);
612
1151
  }
613
1152
 
614
- }
1153
+ //---------------------------------------------------------------------------
1154
+ // rollback()
1155
+ //
1156
+ // Rolls back the current transaction.
1157
+ //---------------------------------------------------------------------------
1158
+ async rollback() {
1159
+ errors.assertArgCount(arguments, 0, 0);
1160
+ errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
1161
+ await this._impl.rollback();
1162
+ }
1163
+
1164
+ //---------------------------------------------------------------------------
1165
+ // shutdown()
1166
+ // Shuts down the database instance.
1167
+ //---------------------------------------------------------------------------
1168
+ async shutdown(a1) {
1169
+ let mode = constants.SHUTDOWN_MODE_DEFAULT;
1170
+
1171
+ errors.assertArgCount(arguments, 0, 1);
1172
+ if (a1 !== undefined) {
1173
+ errors.assertParamValue(typeof mode === 'number', 1);
1174
+ mode = a1;
1175
+ }
1176
+ errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
1177
+
1178
+ await this._impl.shutdown(mode);
1179
+ }
1180
+
1181
+ //---------------------------------------------------------------------------
1182
+ // startup()
1183
+ // Starts up the database instance.
1184
+ //---------------------------------------------------------------------------
1185
+ async startup(a1) {
1186
+ let options = {};
1187
+
1188
+ errors.assertArgCount(arguments, 0, 1);
1189
+ if (arguments.length == 1) {
1190
+ errors.assertParamValue(typeof options === 'object', 1);
1191
+ options = a1;
1192
+ errors.assertParamPropBool(options, 1, "force");
1193
+ errors.assertParamPropBool(options, 1, "restrict");
1194
+ errors.assertParamPropString(options, 1, "pfile");
1195
+ }
1196
+ errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
1197
+
1198
+ await this._impl.startup(options);
1199
+ }
1200
+
1201
+ //---------------------------------------------------------------------------
1202
+ // stmtCacheSize
1203
+ //
1204
+ // Property for statement cache size.
1205
+ //---------------------------------------------------------------------------
1206
+ get stmtCacheSize() {
1207
+ if (this._impl)
1208
+ return this._impl.getStmtCacheSize();
1209
+ return undefined;
1210
+ }
1211
+
1212
+ set stmtCacheSize(value) {
1213
+ errors.assertPropValue(Number.isInteger(value) && value >= 0,
1214
+ "stmtCacheSize");
1215
+ errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
1216
+ this._impl.setStmtCacheSize(value);
1217
+ }
1218
+
1219
+ //---------------------------------------------------------------------------
1220
+ // subscribe()
1221
+ //
1222
+ // Creates a subscription which can be used to get notifications of database
1223
+ // changes or of AQ messages available to dequeue.
1224
+ //---------------------------------------------------------------------------
1225
+ async subscribe(name, options) {
1226
+ errors.assertArgCount(arguments, 2, 2);
1227
+ errors.assertParamValue(typeof name === 'string', 1);
1228
+ errors.assertParamValue(nodbUtil.isObject(options), 2);
1229
+ options = {...options};
1230
+ errors.assertParamPropUnsignedInt(options, 2, "namespace");
1231
+ if (options.namespace === undefined)
1232
+ options.namespace = constants.SUBSCR_NAMESPACE_DBCHANGE;
1233
+ errors.assertParamPropString(options, 2, "ipAddress");
1234
+ errors.assertParamPropUnsignedInt(options, 2, "port");
1235
+ errors.assertParamPropUnsignedInt(options, 2, "timeout");
1236
+ errors.assertParamPropUnsignedInt(options, 2, "operations");
1237
+ errors.assertParamPropUnsignedInt(options, 2, "qos");
1238
+ errors.assertParamPropUnsignedInt(options, 2, "groupingClass");
1239
+ errors.assertParamPropUnsignedInt(options, 2, "groupingValue");
1240
+ errors.assertParamPropUnsignedInt(options, 2, "groupingType");
1241
+ errors.assertParamPropBool(options, 2, "clientInitiated");
1242
+ errors.assertParamPropFunction(options, 2, "callback");
1243
+ errors.assert(options.callback, errors.ERR_MISSING_SUBSCR_CALLBACK);
1244
+ if (options.namespace === constants.SUBSCR_NAMESPACE_DBCHANGE) {
1245
+ errors.assertParamPropString(options, 2, "sql");
1246
+ errors.assert(options.sql && options.sql.length > 0,
1247
+ errors.ERR_MISSING_SUBSCR_SQL);
1248
+ if (options.binds !== undefined) {
1249
+ options.binds = await this._processExecuteBinds(options.binds);
1250
+ }
1251
+ }
1252
+ errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
1253
+
1254
+ const inSubscr = _subscriptions.get(name);
1255
+ let outValue = await this._impl.subscribe(inSubscr, options);
1256
+ let subscription;
1257
+ if (options.namespace === constants.SUBSCR_NAMESPACE_DBCHANGE) {
1258
+ subscription = outValue.subscription;
1259
+ delete outValue.subscription;
1260
+ } else {
1261
+ subscription = outValue;
1262
+ outValue = undefined;
1263
+ }
1264
+ _subscriptions.set(name, subscription);
1265
+ return outValue;
1266
+ }
1267
+
1268
+ //---------------------------------------------------------------------------
1269
+ // tag
1270
+ //
1271
+ // Property for tag to associate with the connection.
1272
+ //---------------------------------------------------------------------------
1273
+ get tag() {
1274
+ if (this._impl)
1275
+ return this._impl.getTag();
1276
+ return undefined;
1277
+ }
1278
+
1279
+ set tag(value) {
1280
+ errors.assertPropValue(typeof value === 'string', "tag");
1281
+ errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
1282
+ this._impl.setTag(value);
1283
+ }
1284
+
1285
+ //---------------------------------------------------------------------------
1286
+ // tpcBegin()
1287
+ //
1288
+ // Starts a two-phase-commit transaction.
1289
+ //--------------------------------------------------------------------------
1290
+ async tpcBegin(xid, flag, timeout) {
1291
+ errors.assertArgCount(arguments, 1, 3);
1292
+ errors.assertParamValue(nodbUtil.isXid(xid), 1);
1293
+
1294
+ if (arguments.length < 3) {
1295
+ timeout = 60; // seconds
1296
+ } else {
1297
+ errors.assertParamValue(typeof timeout === 'number', 3);
1298
+ }
615
1299
 
1300
+ if (arguments.length < 2) {
1301
+ flag = constants.TPC_BEGIN_NEW;
1302
+ } else {
1303
+ errors.assertParamValue(typeof flag === 'number', 2);
1304
+ }
1305
+ errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
1306
+ await this._impl.tpcBegin(xid, flag, timeout);
1307
+ }
1308
+
1309
+ //---------------------------------------------------------------------------
1310
+ // tpcCommit()
1311
+ //
1312
+ // Commits a two-phase-commit transaction.
1313
+ //---------------------------------------------------------------------------
1314
+ async tpcCommit(xid, onePhase) {
1315
+ errors.assertArgCount(arguments, 0, 2);
1316
+
1317
+ if (arguments.length < 2) {
1318
+ onePhase = false;
1319
+ } else {
1320
+ errors.assertParamValue(typeof onePhase === 'boolean', 2);
1321
+ }
1322
+ if (arguments.length >= 1) {
1323
+ errors.assertParamValue(nodbUtil.isXid(xid), 1);
1324
+ }
1325
+ errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
1326
+ await this._impl.tpcCommit(xid, onePhase);
1327
+ }
1328
+
1329
+ //---------------------------------------------------------------------------
1330
+ // tpcEnd()
1331
+ //
1332
+ // Ends a two-phase-commit transaction.
1333
+ //---------------------------------------------------------------------------
1334
+ async tpcEnd(xid, flag) {
1335
+ errors.assertArgCount(arguments, 0, 2);
1336
+
1337
+ if (arguments.length < 2) {
1338
+ flag = constants.TPC_END_NORMAL;
1339
+ } else {
1340
+ errors.assertParamValue(typeof flag === 'number', 2);
1341
+ }
1342
+
1343
+ if (arguments.length >= 1) {
1344
+ errors.assertParamValue(nodbUtil.isXid(xid), 1);
1345
+ }
1346
+ errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
1347
+
1348
+ await this._impl.tpcEnd(xid, flag);
1349
+ }
1350
+
1351
+ //---------------------------------------------------------------------------
1352
+ // tpcForget()
1353
+ //
1354
+ // Causes the server to forget a heuristically completed two-phase-commit
1355
+ // transaction.
1356
+ // ---------------------------------------------------------------------------
1357
+ async tpcForget(xid) {
1358
+ errors.assertArgCount(arguments, 1, 1);
1359
+ errors.assertParamValue(nodbUtil.isXid(xid), 1);
1360
+ errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
1361
+
1362
+ await this._impl.tpcForget(xid);
1363
+ }
1364
+
1365
+ //---------------------------------------------------------------------------
1366
+ // tpcPrepare()
1367
+ //
1368
+ // Prepares a two-phase-commit transaction for commit.
1369
+ //---------------------------------------------------------------------------
1370
+ async tpcPrepare(xid) {
1371
+ errors.assertArgCount(arguments, 0, 1);
1372
+ if (arguments.length >= 1) {
1373
+ errors.assertParamValue(nodbUtil.isXid(xid), 1);
1374
+ }
1375
+ errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
1376
+
1377
+ return await this._impl.tpcPrepare(xid);
1378
+ }
1379
+
1380
+ //---------------------------------------------------------------------------
1381
+ // tpcRecover()
1382
+ //
1383
+ // Returns a list of pending two-phase-commit transactions.
1384
+ //---------------------------------------------------------------------------
1385
+ async tpcRecover(asString) {
1386
+ errors.assertArgCount(arguments, 0, 1);
1387
+
1388
+ if (arguments.length == 1) {
1389
+ errors.assertParamValue(typeof asString === 'boolean', 1);
1390
+ } else {
1391
+ asString = true;
1392
+ }
1393
+
1394
+ const sqlStr = `
1395
+ SELECT
1396
+ formatid as "formatId",
1397
+ UTL_RAW.CAST_TO_VARCHAR2(globalid) as "globalTransactionId",
1398
+ UTL_RAW.CAST_TO_VARCHAR2(branchid) as "branchQualifier"
1399
+ FROM DBA_PENDING_TRANSACTIONS`;
1400
+ const sqlBuf = `
1401
+ SELECT
1402
+ formatid as "formatId",
1403
+ globalid as "globalTransactionId",
1404
+ branchid as "branchQualifier"
1405
+ FROM DBA_PENDING_TRANSACTIONS`;
1406
+ const options = {
1407
+ outFormat: constants.OUT_FORMAT_OBJECT,
1408
+ resultSet: false
1409
+ };
1410
+
1411
+ const result = await this.execute(asString ? sqlStr : sqlBuf, {}, options);
1412
+ return result.rows;
1413
+ }
1414
+
1415
+ //---------------------------------------------------------------------------
1416
+ // tpcRollback()
1417
+ //
1418
+ // Rolls back the current changes in a two-phase-commit transaction.
1419
+ //---------------------------------------------------------------------------
1420
+ async tpcRollback(xid) {
1421
+ errors.assertArgCount(arguments, 0, 1);
1422
+ if (arguments.length == 1) {
1423
+ errors.assertParamValue(nodbUtil.isXid(xid), 1);
1424
+ }
1425
+ errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
1426
+
1427
+ await this._impl.tpcRollback(xid);
1428
+ }
1429
+
1430
+ //---------------------------------------------------------------------------
1431
+ // unsubscribe()
1432
+ //
1433
+ // Destroy a subscription which was earlier created using subscribe().
1434
+ //---------------------------------------------------------------------------
1435
+ async unsubscribe(name) {
1436
+ errors.assertArgCount(arguments, 1, 1);
1437
+ errors.assertParamValue(typeof name === 'string', 1);
1438
+ errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
1439
+ errors.assert(_subscriptions.has(name), errors.ERR_INVALID_SUBSCR);
1440
+ await this._impl.unsubscribe(_subscriptions.get(name));
1441
+ _subscriptions.delete(name);
1442
+ }
1443
+
1444
+ }
616
1445
 
617
- // module.exports.extend = extend;
1446
+ // adjust functions to support the old callback style and to serialize calls
1447
+ // that cannot take place concurrently
1448
+ // NOTE: breakExecution() should not be serialized
1449
+ Connection.prototype.break =
1450
+ nodbUtil.callbackify(Connection.prototype.breakExecution);
1451
+ nodbUtil.wrapFns(Connection.prototype,
1452
+ "changePassword",
1453
+ "close",
1454
+ "commit",
1455
+ "createLob",
1456
+ "execute",
1457
+ "executeMany",
1458
+ "getDbObjectClass",
1459
+ "getQueue",
1460
+ "getStatementInfo",
1461
+ "ping",
1462
+ "rollback",
1463
+ "shutdown",
1464
+ "startup",
1465
+ "subscribe",
1466
+ "tpcBegin",
1467
+ "tpcCommit",
1468
+ "tpcEnd",
1469
+ "tpcForget",
1470
+ "tpcPrepare",
1471
+ "tpcRecover",
1472
+ "tpcRollback",
1473
+ "unsubscribe");
1474
+
1475
+ // add alias for release()
1476
+ Connection.prototype.release = Connection.prototype.close;
1477
+
1478
+ // export just the Connection class
618
1479
  module.exports = Connection;