oracledb 5.4.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 (108) hide show
  1. package/CHANGELOG.md +1 -1849
  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/THIRD_PARTY_LICENSES.txt +1 -1
  7. package/build/Release/oracledb-6.0.0-darwin-x64.node +0 -0
  8. package/build/Release/oracledb-6.0.0-darwin-x64.node-buildinfo.txt +1 -0
  9. package/build/Release/oracledb-6.0.0-js-buildinfo.txt +1 -0
  10. package/build/Release/oracledb-6.0.0-linux-arm64.node +0 -0
  11. package/build/Release/oracledb-6.0.0-linux-arm64.node-buildinfo.txt +1 -0
  12. package/build/Release/oracledb-6.0.0-linux-x64.node +0 -0
  13. package/build/Release/oracledb-6.0.0-linux-x64.node-buildinfo.txt +1 -0
  14. package/build/Release/oracledb-6.0.0-win32-x64.node +0 -0
  15. package/build/Release/oracledb-6.0.0-win32-x64.node-buildinfo.txt +1 -0
  16. package/examples/README.md +113 -0
  17. package/examples/dbconfig.js +100 -0
  18. package/examples/example.js +156 -0
  19. package/index.js +26 -0
  20. package/lib/aqDeqOptions.js +146 -7
  21. package/lib/aqEnqOptions.js +59 -7
  22. package/lib/aqMessage.js +118 -7
  23. package/lib/aqQueue.js +242 -53
  24. package/lib/connection.js +1324 -465
  25. package/lib/constants.js +203 -0
  26. package/lib/dbObject.js +346 -32
  27. package/lib/errors.js +781 -0
  28. package/lib/impl/aqDeqOptions.js +197 -0
  29. package/lib/impl/aqEnqOptions.js +89 -0
  30. package/lib/impl/aqMessage.js +134 -0
  31. package/lib/impl/aqQueue.js +81 -0
  32. package/lib/impl/connection.js +529 -0
  33. package/lib/impl/dbObject.js +159 -0
  34. package/lib/impl/index.js +59 -0
  35. package/lib/impl/lob.js +85 -0
  36. package/lib/impl/pool.js +195 -0
  37. package/lib/impl/resultset.js +223 -0
  38. package/lib/impl/sodaCollection.js +174 -0
  39. package/lib/impl/sodaDatabase.js +81 -0
  40. package/lib/impl/sodaDocCursor.js +63 -0
  41. package/lib/impl/sodaDocument.js +98 -0
  42. package/lib/impl/sodaOperation.js +109 -0
  43. package/lib/lob.js +156 -68
  44. package/lib/oracledb.js +1051 -257
  45. package/lib/pool.js +654 -465
  46. package/lib/poolStatistics.js +23 -9
  47. package/lib/queryStream.js +14 -7
  48. package/lib/resultset.js +292 -171
  49. package/lib/settings.js +191 -0
  50. package/lib/sodaCollection.js +214 -201
  51. package/lib/sodaDatabase.js +107 -71
  52. package/lib/sodaDocCursor.js +44 -32
  53. package/lib/sodaDocument.js +76 -14
  54. package/lib/sodaOperation.js +131 -118
  55. package/lib/thin/connection.js +1038 -0
  56. package/lib/thin/dbObject.js +629 -0
  57. package/lib/thin/index.js +40 -0
  58. package/lib/thin/lob.js +188 -0
  59. package/lib/thin/pool.js +481 -0
  60. package/lib/thin/protocol/buffer.js +1040 -0
  61. package/lib/thin/protocol/capabilities.js +116 -0
  62. package/lib/thin/protocol/constants.js +764 -0
  63. package/lib/thin/protocol/encryptDecrypt.js +185 -0
  64. package/lib/thin/protocol/messages/auth.js +348 -0
  65. package/lib/thin/protocol/messages/base.js +475 -0
  66. package/lib/thin/protocol/messages/commit.js +56 -0
  67. package/lib/thin/protocol/messages/dataType.js +382 -0
  68. package/lib/thin/protocol/messages/execute.js +312 -0
  69. package/lib/thin/protocol/messages/fetch.js +60 -0
  70. package/lib/thin/protocol/messages/index.js +53 -0
  71. package/lib/thin/protocol/messages/lobOp.js +200 -0
  72. package/lib/thin/protocol/messages/logOff.js +53 -0
  73. package/lib/thin/protocol/messages/ping.js +56 -0
  74. package/lib/thin/protocol/messages/protocol.js +78 -0
  75. package/lib/thin/protocol/messages/rollback.js +56 -0
  76. package/lib/thin/protocol/messages/sessionRelease.js +60 -0
  77. package/lib/thin/protocol/messages/withData.js +811 -0
  78. package/lib/thin/protocol/oson.js +660 -0
  79. package/lib/thin/protocol/packet.js +520 -0
  80. package/lib/thin/protocol/protocol.js +202 -0
  81. package/lib/thin/protocol/utils.js +88 -0
  82. package/lib/thin/resultSet.js +122 -0
  83. package/lib/thin/sqlnet/connStrategy.js +175 -0
  84. package/lib/thin/sqlnet/constants.js +199 -0
  85. package/lib/thin/sqlnet/ezConnectResolver.js +488 -0
  86. package/lib/thin/sqlnet/navNodes.js +870 -0
  87. package/lib/thin/sqlnet/networkSession.js +620 -0
  88. package/lib/thin/sqlnet/ntTcp.js +525 -0
  89. package/lib/thin/sqlnet/nvStrToNvPair.js +783 -0
  90. package/lib/thin/sqlnet/packet.js +405 -0
  91. package/lib/thin/sqlnet/paramParser.js +205 -0
  92. package/lib/thin/sqlnet/sessionAtts.js +160 -0
  93. package/lib/thin/statement.js +301 -0
  94. package/lib/thin/util.js +289 -0
  95. package/lib/transformer.js +250 -0
  96. package/lib/types.js +357 -0
  97. package/lib/util.js +194 -108
  98. package/lib/version.js +36 -0
  99. package/package/README.md +33 -30
  100. package/package/install.js +89 -64
  101. package/package/prunebinaries.js +60 -12
  102. package/package.json +3 -3
  103. package/build/Release/oracledb-5.4.0-darwin-x64.node +0 -0
  104. package/build/Release/oracledb-5.4.0-darwin-x64.node-buildinfo.txt +0 -1
  105. package/build/Release/oracledb-5.4.0-linux-x64.node +0 -0
  106. package/build/Release/oracledb-5.4.0-linux-x64.node-buildinfo.txt +0 -1
  107. package/build/Release/oracledb-5.4.0-win32-x64.node +0 -0
  108. package/build/Release/oracledb-5.4.0-win32-x64.node-buildinfo.txt +0 -1
