oracledb 6.1.0 → 6.3.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.
- package/README.md +2 -2
- package/build/Release/oracledb-6.3.0-darwin-x64.node +0 -0
- package/build/Release/oracledb-6.3.0-darwin-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.3.0-js-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.3.0-linux-arm64.node +0 -0
- package/build/Release/oracledb-6.3.0-linux-arm64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.3.0-linux-x64.node +0 -0
- package/build/Release/oracledb-6.3.0-linux-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.3.0-win32-x64.node +0 -0
- package/build/Release/oracledb-6.3.0-win32-x64.node-buildinfo.txt +1 -0
- package/examples/README.md +26 -8
- package/examples/dbconfig.js +57 -40
- package/examples/example.js +6 -4
- package/lib/connection.js +67 -1
- package/lib/dbObject.js +9 -0
- package/lib/errors.js +25 -7
- package/lib/future.js +53 -0
- package/lib/impl/connection.js +56 -0
- package/lib/impl/pool.js +5 -3
- package/lib/impl/resultset.js +48 -11
- package/lib/oracledb.js +34 -14
- package/lib/pool.js +10 -0
- package/lib/sodaCollection.js +11 -0
- package/lib/sodaOperation.js +16 -0
- package/lib/thin/connection.js +184 -155
- package/lib/thin/dbObject.js +49 -2
- package/lib/thin/index.js +1 -1
- package/lib/thin/pool.js +3 -2
- package/lib/thin/protocol/buffer.js +79 -70
- package/lib/thin/protocol/capabilities.js +3 -1
- package/lib/thin/protocol/constants.js +31 -14
- package/lib/thin/protocol/messages/auth.js +6 -2
- package/lib/thin/protocol/messages/base.js +36 -14
- package/lib/thin/protocol/messages/dataType.js +8 -5
- package/lib/thin/protocol/messages/lobOp.js +7 -8
- package/lib/thin/protocol/messages/withData.js +62 -22
- package/lib/thin/protocol/oson.js +13 -10
- package/lib/thin/protocol/packet.js +6 -5
- package/lib/thin/protocol/utils.js +2 -2
- package/lib/thin/sqlnet/connStrategy.js +8 -4
- package/lib/thin/sqlnet/constants.js +138 -138
- package/lib/thin/sqlnet/ezConnectResolver.js +10 -43
- package/lib/thin/sqlnet/navNodes.js +7 -7
- package/lib/thin/sqlnet/networkSession.js +22 -21
- package/lib/thin/sqlnet/ntTcp.js +7 -7
- package/lib/thin/sqlnet/packet.js +1 -1
- package/lib/thin/statement.js +345 -113
- package/lib/thin/util.js +35 -86
- package/lib/types.js +6 -1
- package/lib/util.js +12 -0
- package/lib/version.js +1 -1
- package/package.json +1 -1
- package/build/Release/oracledb-6.1.0-darwin-x64.node +0 -0
- package/build/Release/oracledb-6.1.0-darwin-x64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.1.0-js-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.1.0-linux-arm64.node +0 -0
- package/build/Release/oracledb-6.1.0-linux-arm64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.1.0-linux-x64.node +0 -0
- package/build/Release/oracledb-6.1.0-linux-x64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.1.0-win32-x64.node +0 -0
- package/build/Release/oracledb-6.1.0-win32-x64.node-buildinfo.txt +0 -1
package/lib/impl/resultset.js
CHANGED
|
@@ -30,7 +30,9 @@ const constants = require('../constants.js');
|
|
|
30
30
|
const errors = require('../errors.js');
|
|
31
31
|
const nodbUtil = require('../util.js');
|
|
32
32
|
const settings = require('../settings.js');
|
|
33
|
+
const future = require('../future.js');
|
|
33
34
|
const types = require('../types.js');
|
|
35
|
+
const Lob = require('../lob.js');
|
|
34
36
|
|
|
35
37
|
// define implementation class
|
|
36
38
|
class ResultSetImpl {
|
|
@@ -100,36 +102,71 @@ class ResultSetImpl {
|
|
|
100
102
|
metadata.fetchType = actualFetchType;
|
|
101
103
|
}
|
|
102
104
|
|
|
105
|
+
let converter;
|
|
106
|
+
const userConverter = metadata.converter;
|
|
107
|
+
|
|
108
|
+
// If IsJson is set convert to JSON objects unless
|
|
109
|
+
// user defined output type handler overwrites it.
|
|
110
|
+
if (future.oldJsonColumnAsObj && metadata.isJson && metadata.dbType !== types.DB_TYPE_JSON
|
|
111
|
+
&& userConverter === undefined) {
|
|
112
|
+
const outConverter = async function(val) {
|
|
113
|
+
if (!val) {
|
|
114
|
+
return val;
|
|
115
|
+
}
|
|
116
|
+
|
|
117
|
+
let result = val;
|
|
118
|
+
if (val instanceof Lob) {
|
|
119
|
+
result = await val.getData();
|
|
120
|
+
}
|
|
121
|
+
if (result instanceof Buffer) {
|
|
122
|
+
result = result.toString();
|
|
123
|
+
}
|
|
124
|
+
result = JSON.parse(result);
|
|
125
|
+
return result;
|
|
126
|
+
};
|
|
127
|
+
converter = outConverter;
|
|
128
|
+
}
|
|
129
|
+
|
|
103
130
|
// in thin mode, Oracle NUMBER values are internally fetched as string in
|
|
104
131
|
// order to preserve precision so must be converted to JavaScript Number
|
|
105
132
|
// when needed; other numeric and date types are fetched natively as
|
|
106
133
|
// JavaScript Number and Date values and are converted to string using
|
|
107
134
|
// toString() when desired
|
|
108
135
|
if (settings.thin) {
|
|
109
|
-
let converter;
|
|
110
|
-
const userConverter = metadata.converter;
|
|
111
136
|
if (metadata.dbType === types.DB_TYPE_NUMBER &&
|
|
112
|
-
|
|
137
|
+
metadata.fetchType === types.DB_TYPE_NUMBER) {
|
|
113
138
|
converter = (v) => (v === null) ? null : parseFloat(v);
|
|
114
139
|
} else if (metadata.fetchType === types.DB_TYPE_VARCHAR) {
|
|
115
140
|
if (metadata.dbType === types.DB_TYPE_BINARY_DOUBLE ||
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
141
|
+
metadata.dbType === types.DB_TYPE_BINARY_FLOAT ||
|
|
142
|
+
metadata.dbType === types.DB_TYPE_DATE ||
|
|
143
|
+
metadata.dbType === types.DB_TYPE_TIMESTAMP ||
|
|
144
|
+
metadata.dbType === types.DB_TYPE_TIMESTAMP_LTZ ||
|
|
145
|
+
metadata.dbType === types.DB_TYPE_TIMESTAMP_TZ) {
|
|
121
146
|
converter = (v) => (v === null) ? null : v.toString();
|
|
122
147
|
} else if (metadata.dbType === types.DB_TYPE_RAW) {
|
|
123
148
|
converter = (v) => (v === null) ? null : v.toString('hex').toUpperCase();
|
|
124
149
|
}
|
|
150
|
+
} else if (metadata.dbType === types.DB_TYPE_XMLTYPE) {
|
|
151
|
+
const xmlConverter = async function(val) {
|
|
152
|
+
if (!val) {
|
|
153
|
+
return val;
|
|
154
|
+
}
|
|
155
|
+
if (typeof val === 'string') {
|
|
156
|
+
return val;
|
|
157
|
+
}
|
|
158
|
+
return await val.getData();
|
|
159
|
+
};
|
|
160
|
+
converter = xmlConverter;
|
|
125
161
|
}
|
|
126
162
|
if (userConverter && converter) {
|
|
127
163
|
const internalConverter = converter;
|
|
128
164
|
converter = (v) => userConverter(internalConverter(v));
|
|
129
165
|
}
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (converter) {
|
|
169
|
+
metadata.converter = converter;
|
|
133
170
|
}
|
|
134
171
|
|
|
135
172
|
}
|
package/lib/oracledb.js
CHANGED
|
@@ -48,6 +48,7 @@ const AqDeqOptions = require('./aqDeqOptions.js');
|
|
|
48
48
|
const AqEnqOptions = require('./aqEnqOptions.js');
|
|
49
49
|
const AqMessage = require('./aqMessage.js');
|
|
50
50
|
const AqQueue = require('./aqQueue.js');
|
|
51
|
+
const future = require('./future.js');
|
|
51
52
|
const BaseDbObject = require('./dbObject.js');
|
|
52
53
|
const Connection = require('./connection.js');
|
|
53
54
|
const Lob = require('./lob.js');
|
|
@@ -69,22 +70,26 @@ const defaultPoolAlias = 'default';
|
|
|
69
70
|
let _initOracleClientArgs;
|
|
70
71
|
|
|
71
72
|
// Load the Oracledb binary
|
|
72
|
-
function _initCLib() {
|
|
73
|
+
function _initCLib(options) {
|
|
73
74
|
/*global __non_webpack_require__*/ // quieten eslint
|
|
74
75
|
const requireBinary = (typeof __non_webpack_require__ === 'function') ? __non_webpack_require__ : require; // See Issue 1156
|
|
75
|
-
|
|
76
76
|
const binaryLocations = [
|
|
77
77
|
'../' + nodbUtil.RELEASE_DIR + '/' + nodbUtil.BINARY_FILE, // pre-built binary
|
|
78
|
-
'../' + nodbUtil.RELEASE_DIR + '/' +
|
|
79
|
-
'../build/Debug/
|
|
78
|
+
'../' + nodbUtil.RELEASE_DIR + '/' + nodbUtil.BUILD_FILE, // binary built from source
|
|
79
|
+
'../build/Debug/' + nodbUtil.BUILD_FILE, // debug binary
|
|
80
80
|
// Paths for Webpack.
|
|
81
81
|
// Note: to use node-oracledb Thick mode, you will need a Webpack copy plugin to
|
|
82
82
|
// copy 'node_modules/oracledb/build/' to the output directory,
|
|
83
83
|
// see https://github.com/oracle/node-oracledb/issues/1156
|
|
84
84
|
// If you want to use only node-oracledb Thin mode, a copy plugin is not needed.
|
|
85
85
|
'./node_modules/oracledb/' + nodbUtil.RELEASE_DIR + '/' + nodbUtil.BINARY_FILE,
|
|
86
|
-
'./node_modules/oracledb/' + nodbUtil.RELEASE_DIR + '/' +
|
|
86
|
+
'./node_modules/oracledb/' + nodbUtil.RELEASE_DIR + '/' + nodbUtil.BUILD_FILE
|
|
87
87
|
];
|
|
88
|
+
|
|
89
|
+
if (options.binaryDir !== undefined) {
|
|
90
|
+
binaryLocations.splice(0, 0, options.binaryDir + '/' + nodbUtil.BINARY_FILE,
|
|
91
|
+
options.binaryDir + '/' + nodbUtil.BUILD_FILE);
|
|
92
|
+
}
|
|
88
93
|
let oracledbCLib;
|
|
89
94
|
for (let i = 0; i < binaryLocations.length; i++) {
|
|
90
95
|
try {
|
|
@@ -467,9 +472,10 @@ async function _verifyOptions(options, inCreatePool) {
|
|
|
467
472
|
let accessToken;
|
|
468
473
|
if (typeof options.accessToken === 'function') {
|
|
469
474
|
outOptions.accessTokenFn = options.accessToken;
|
|
470
|
-
|
|
475
|
+
outOptions.accessTokenConfig = options.accessTokenConfig;
|
|
476
|
+
accessToken = await options.accessToken(false, options.accessTokenConfig);
|
|
471
477
|
if (!nodbUtil.isTokenValid(accessToken)) {
|
|
472
|
-
accessToken = await options.accessToken(true);
|
|
478
|
+
accessToken = await options.accessToken(true, options.accessTokenConfig);
|
|
473
479
|
}
|
|
474
480
|
} else {
|
|
475
481
|
accessToken = options.accessToken;
|
|
@@ -478,9 +484,7 @@ async function _verifyOptions(options, inCreatePool) {
|
|
|
478
484
|
errors.ERR_TOKEN_HAS_EXPIRED);
|
|
479
485
|
if (accessToken.privateKey !== undefined) {
|
|
480
486
|
errors.assert(typeof accessToken.privateKey === 'string', errors.ERR_TOKEN_BASED_AUTH);
|
|
481
|
-
accessToken.privateKey = accessToken.privateKey
|
|
482
|
-
accessToken.privateKey = accessToken.privateKey.replace('-----BEGIN PRIVATE KEY-----', '');
|
|
483
|
-
accessToken.privateKey = accessToken.privateKey.replace('-----END PRIVATE KEY-----', '');
|
|
487
|
+
accessToken.privateKey = nodbUtil.denormalizePrivateKey(accessToken.privateKey);
|
|
484
488
|
}
|
|
485
489
|
|
|
486
490
|
// store token and privatekey
|
|
@@ -493,9 +497,20 @@ async function _verifyOptions(options, inCreatePool) {
|
|
|
493
497
|
|
|
494
498
|
}
|
|
495
499
|
|
|
496
|
-
// Check external Auth config
|
|
497
|
-
|
|
498
|
-
|
|
500
|
+
// Check external Auth config.
|
|
501
|
+
// Allow Session User enclosed in [] for proxy authentication.
|
|
502
|
+
if (outOptions.token === undefined && outOptions.externalAuth) {
|
|
503
|
+
if (outOptions.password) {
|
|
504
|
+
errors.throwErr(errors.ERR_WRONG_CRED_FOR_EXTAUTH);
|
|
505
|
+
}
|
|
506
|
+
if (outOptions.user) {
|
|
507
|
+
if (inCreatePool) {
|
|
508
|
+
errors.throwErr(errors.ERR_WRONG_CRED_FOR_EXTAUTH);
|
|
509
|
+
} else if (outOptions.user[0] !== '[' || outOptions.user.slice(-1) !== ']') {
|
|
510
|
+
// username is not enclosed in [].
|
|
511
|
+
errors.throwErr(errors.ERR_WRONG_USER_FORMAT_EXTAUTH_PROXY);
|
|
512
|
+
}
|
|
513
|
+
}
|
|
499
514
|
}
|
|
500
515
|
|
|
501
516
|
return outOptions;
|
|
@@ -682,12 +697,13 @@ function initOracleClient(arg1) {
|
|
|
682
697
|
errors.assertParamPropString(options, 1, "configDir");
|
|
683
698
|
errors.assertParamPropString(options, 1, "errorUrl");
|
|
684
699
|
errors.assertParamPropString(options, 1, "driverName");
|
|
700
|
+
errors.assertParamPropString(options, 1, "binaryDir");
|
|
685
701
|
}
|
|
686
702
|
if (settings.thinDriverInitialized) {
|
|
687
703
|
errors.throwErr(errors.ERR_THIN_CONNECTION_ALREADY_CREATED);
|
|
688
704
|
}
|
|
689
705
|
if (_initOracleClientArgs === undefined) {
|
|
690
|
-
const oracledbCLib = _initCLib();
|
|
706
|
+
const oracledbCLib = _initCLib(options);
|
|
691
707
|
if (options.driverName === undefined)
|
|
692
708
|
options.driverName = constants.DEFAULT_DRIVER_NAME + " thk";
|
|
693
709
|
if (options.errorUrl === undefined)
|
|
@@ -863,6 +879,7 @@ module.exports = {
|
|
|
863
879
|
DB_TYPE_TIMESTAMP_LTZ: types.DB_TYPE_TIMESTAMP_LTZ,
|
|
864
880
|
DB_TYPE_TIMESTAMP_TZ: types.DB_TYPE_TIMESTAMP_TZ,
|
|
865
881
|
DB_TYPE_VARCHAR: types.DB_TYPE_VARCHAR,
|
|
882
|
+
DB_TYPE_XMLTYPE: types.DB_TYPE_XMLTYPE,
|
|
866
883
|
|
|
867
884
|
// fetchInfo type defaulting
|
|
868
885
|
DEFAULT: constants.DEFAULT,
|
|
@@ -1008,6 +1025,9 @@ module.exports = {
|
|
|
1008
1025
|
ARRAY: constants.OUT_FORMAT_ARRAY,
|
|
1009
1026
|
OBJECT: constants.OUT_FORMAT_OBJECT,
|
|
1010
1027
|
|
|
1028
|
+
// Instances
|
|
1029
|
+
future,
|
|
1030
|
+
|
|
1011
1031
|
// property getters
|
|
1012
1032
|
get autoCommit() {
|
|
1013
1033
|
return settings.autoCommit;
|
package/lib/pool.js
CHANGED
|
@@ -192,10 +192,20 @@ class Pool extends EventEmitter {
|
|
|
192
192
|
outOptions.user = options.username;
|
|
193
193
|
}
|
|
194
194
|
|
|
195
|
+
if (this.externalAuth &&
|
|
196
|
+
outOptions.user && (outOptions.user[0] !== '['
|
|
197
|
+
|| outOptions.user.slice(-1) !== ']')) {
|
|
198
|
+
// username is not enclosed in [].
|
|
199
|
+
errors.throwErr(errors.ERR_WRONG_USER_FORMAT_EXTAUTH_PROXY);
|
|
200
|
+
}
|
|
201
|
+
|
|
195
202
|
// password must be a string
|
|
196
203
|
if (options.password !== undefined) {
|
|
197
204
|
errors.assertParamPropValue(typeof options.password === 'string', 1,
|
|
198
205
|
"password");
|
|
206
|
+
if (this.externalAuth) {
|
|
207
|
+
errors.throwErr(errors.ERR_WRONG_CRED_FOR_EXTAUTH);
|
|
208
|
+
}
|
|
199
209
|
outOptions.password = options.password;
|
|
200
210
|
}
|
|
201
211
|
|
package/lib/sodaCollection.js
CHANGED
|
@@ -188,6 +188,16 @@ class SodaCollection {
|
|
|
188
188
|
return doc;
|
|
189
189
|
}
|
|
190
190
|
|
|
191
|
+
//---------------------------------------------------------------------------
|
|
192
|
+
// listIndexes()
|
|
193
|
+
//
|
|
194
|
+
// To obtain all indices from the collection
|
|
195
|
+
//---------------------------------------------------------------------------
|
|
196
|
+
async listIndexes() {
|
|
197
|
+
const arr = await this._impl.listIndexes();
|
|
198
|
+
return arr.map(i => JSON.parse(i));
|
|
199
|
+
}
|
|
200
|
+
|
|
191
201
|
//---------------------------------------------------------------------------
|
|
192
202
|
// metaData()
|
|
193
203
|
//
|
|
@@ -262,6 +272,7 @@ nodbUtil.wrapFns(SodaCollection.prototype,
|
|
|
262
272
|
"insertManyAndGet",
|
|
263
273
|
"insertOne",
|
|
264
274
|
"insertOneAndGet",
|
|
275
|
+
"listIndexes",
|
|
265
276
|
"save",
|
|
266
277
|
"saveAndGet",
|
|
267
278
|
"truncate");
|
package/lib/sodaOperation.js
CHANGED
|
@@ -94,6 +94,22 @@ class SodaOperation {
|
|
|
94
94
|
}
|
|
95
95
|
}
|
|
96
96
|
|
|
97
|
+
|
|
98
|
+
//---------------------------------------------------------------------------
|
|
99
|
+
// lock()
|
|
100
|
+
//
|
|
101
|
+
// Pessimistic locking - similar to SELECT FOR UPDATE, these documents
|
|
102
|
+
// cannot be updated by other threads until an explicit commit/rollback is
|
|
103
|
+
// called. With autoCommit set to true is applicable only for one immediate
|
|
104
|
+
// operation and is not recommended in this context
|
|
105
|
+
//---------------------------------------------------------------------------
|
|
106
|
+
lock() {
|
|
107
|
+
errors.assertArgCount(arguments, 0, 0);
|
|
108
|
+
this._options.lock = true;
|
|
109
|
+
return this;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
|
|
97
113
|
//---------------------------------------------------------------------------
|
|
98
114
|
// replaceOne()
|
|
99
115
|
//
|
package/lib/thin/connection.js
CHANGED
|
@@ -32,7 +32,7 @@ const ThinResultSetImpl = require('./resultSet.js');
|
|
|
32
32
|
const ThinLobImpl = require("./lob.js");
|
|
33
33
|
const Protocol = require("./protocol/protocol.js");
|
|
34
34
|
const { BaseBuffer } = require('./protocol/buffer.js');
|
|
35
|
-
const {NetworkSession:nsi} = require("./sqlnet/networkSession.js");
|
|
35
|
+
const {NetworkSession: nsi} = require("./sqlnet/networkSession.js");
|
|
36
36
|
const { Statement } = require("./statement");
|
|
37
37
|
const thinUtil = require('./util');
|
|
38
38
|
const sqlNetConstants = require('./sqlnet/constants.js');
|
|
@@ -59,23 +59,29 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
59
59
|
* @return {Promise}
|
|
60
60
|
*/
|
|
61
61
|
async close() {
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
62
|
+
try {
|
|
63
|
+
if (this._protocol.txnInProgress) {
|
|
64
|
+
await this.rollback();
|
|
65
|
+
}
|
|
66
|
+
this._protocol.callTimeout = 0; // not applicable for close
|
|
67
|
+
if (this._drcpEnabled) {
|
|
68
|
+
await this._sessRelease();
|
|
69
|
+
this._drcpEstablishSession = true;
|
|
70
|
+
}
|
|
70
71
|
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
72
|
+
if (this._pool && !this._dropSess) {
|
|
73
|
+
await this._pool.release(this);
|
|
74
|
+
} else {
|
|
75
|
+
if (!this._drcpEnabled) {
|
|
76
|
+
const message = new messages.LogOffMessage(this);
|
|
77
|
+
await this._protocol._processMessage(message);
|
|
78
|
+
}
|
|
79
|
+
this.nscon.disconnect();
|
|
77
80
|
}
|
|
78
|
-
|
|
81
|
+
} catch (err) {
|
|
82
|
+
// immediate close of open socket on failure
|
|
83
|
+
// exception won't be thrown to user
|
|
84
|
+
this.nscon.disconnect(sqlNetConstants.NSFIMM);
|
|
79
85
|
}
|
|
80
86
|
}
|
|
81
87
|
|
|
@@ -153,6 +159,101 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
153
159
|
}
|
|
154
160
|
}
|
|
155
161
|
|
|
162
|
+
//---------------------------------------------------------------------------
|
|
163
|
+
// _execute()
|
|
164
|
+
//
|
|
165
|
+
// Calls the RPC that executes a SQL statement and returns the results.
|
|
166
|
+
//---------------------------------------------------------------------------
|
|
167
|
+
async _execute(statement, numIters, binds, options, executeManyFlag) {
|
|
168
|
+
|
|
169
|
+
// perform binds
|
|
170
|
+
const numBinds = statement.bindInfoList.length;
|
|
171
|
+
const numVars = binds.length;
|
|
172
|
+
if (numBinds !== numVars && (numVars === 0 || !binds[0].name)) {
|
|
173
|
+
errors.throwErr(errors.ERR_WRONG_NUMBER_OF_POSITIONAL_BINDS, numBinds, numVars);
|
|
174
|
+
}
|
|
175
|
+
for (let i = 0; i < binds.length; i++) {
|
|
176
|
+
await this._bind(statement, binds[i], i + 1);
|
|
177
|
+
}
|
|
178
|
+
if (statement.isPlSql && (options.batchErrors || options.dmlRowCounts)) {
|
|
179
|
+
errors.throwErr(errors.ERR_EXEC_MODE_ONLY_FOR_DML);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// send database request
|
|
183
|
+
const message = new messages.ExecuteMessage(this, statement, options);
|
|
184
|
+
message.numExecs = numIters;
|
|
185
|
+
message.arrayDmlRowCounts = options.dmlRowCounts;
|
|
186
|
+
message.batchErrors = options.batchErrors;
|
|
187
|
+
if (statement.isPlSql && statement.requiresFullExecute) {
|
|
188
|
+
message.numExecs = 1;
|
|
189
|
+
await this._protocol._processMessage(message);
|
|
190
|
+
statement.requiresFullExecute = false;
|
|
191
|
+
message.numExecs = numIters - 1;
|
|
192
|
+
message.offset = 1;
|
|
193
|
+
}
|
|
194
|
+
if (message.numExecs > 0) {
|
|
195
|
+
await this._protocol._processMessage(message);
|
|
196
|
+
statement.requiresFullExecute = false;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// if a define is required, send an additional request to the database
|
|
200
|
+
if (statement.requiresDefine && statement.sql) {
|
|
201
|
+
statement.requiresFullExecute = true;
|
|
202
|
+
await this._protocol._processMessage(message);
|
|
203
|
+
statement.requiresFullExecute = false;
|
|
204
|
+
statement.requiresDefine = false;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// process results
|
|
208
|
+
const result = {};
|
|
209
|
+
if (message.warning) {
|
|
210
|
+
result.warning = message.warning;
|
|
211
|
+
}
|
|
212
|
+
if (statement.numQueryVars > 0) {
|
|
213
|
+
result.resultSet = message.resultSet;
|
|
214
|
+
} else {
|
|
215
|
+
statement.bufferRowIndex = 0;
|
|
216
|
+
const outBinds = thinUtil.getOutBinds(statement, numIters,
|
|
217
|
+
executeManyFlag);
|
|
218
|
+
if (outBinds) {
|
|
219
|
+
result.outBinds = outBinds;
|
|
220
|
+
}
|
|
221
|
+
if (executeManyFlag) {
|
|
222
|
+
if (!statement.isPlSql) {
|
|
223
|
+
result.rowsAffected = statement.rowCount;
|
|
224
|
+
delete statement.rowCount;
|
|
225
|
+
}
|
|
226
|
+
if (options.dmlRowCounts) {
|
|
227
|
+
result.dmlRowCounts = options.dmlRowCounts;
|
|
228
|
+
}
|
|
229
|
+
if (options.batchErrors) {
|
|
230
|
+
result.batchErrors = options.batchErrors;
|
|
231
|
+
}
|
|
232
|
+
} else {
|
|
233
|
+
if (statement.isPlSql && options.implicitResultSet) {
|
|
234
|
+
result.implicitResults = options.implicitResultSet;
|
|
235
|
+
}
|
|
236
|
+
if (statement.lastRowid) {
|
|
237
|
+
result.lastRowid = statement.lastRowid;
|
|
238
|
+
delete statement.lastRowid;
|
|
239
|
+
}
|
|
240
|
+
if (statement.isPlSql) {
|
|
241
|
+
if (statement.rowCount) {
|
|
242
|
+
result.rowsAffected = statement.rowCount;
|
|
243
|
+
}
|
|
244
|
+
} else {
|
|
245
|
+
result.rowsAffected = statement.rowCount || 0;
|
|
246
|
+
}
|
|
247
|
+
if (statement.rowCount) {
|
|
248
|
+
delete statement.rowCount;
|
|
249
|
+
}
|
|
250
|
+
}
|
|
251
|
+
this._returnStatement(statement);
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
return result;
|
|
255
|
+
}
|
|
256
|
+
|
|
156
257
|
//---------------------------------------------------------------------------
|
|
157
258
|
// _parseElementType()
|
|
158
259
|
//
|
|
@@ -772,26 +873,6 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
772
873
|
return resultSet;
|
|
773
874
|
}
|
|
774
875
|
|
|
775
|
-
//---------------------------------------------------------------------------
|
|
776
|
-
// Prepares the sql given by user and binds the value to the statement object
|
|
777
|
-
//---------------------------------------------------------------------------
|
|
778
|
-
async _prepareAndBind(sql, binds, options, isParse = false) {
|
|
779
|
-
const stmt = this._prepare(sql, options);
|
|
780
|
-
let position = 0;
|
|
781
|
-
if (!isParse) {
|
|
782
|
-
const numBinds = stmt.bindInfoList.length;
|
|
783
|
-
const numVars = binds.length;
|
|
784
|
-
if (numBinds !== numVars && (numVars === 0 || !binds[0].name)) {
|
|
785
|
-
errors.throwErr(errors.ERR_WRONG_NUMBER_OF_POSITIONAL_BINDS, numBinds, numVars);
|
|
786
|
-
}
|
|
787
|
-
for (const variable of binds) {
|
|
788
|
-
await this._bind(stmt, variable, position + 1);
|
|
789
|
-
position += 1;
|
|
790
|
-
}
|
|
791
|
-
}
|
|
792
|
-
return stmt;
|
|
793
|
-
}
|
|
794
|
-
|
|
795
876
|
//---------------------------------------------------------------------------
|
|
796
877
|
// Clears the statement cache for the connection
|
|
797
878
|
//---------------------------------------------------------------------------
|
|
@@ -812,139 +893,46 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
812
893
|
}
|
|
813
894
|
|
|
814
895
|
//---------------------------------------------------------------------------
|
|
815
|
-
//
|
|
816
|
-
//
|
|
817
|
-
// information
|
|
896
|
+
// getStatementInfo()
|
|
897
|
+
//
|
|
898
|
+
// Parses the SQL statement and returns information about the statement.
|
|
818
899
|
//---------------------------------------------------------------------------
|
|
819
900
|
async getStatementInfo(sql) {
|
|
820
901
|
const options = {};
|
|
821
902
|
const result = {};
|
|
822
|
-
const statement =
|
|
903
|
+
const statement = this._prepare(sql, options);
|
|
823
904
|
options.connection = this;
|
|
824
|
-
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
|
|
828
|
-
|
|
829
|
-
}
|
|
830
|
-
if (statement.numQueryVars > 0) {
|
|
831
|
-
result.metaData = thinUtil.getMetadataMany(statement.queryVars);
|
|
832
|
-
}
|
|
833
|
-
result.bindNames = Array.from(statement.bindInfoDict.keys());
|
|
834
|
-
result.statementType = statement.statementType;
|
|
835
|
-
return result;
|
|
836
|
-
}
|
|
837
|
-
|
|
838
|
-
//---------------------------------------------------------------------------
|
|
839
|
-
// Prepares the sql given by the user,
|
|
840
|
-
// calls the OAL8 RPC that executes a SQL statement and returns the results.
|
|
841
|
-
//---------------------------------------------------------------------------
|
|
842
|
-
async execute(sql, numIters, binds, options, executeManyFlag) {
|
|
843
|
-
const result = {};
|
|
844
|
-
if (executeManyFlag) {
|
|
845
|
-
return await this.executeMany(sql, numIters, binds, options);
|
|
846
|
-
}
|
|
847
|
-
const statement = await this._prepareAndBind(sql, binds, options);
|
|
848
|
-
|
|
849
|
-
// send the initial request to the database
|
|
850
|
-
const message = new messages.ExecuteMessage(this, statement, options);
|
|
851
|
-
message.numExecs = 1;
|
|
852
|
-
await this._protocol._processMessage(message);
|
|
853
|
-
statement.requiresFullExecute = false;
|
|
854
|
-
|
|
855
|
-
// if a define is required, send an additional request to the database
|
|
856
|
-
if (statement.requiresDefine && statement.sql) {
|
|
857
|
-
statement.requiresFullExecute = true;
|
|
858
|
-
await this._protocol._processMessage(message);
|
|
859
|
-
statement.requiresFullExecute = false;
|
|
860
|
-
statement.requiresDefine = false;
|
|
861
|
-
}
|
|
862
|
-
|
|
863
|
-
// process message results
|
|
864
|
-
if (statement.numQueryVars > 0) {
|
|
865
|
-
result.resultSet = message.resultSet;
|
|
866
|
-
} else {
|
|
867
|
-
statement.bufferRowIndex = 0;
|
|
868
|
-
const bindVars = thinUtil.getBindVars(statement);
|
|
869
|
-
const outBinds = thinUtil.getExecuteOutBinds(bindVars);
|
|
870
|
-
if (outBinds) {
|
|
871
|
-
result.outBinds = outBinds;
|
|
872
|
-
}
|
|
873
|
-
if (statement.isPlSql) {
|
|
874
|
-
if (options.implicitResultSet) {
|
|
875
|
-
result.implicitResults = options.implicitResultSet;
|
|
876
|
-
}
|
|
877
|
-
}
|
|
878
|
-
if (statement.lastRowid) {
|
|
879
|
-
result.lastRowid = statement.lastRowid;
|
|
880
|
-
delete statement.lastRowid;
|
|
881
|
-
}
|
|
882
|
-
if (statement.isPlSql) {
|
|
883
|
-
if (statement.rowCount) {
|
|
884
|
-
result.rowsAffected = statement.rowCount;
|
|
885
|
-
}
|
|
886
|
-
} else {
|
|
887
|
-
result.rowsAffected = statement.rowCount || 0;
|
|
905
|
+
try {
|
|
906
|
+
if (!statement.isDdl) {
|
|
907
|
+
const message = new messages.ExecuteMessage(this, statement, options);
|
|
908
|
+
message.parseOnly = true;
|
|
909
|
+
await this._protocol._processMessage(message);
|
|
888
910
|
}
|
|
889
|
-
if (statement.
|
|
890
|
-
|
|
911
|
+
if (statement.numQueryVars > 0) {
|
|
912
|
+
result.metaData = thinUtil.getMetadataMany(statement.queryVars);
|
|
891
913
|
}
|
|
914
|
+
result.bindNames = Array.from(statement.bindInfoDict.keys());
|
|
915
|
+
result.statementType = statement.statementType;
|
|
916
|
+
return result;
|
|
917
|
+
} finally {
|
|
892
918
|
this._returnStatement(statement);
|
|
893
919
|
}
|
|
894
|
-
|
|
895
|
-
return result;
|
|
896
920
|
}
|
|
897
921
|
|
|
898
922
|
//---------------------------------------------------------------------------
|
|
899
|
-
//
|
|
923
|
+
// execute()
|
|
900
924
|
//
|
|
901
|
-
//
|
|
902
|
-
// statement multiple times and returns the results.
|
|
925
|
+
// Calls the RPC that executes a SQL statement and returns the results.
|
|
903
926
|
//---------------------------------------------------------------------------
|
|
904
|
-
async
|
|
905
|
-
const statement =
|
|
906
|
-
|
|
907
|
-
|
|
908
|
-
|
|
909
|
-
|
|
910
|
-
|
|
911
|
-
|
|
912
|
-
message.numExecs = numIters;
|
|
913
|
-
message.arrayDmlRowCounts = options.dmlRowCounts;
|
|
914
|
-
message.batchErrors = options.batchErrors;
|
|
915
|
-
if (statement.isPlSql && statement.requiresFullExecute) {
|
|
916
|
-
message.numExecs = 1;
|
|
917
|
-
await this._protocol._processMessage(message);
|
|
918
|
-
statement.requiresFullExecute = false;
|
|
919
|
-
message.numExecs = numIters - 1;
|
|
920
|
-
message.offset = 1;
|
|
921
|
-
}
|
|
922
|
-
if (message.numExecs > 0) {
|
|
923
|
-
await this._protocol._processMessage(message);
|
|
924
|
-
}
|
|
925
|
-
|
|
926
|
-
// process results
|
|
927
|
-
const returnObj = {};
|
|
928
|
-
statement.bufferRowIndex = 0;
|
|
929
|
-
const bindVars = thinUtil.getBindVars(statement);
|
|
930
|
-
const outBinds = thinUtil.getExecuteManyOutBinds(bindVars, numIters);
|
|
931
|
-
if (outBinds) {
|
|
932
|
-
returnObj.outBinds = outBinds;
|
|
933
|
-
}
|
|
934
|
-
const rowsAffected = !statement.isPlSql ? statement.rowCount : undefined;
|
|
935
|
-
if (rowsAffected) {
|
|
936
|
-
returnObj.rowsAffected = rowsAffected;
|
|
937
|
-
delete statement.rowCount;
|
|
938
|
-
}
|
|
939
|
-
if (options.dmlRowCounts) {
|
|
940
|
-
returnObj.dmlRowCounts = options.dmlRowCounts;
|
|
941
|
-
}
|
|
942
|
-
if (options.batchErrors) {
|
|
943
|
-
returnObj.batchErrors = options.batchErrors;
|
|
927
|
+
async execute(sql, numIters, binds, options, executeManyFlag) {
|
|
928
|
+
const statement = this._prepare(sql, options);
|
|
929
|
+
try {
|
|
930
|
+
return await this._execute(statement, numIters, binds, options,
|
|
931
|
+
executeManyFlag);
|
|
932
|
+
} catch (err) {
|
|
933
|
+
this._returnStatement(statement);
|
|
934
|
+
throw err;
|
|
944
935
|
}
|
|
945
|
-
this._returnStatement(statement);
|
|
946
|
-
|
|
947
|
-
return returnObj;
|
|
948
936
|
}
|
|
949
937
|
|
|
950
938
|
//---------------------------------------------------------------------------
|
|
@@ -1100,6 +1088,47 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
1100
1088
|
getInstanceName() {
|
|
1101
1089
|
return this.instanceName;
|
|
1102
1090
|
}
|
|
1103
|
-
}
|
|
1104
1091
|
|
|
1092
|
+
//---------------------------------------------------------------------------
|
|
1093
|
+
// Returns the Oracle Database domain name associated with the connection.
|
|
1094
|
+
//---------------------------------------------------------------------------
|
|
1095
|
+
getDbDomain() {
|
|
1096
|
+
return this.dbDomain;
|
|
1097
|
+
}
|
|
1098
|
+
|
|
1099
|
+
//---------------------------------------------------------------------------
|
|
1100
|
+
// Returns the Oracle Database name associated with the connection.
|
|
1101
|
+
//---------------------------------------------------------------------------
|
|
1102
|
+
getDbName() {
|
|
1103
|
+
return this.dbName;
|
|
1104
|
+
}
|
|
1105
|
+
|
|
1106
|
+
//---------------------------------------------------------------------------
|
|
1107
|
+
// Returns maximum number of cursors that can be opened in one session.
|
|
1108
|
+
//---------------------------------------------------------------------------
|
|
1109
|
+
getMaxOpenCursors() {
|
|
1110
|
+
return this.maxOpenCursors;
|
|
1111
|
+
}
|
|
1112
|
+
|
|
1113
|
+
//---------------------------------------------------------------------------
|
|
1114
|
+
// Returns the Oracle Database service name associated with the connection.
|
|
1115
|
+
//---------------------------------------------------------------------------
|
|
1116
|
+
getServiceName() {
|
|
1117
|
+
return this.serviceName;
|
|
1118
|
+
}
|
|
1119
|
+
|
|
1120
|
+
//---------------------------------------------------------------------------
|
|
1121
|
+
// Returns boolean based on this._protocol.txnInProgress value.
|
|
1122
|
+
//---------------------------------------------------------------------------
|
|
1123
|
+
getTransactionInProgress() {
|
|
1124
|
+
return this._protocol.txnInProgress === constants.TNS_TXN_IN_PROGRESS;
|
|
1125
|
+
}
|
|
1126
|
+
|
|
1127
|
+
//---------------------------------------------------------------------------
|
|
1128
|
+
// Returns the warning object.
|
|
1129
|
+
//---------------------------------------------------------------------------
|
|
1130
|
+
getWarning() {
|
|
1131
|
+
return this.warning;
|
|
1132
|
+
}
|
|
1133
|
+
}
|
|
1105
1134
|
module.exports = ThinConnectionImpl;
|