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