@@ -1,16 +1,24 @@
1
- // Copyright (c) 2021, 2022, Oracle and/or its affiliates.
1
+ // Copyright (c) 2021, 2023, Oracle and/or its affiliates.
2
+
2
3
  //-----------------------------------------------------------------------------
3
4
  //
4
- // You may not use the identified files except in compliance with the Apache
5
- // 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.
9
+ //
10
+ // If you elect to accept the software under the Apache License, Version 2.0,
11
+ // the following applies:
6
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.
7
15
  // You may obtain a copy of the License at
8
- // http://www.apache.org/licenses/LICENSE-2.0.
9
16
  //
10
- // Unless required by applicable law or agreed to in writing, software
11
- // distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
12
- // WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17
+ // https://www.apache.org/licenses/LICENSE-2.0
13
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.
14
22
  // See the License for the specific language governing permissions and
15
23
  // limitations under the License.
16
24
  //
@@ -18,6 +26,8 @@
18
26
 
19
27
  'use strict';
20
28
 
29
+ const settings = require('./settings.js');
30
+
21
31
  //-----------------------------------------------------------------------------
22
32
  // class PoolStatistics
23
33
  // collection of statistics metrics for Pool object
@@ -68,14 +78,18 @@ class PoolStatistics {
68
78
  this.stmtCacheSize = pool.stmtCacheSize;
69
79
  this.user = pool.user;
70
80
  this.threadPoolSize = process.env.UV_THREADPOOL_SIZE;
81
+ this.thin = settings.thin;
71
82
  }
72
83
 
73
84
  //---------------------------------------------------------------------------
74
85
  // logStatistics()
75
- // To print the statistics metrics of the pool
86
+ //
87
+ // To print the statistics metrics of the pool
76
88
  //---------------------------------------------------------------------------
77
89
  logStatistics() {
78
- console.log('\nPool statistics:');
90
+ console.log('\nDriver:');
91
+ console.log('...thin mode:', this.thin);
92
+ console.log('Pool statistics:');
79
93
  console.log('...gathered at:', new Date(this.gatheredDate).toISOString());
80
94
  console.log('...up time (milliseconds):', this.upTime);
81
95
  console.log('...up time from last reset (milliseconds)',
@@ -2,16 +2,23 @@
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
  //
@@ -48,7 +55,7 @@ class QueryStream extends Readable {
48
55
  this.once('_doneFetching', resolve));
49
56
  }
50
57
  try {
51
- await rs._close();
58
+ await rs._impl.close();
52
59
  } catch (closeErr) {
53
60
  cb(closeErr);
54
61
  return;
package/lib/resultset.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
  //
@@ -20,220 +27,317 @@
20
27
  'use strict';
21
28
 
22
29
  const QueryStream = require('./queryStream.js');
30
+ const BaseDbObject = require('./dbObject.js');
23
31
  const nodbUtil = require('./util.js');
32
+ const constants = require('./constants.js');
33
+ const Lob = require('./lob.js');
34
+ const errors = require('./errors.js');
24
35
 
25
- //-----------------------------------------------------------------------------
26
- // close()
27
- // Close the result set and make it unusable for further operations.
28
- //-----------------------------------------------------------------------------
29
- async function close() {
30
- nodbUtil.checkArgCount(arguments, 0, 0);
36
+ class ResultSet {
31
37
 
32
- if (this._convertedToStream) {
33
- throw new Error(nodbUtil.getErrorMessage('NJS-042'));
38
+ constructor() {
39
+ this._rowCache = [];
40
+ this._processingStarted = false;
41
+ this._convertedToStream = false;
42
+ this._allowGetRowCall = false;
43
+ this._isActive = false;
34
44
  }
35
45
 
36
- this._processingStarted = true;
37
- await this._close();
38
- }
46
+ //---------------------------------------------------------------------------
47
+ // _getAllRows()
48
+ //
49
+ // Return all of the rows in the result set.
50
+ //---------------------------------------------------------------------------
51
+ async _getAllRows() {
52
+
53
+ try {
54
+
55
+ // retain initial values of the maximum number of rows to fetch and the
56
+ // number of rows to fetch from the database at a single time
57
+ let maxRows = this._impl.maxRows;
58
+ let fetchArraySize = this._impl.fetchArraySize;
59
+
60
+ // fetch all rows
61
+ let rowsFetched = [];
62
+ while (true) { // eslint-disable-line
63
+ if (maxRows > 0 && fetchArraySize >= maxRows) {
64
+ fetchArraySize = maxRows;
65
+ }
66
+ const rows = await this._getRows(fetchArraySize);
67
+ if (rows) {
68
+ await this._processRows(rows, true);
69
+ rowsFetched = rowsFetched.concat(rows);
70
+ }
71
+ if (rows.length == maxRows || rows.length < fetchArraySize) {
72
+ break;
73
+ }
74
+ if (maxRows > 0) {
75
+ maxRows -= rows.length;
76
+ }
77
+ }
39
78
 
79
+ return rowsFetched;
40
80
 
41
- //-----------------------------------------------------------------------------
42
- // getRow()
43
- // Returns a single row to the caller from the result set, if one is
44
- // available. Rows are buffered in a JavaScript array in order to avoid trips
45
- // through the thread pool that would be required if implemented in C.
46
- //-----------------------------------------------------------------------------
47
- async function getRow() {
48
- nodbUtil.checkArgCount(arguments, 0, 0);
81
+ } finally {
82
+ await this._impl.close();
83
+ delete this._impl;
84
+ }
49
85
 
50
- if (this._convertedToStream && !this._allowGetRowCall) {
51
- throw new Error(nodbUtil.getErrorMessage('NJS-042'));
52
86
  }
53
87
 
54
- this._allowGetRowCall = false;
55
- this._processingStarted = true;
56
-
57
- if (this._rowCache.length == 0) {
58
- this._rowCache = await this._getRows(this._fetchArraySize, false, false);
88
+ //---------------------------------------------------------------------------
89
+ // _getRows()
90
+ //
91
+ // Return up to the specified number of rows from the result set. If nested
92
+ // cursors are possible, setup the execute options so that they can be
93
+ // examined within the implementation's setup routine.
94
+ //---------------------------------------------------------------------------
95
+ async _getRows(numRows) {
96
+ let options = {};
97
+ if (this._impl.nestedCursorIndices.length > 0) {
98
+ options = {
99
+ connection: this._connection,
100
+ outFormat: this._impl.outFormat,
101
+ fetchArraySize: this._impl.fetchArraySize,
102
+ dbObjectAsPojo: this._impl.dbObjectAsPojo,
103
+ maxRows: this._impl.maxRows,
104
+ fetchTypeMap: this._impl.fetchTypeMap
105
+ };
106
+ }
107
+ return await this._impl.getRows(numRows, options);
59
108
  }
60
- return this._rowCache.shift();
61
- }
62
-
63
-
64
- //-----------------------------------------------------------------------------
65
- // getRows()
66
- // Check to see if any rows are in the JS buffer (which could result from
67
- // interspersed calls to getRow() and getRows()). If no rows are in the buffer
68
- // buffer, the call is just proxied to the C layer. Otherwise, rows are pulled
69
- // from the buffer and potentially concatenated with rows from a call to
70
- // getRows().
71
- //-----------------------------------------------------------------------------
72
- async function getRows(numRows) {
73
- let rowsNeeded;
74
-
75
- nodbUtil.checkArgCount(arguments, 0, 1);
76
109
 
77
- if (arguments.length == 0) {
78
- numRows = 0;
79
- } else {
80
- nodbUtil.assert(Number.isInteger(numRows), 'NJS-005', 1);
81
- nodbUtil.assert(numRows >= 0, 'NJS-005', 1);
82
- }
110
+ //---------------------------------------------------------------------------
111
+ // _processRows()
112
+ //
113
+ // Process rows returned by the implementation. This will transform result
114
+ // set and LOB implementations into user facing objects. It will also perform
115
+ // any fetched that are needed (if a result set is undesirable)
116
+ //---------------------------------------------------------------------------
117
+ async _processRows(rows, expandNestedCursors) {
118
+
119
+ // transform any nested cursors into user facing objects
120
+ for (const i of this._impl.nestedCursorIndices) {
121
+ for (let j = 0; j < rows.length; j++) {
122
+ const val = rows[j][i];
123
+ if (val) {
124
+ const resultSet = new ResultSet();
125
+ resultSet._setup(this._connection, val);
126
+ this._impl.metaData[i].metaData = val.metaData;
127
+ if (expandNestedCursors) {
128
+ rows[j][i] = await resultSet._getAllRows();
129
+ } else {
130
+ rows[j][i] = resultSet;
131
+ }
132
+ }
133
+ }
134
+ }
83
135
 
84
- if (this._convertedToStream) {
85
- throw new Error(nodbUtil.getErrorMessage('NJS-042'));
86
- }
136
+ // transform any LOBs into user facing objects
137
+ for (const i of this._impl.lobIndices) {
138
+ for (let j = 0; j < rows.length; j++) {
139
+ const val = rows[j][i];
140
+ if (val) {
141
+ const lob = rows[j][i] = new Lob();
142
+ lob._setup(val, true);
143
+ }
144
+ }
145
+ }
87
146
 
88
- this._processingStarted = true;
147
+ // transform any database objects into user facing objects
148
+ for (const i of this._impl.dbObjectIndices) {
149
+ const dbObjectClass = this._impl.metaData[i].dbTypeClass;
150
+ for (let j = 0; j < rows.length; j++) {
151
+ const val = rows[j][i];
152
+ if (val) {
153
+ const obj = rows[j][i] = Object.create(dbObjectClass.prototype);
154
+ obj._impl = val;
155
+ if (this._impl.dbObjectAsPojo) {
156
+ rows[j][i] = obj._toPojo();
157
+ } else if (obj.isCollection) {
158
+ rows[j][i] = new Proxy(obj, BaseDbObject._collectionProxyHandler);
159
+ }
160
+ }
161
+ }
162
+ }
89
163
 
90
- if (numRows == 0) {
91
- let requestedRows = this._rowCache;
164
+ // run any conversion functions, if applicable
165
+ // NOTE: we mark the connection as no longer in progress before making
166
+ // calls to the converter function; this is needed to allow calls against
167
+ // the database (like getting LOB data) to succeed, as this code is running
168
+ // in the middle of a call to connection.execute() or resultSet.getRows()
169
+ for (const i of this._impl.converterIndices) {
170
+ const fn = this._impl.metaData[i].converter;
171
+ this._connection._impl._inProgress = false;
172
+ try {
173
+ for (let j = 0; j < rows.length; j++) {
174
+ let result = fn(rows[j][i]);
175
+ if (result instanceof Promise) {
176
+ result = await result;
177
+ }
178
+ rows[j][i] = result;
179
+ }
180
+ } finally {
181
+ this._connection._impl._inProgress = true;
182
+ }
183
+ }
92
184
 
93
- const fetchArraySize = this._fetchArraySize;
94
- while (true) { // eslint-disable-line
95
- let rows = await this._getRows(fetchArraySize, false, false);
96
- if (rows)
97
- requestedRows = requestedRows.concat(rows);
98
- if (rows.length < fetchArraySize)
99
- break;
185
+ // create objects, if desired
186
+ if (this._impl.outFormat === constants.OUT_FORMAT_OBJECT) {
187
+ for (let i = 0; i < rows.length; i++) {
188
+ const origRow = rows[i];
189
+ const newRow = rows[i] = {};
190
+ const metaData = this._impl.metaData;
191
+ for (let j = 0; j < metaData.length; j++) {
192
+ newRow[metaData[j].name] = origRow[j];
193
+ }
194
+ }
100
195
  }
101
- return requestedRows;
102
- }
103
196
 
104
- if (this._rowCache.length === 0) {
105
- return await this._getRows(numRows, false, false);
106
197
  }
107
198
 
108
- rowsNeeded = numRows - this._rowCache.length;
109
- if (rowsNeeded <= 0) {
110
- return this._rowCache.splice(0, numRows);
111
- } else {
112
- const rows = await this._getRows(rowsNeeded, false, false);
113
- const requestedRows = this._rowCache.concat(rows);
114
- this._rowCache = [];
115
- return requestedRows;
199
+ //---------------------------------------------------------------------------
200
+ // _setup()
201
+ //
202
+ // Setup a result set.
203
+ // ---------------------------------------------------------------------------
204
+ _setup(connection, resultSetImpl) {
205
+ this._connection = connection;
206
+ this._impl = resultSetImpl;
116
207
  }
117
- }
118
-
119
208
 
120
- class ResultSet {
209
+ //---------------------------------------------------------------------------
210
+ // close()
211
+ //
212
+ // Close the result set and make it unusable for further operations.
213
+ //---------------------------------------------------------------------------
214
+ async close() {
215
+ errors.assertArgCount(arguments, 0, 0);
216
+ errors.assert(this._impl && this._connection._impl, errors.ERR_INVALID_RS);
121
217
 
122
- constructor() {
123
- this._rowCache = [];
124
- this._processingStarted = false;
125
- this._convertedToStream = false;
126
- this._allowGetRowCall = false;
127
- this._isActive = false;
128
- }
218
+ if (this._convertedToStream) {
219
+ errors.throwErr(errors.ERR_CANNOT_INVOKE_RS_METHODS);
220
+ }
129
221
 
130
- _extend(oracledb) {
131
- this._oracledb = oracledb;
132
- this.close = nodbUtil.callbackify(nodbUtil.preventConcurrent(nodbUtil.serialize(close), 'NJS-017'));
133
- this.getRow = nodbUtil.callbackify(nodbUtil.preventConcurrent(nodbUtil.serialize(getRow), 'NJS-017'));
134
- this.getRows = nodbUtil.callbackify(nodbUtil.preventConcurrent(nodbUtil.serialize(getRows), 'NJS-017'));
222
+ this._processingStarted = true;
223
+ const resultSetImpl = this._impl;
224
+ delete this._impl;
225
+ await resultSetImpl.close();
135
226
  }
136
227
 
137
- _getConnection() {
138
- let connection = this._parentObj;
139
- while (!(connection instanceof this._oracledb.Connection))
140
- connection = connection._parentObj;
141
- return connection;
142
- }
228
+ //---------------------------------------------------------------------------
229
+ // getRow()
230
+ //
231
+ // Returns a single row to the caller from the result set, if one is
232
+ // available. Rows are buffered in a JavaScript array in order to avoid trips
233
+ // through the thread pool that would be required if implemented in C.
234
+ //---------------------------------------------------------------------------
235
+ async getRow() {
236
+ errors.assertArgCount(arguments, 0, 0);
237
+ errors.assert(this._impl && this._connection._impl, errors.ERR_INVALID_RS);
238
+
239
+ if (this._convertedToStream && !this._allowGetRowCall) {
240
+ errors.throwErr(errors.ERR_CANNOT_INVOKE_RS_METHODS);
241
+ }
143
242
 
144
- async _getAllRows(executeOpts, metaDataObj, isNested) {
243
+ this._allowGetRowCall = false;
244
+ this._processingStarted = true;
145
245
 
146
- // assign result set metadata to the object; this is either a top-level
147
- // result object that is returned to the user or a metadata object for a
148
- // nested cursor or empty (for implicit results which don't provide
149
- // metadata to the caller)
150
- if (metaDataObj && !metaDataObj.metaData) {
151
- metaDataObj.metaData = this.metaData;
246
+ if (this._rowCache.length == 0) {
247
+ const rows = await this._getRows(this._impl.fetchArraySize);
248
+ await this._processRows(rows, false);
249
+ this._rowCache = rows;
152
250
  }
251
+ return this._rowCache.shift();
252
+ }
153
253
 
154
- // determine value of maxRows to use
155
- let maxRows = this._oracledb.maxRows;
156
- if (executeOpts && executeOpts.maxRows !== undefined) {
157
- maxRows = executeOpts.maxRows;
254
+ //---------------------------------------------------------------------------
255
+ // getRows()
256
+ //
257
+ // Check to see if any rows are in the JS buffer (which could result from
258
+ // interspersed calls to getRow() and getRows()). If no rows are in the
259
+ // buffer, the call is just proxied to the implementation layer. Otherwise,
260
+ // rows are pulled from the buffer and potentially concatenated with rows
261
+ // from calls to the implementation's getRows().
262
+ //---------------------------------------------------------------------------
263
+ async getRows(numRows) {
264
+ let rowsNeeded;
265
+
266
+ errors.assertArgCount(arguments, 0, 1);
267
+ errors.assert(this._impl && this._connection._impl, errors.ERR_INVALID_RS);
268
+
269
+ if (arguments.length == 0) {
270
+ numRows = 0;
271
+ } else {
272
+ errors.assertParamValue(Number.isInteger(numRows) && numRows >= 0, 1);
158
273
  }
159
274
 
160
- // determine value of outFormat to use
161
- let outFormat = this._oracledb.outFormat;
162
- if (executeOpts && executeOpts.outFormat !== undefined) {
163
- outFormat = executeOpts.outFormat;
275
+ if (this._convertedToStream) {
276
+ errors.throwErr(errors.ERR_CANNOT_INVOKE_RS_METHODS);
164
277
  }
165
278
 
166
- // determine the nested cursor indices to use, allowing for both
167
- // OUT_FORMAT_ARRAY and OUT_FORMAT_OBJECT formats
168
- const nestedCursorMetaDataObjs = [];
169
- const nestedCursorIndices = this._nestedCursorIndices;
170
- for (let i = 0; i < nestedCursorIndices.length; i++) {
171
- nestedCursorMetaDataObjs[i] =
172
- metaDataObj.metaData[nestedCursorIndices[i]];
173
- if (outFormat == this._oracledb.OUT_FORMAT_OBJECT) {
174
- nestedCursorIndices[i] = nestedCursorMetaDataObjs[i].name;
279
+ this._processingStarted = true;
280
+
281
+ let requestedRows;
282
+ if (numRows == 0) {
283
+ requestedRows = this._rowCache;
284
+ const fetchArraySize = this._impl.fetchArraySize;
285
+ while (true) { // eslint-disable-line
286
+ const rows = await this._getRows(fetchArraySize);
287
+ if (rows) {
288
+ await this._processRows(rows, false);
289
+ requestedRows = requestedRows.concat(rows);
290
+ }
291
+ if (rows.length < fetchArraySize)
292
+ break;
175
293
  }
294
+ return requestedRows;
176
295
  }
177
296
 
178
- // process all rows; transform nested cursors into arrays of rows by
179
- // fetching them
180
- let rowsFetched = [];
181
- let fetchArraySize = this._fetchArraySize;
182
- let closeOnFetch = false;
183
- const closeOnAllRowsFetched = !isNested && nestedCursorIndices.length === 0;
184
- while (true) { // eslint-disable-line
185
- if (maxRows > 0 && fetchArraySize >= maxRows) {
186
- fetchArraySize = maxRows;
187
- closeOnFetch = closeOnAllRowsFetched;
188
- }
189
- const rows = await this._getRows(fetchArraySize, closeOnFetch,
190
- closeOnAllRowsFetched);
191
- if (nestedCursorIndices) {
192
- for (let i = 0; i < rows.length; i++) {
193
- const row = rows[i];
194
- for (let j = 0; j < nestedCursorIndices.length; j++) {
195
- const val = row[nestedCursorIndices[j]];
196
- if (val) {
197
- row[nestedCursorIndices[j]] =
198
- await val._getAllRows(executeOpts,
199
- nestedCursorMetaDataObjs[j], true);
200
- }
201
- }
202
- }
203
- }
204
- if (rows) {
205
- rowsFetched = rowsFetched.concat(rows);
206
- }
207
- if (rows.length == maxRows || rows.length < fetchArraySize) {
208
- break;
209
- }
210
- if (maxRows > 0) {
211
- maxRows -= rows.length;
297
+ if (this._rowCache.length === 0) {
298
+ requestedRows = await this._getRows(numRows);
299
+ await this._processRows(requestedRows, false);
300
+ } else {
301
+ rowsNeeded = numRows - this._rowCache.length;
302
+ if (rowsNeeded <= 0) {
303
+ requestedRows = this._rowCache.splice(0, numRows);
304
+ } else {
305
+ const rows = await this._getRows(rowsNeeded);
306
+ await this._processRows(rows, false);
307
+ requestedRows = this._rowCache.concat(rows);
308
+ this._rowCache = [];
212
309
  }
213
310
  }
214
311
 
215
- // if the cursor was not automatically closed (in order to ensure that
216
- // nested cursors could be fetched), close it now that all rows have been
217
- // fetched
218
- if (!closeOnAllRowsFetched) {
219
- await this._close();
220
- }
221
- return rowsFetched;
312
+ return requestedRows;
222
313
  }
223
314
 
224
- _getDbObjectClassJS(schema, name) {
225
- return this._connection._getDbObjectClassJS(schema, name);
315
+ //---------------------------------------------------------------------------
316
+ // metaData()
317
+ //
318
+ // Property returning the metadata associated with the result set.
319
+ //---------------------------------------------------------------------------
320
+ get metaData() {
321
+ if (this._impl) {
322
+ return this._impl.metaData;
323
+ }
324
+ return undefined;
226
325
  }
227
326
 
327
+ //---------------------------------------------------------------------------
328
+ // toQueryStream()
329
+ //
330
+ // Converts a result set to a QueryStream object.
331
+ //---------------------------------------------------------------------------
228
332
  toQueryStream() {
229
- nodbUtil.checkArgCount(arguments, 0, 0);
333
+ errors.assertArgCount(arguments, 0, 0);
230
334
 
231
335
  if (this._processingStarted) {
232
- throw new Error(nodbUtil.getErrorMessage('NJS-041'));
336
+ errors.throwErr(errors.ERR_CANNOT_CONVERT_RS_TO_STREAM);
233
337
  }
234
338
 
235
339
  if (this._convertedToStream) {
236
- throw new Error(nodbUtil.getErrorMessage('NJS-043'));
340
+ errors.throwErr(errors.ERR_RS_ALREADY_CONVERTED);
237
341
  }
238
342
 
239
343
  this._convertedToStream = true;
@@ -241,7 +345,24 @@ class ResultSet {
241
345
  return new QueryStream(this);
242
346
  }
243
347
 
348
+ [Symbol.asyncIterator]() {
349
+ const resultSet = this;
350
+ return {
351
+ async next() {
352
+ const row = await resultSet.getRow();
353
+ return {value: row, done: row === undefined};
354
+ },
355
+ return() {
356
+ return {done: true};
357
+ }
358
+ };
359
+ }
360
+
244
361
  }
245
362
 
363
+ nodbUtil.wrapFns(ResultSet.prototype, errors.ERR_BUSY_RS,
364
+ "close",
365
+ "getRow",
366
+ "getRows");
246
367
 
247
368
  module.exports = ResultSet;