oracledb 6.0.3 → 6.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/build/Release/oracledb-6.2.0-darwin-x64.node +0 -0
- package/build/Release/oracledb-6.2.0-darwin-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.2.0-js-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.2.0-linux-arm64.node +0 -0
- package/build/Release/oracledb-6.2.0-linux-arm64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.2.0-linux-x64.node +0 -0
- package/build/Release/oracledb-6.2.0-linux-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.2.0-win32-x64.node +0 -0
- package/build/Release/oracledb-6.2.0-win32-x64.node-buildinfo.txt +1 -0
- package/examples/dbconfig.js +7 -14
- package/examples/example.js +0 -1
- package/lib/aqQueue.js +40 -26
- package/lib/connection.js +16 -4
- package/lib/dbObject.js +9 -0
- package/lib/errors.js +17 -13
- package/lib/impl/connection.js +9 -0
- package/lib/impl/resultset.js +7 -4
- package/lib/oracledb.js +26 -18
- package/lib/pool.js +7 -1
- package/lib/sodaCollection.js +12 -1
- package/lib/sodaOperation.js +16 -0
- package/lib/thin/connection.js +229 -182
- package/lib/thin/dbObject.js +4 -1
- package/lib/thin/pool.js +153 -68
- package/lib/thin/protocol/buffer.js +83 -64
- package/lib/thin/protocol/constants.js +3 -14
- package/lib/thin/protocol/encryptDecrypt.js +17 -17
- package/lib/thin/protocol/messages/auth.js +21 -23
- package/lib/thin/protocol/messages/base.js +29 -45
- package/lib/thin/protocol/messages/connectionCookie.js +76 -0
- package/lib/thin/protocol/messages/dataType.js +13 -9
- package/lib/thin/protocol/messages/execute.js +7 -7
- package/lib/thin/protocol/messages/index.js +2 -0
- package/lib/thin/protocol/messages/protocol.js +31 -20
- package/lib/thin/protocol/messages/withData.js +58 -47
- package/lib/thin/protocol/oson.js +17 -14
- package/lib/thin/protocol/packet.js +36 -14
- package/lib/thin/protocol/utils.js +2 -2
- package/lib/thin/resultSet.js +6 -6
- package/lib/thin/sqlnet/connStrategy.js +130 -5
- package/lib/thin/sqlnet/constants.js +2 -0
- package/lib/thin/sqlnet/ezConnectResolver.js +29 -61
- package/lib/thin/sqlnet/navNodes.js +34 -27
- package/lib/thin/sqlnet/networkSession.js +46 -47
- package/lib/thin/sqlnet/ntTcp.js +30 -14
- package/lib/thin/sqlnet/nvStrToNvPair.js +16 -16
- package/lib/thin/sqlnet/packet.js +10 -3
- package/lib/thin/sqlnet/paramParser.js +9 -9
- package/lib/thin/sqlnet/sessionAtts.js +4 -0
- package/lib/thin/statement.js +345 -113
- package/lib/thin/util.js +23 -86
- package/lib/transformer.js +3 -1
- package/lib/util.js +4 -13
- package/lib/version.js +2 -2
- package/package.json +1 -1
- package/build/Release/oracledb-6.0.3-darwin-x64.node +0 -0
- package/build/Release/oracledb-6.0.3-darwin-x64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.0.3-js-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.0.3-linux-arm64.node +0 -0
- package/build/Release/oracledb-6.0.3-linux-arm64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.0.3-linux-x64.node +0 -0
- package/build/Release/oracledb-6.0.3-linux-x64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.0.3-win32-x64.node +0 -0
- package/build/Release/oracledb-6.0.3-win32-x64.node-buildinfo.txt +0 -1
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
|
|
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');
|
|
@@ -49,6 +49,8 @@ const finalizationRegistry = new global.FinalizationRegistry((heldValue) => {
|
|
|
49
49
|
class TDSBuffer extends BaseBuffer {
|
|
50
50
|
}
|
|
51
51
|
|
|
52
|
+
const connectionCookies = new Map();
|
|
53
|
+
|
|
52
54
|
class ThinConnectionImpl extends ConnectionImpl {
|
|
53
55
|
|
|
54
56
|
/**
|
|
@@ -57,23 +59,29 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
57
59
|
* @return {Promise}
|
|
58
60
|
*/
|
|
59
61
|
async close() {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
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
|
+
}
|
|
68
71
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
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();
|
|
75
80
|
}
|
|
76
|
-
|
|
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);
|
|
77
85
|
}
|
|
78
86
|
}
|
|
79
87
|
|
|
@@ -151,6 +159,98 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
151
159
|
}
|
|
152
160
|
}
|
|
153
161
|
|
|
162
|
+
//---------------------------------------------------------------------------
|
|
163
|
+
// _execute()
|
|
164
|
+
//
|
|
165
|
+
// Calls the RPC that executes a SQL statement and returns the results.
|
|
166
|
+
//---------------------------------------------------------------------------
|
|
167
|
+
async _execute(statement, numIters, binds, options, executeManyFlag) {
|
|
168
|
+
|
|
169
|
+
// perform binds
|
|
170
|
+
const numBinds = statement.bindInfoList.length;
|
|
171
|
+
const numVars = binds.length;
|
|
172
|
+
if (numBinds !== numVars && (numVars === 0 || !binds[0].name)) {
|
|
173
|
+
errors.throwErr(errors.ERR_WRONG_NUMBER_OF_POSITIONAL_BINDS, numBinds, numVars);
|
|
174
|
+
}
|
|
175
|
+
for (let i = 0; i < binds.length; i++) {
|
|
176
|
+
await this._bind(statement, binds[i], i + 1);
|
|
177
|
+
}
|
|
178
|
+
if (statement.isPlSql && (options.batchErrors || options.dmlRowCounts)) {
|
|
179
|
+
errors.throwErr(errors.ERR_EXEC_MODE_ONLY_FOR_DML);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
// send database request
|
|
183
|
+
const message = new messages.ExecuteMessage(this, statement, options);
|
|
184
|
+
message.numExecs = numIters;
|
|
185
|
+
message.arrayDmlRowCounts = options.dmlRowCounts;
|
|
186
|
+
message.batchErrors = options.batchErrors;
|
|
187
|
+
if (statement.isPlSql && statement.requiresFullExecute) {
|
|
188
|
+
message.numExecs = 1;
|
|
189
|
+
await this._protocol._processMessage(message);
|
|
190
|
+
statement.requiresFullExecute = false;
|
|
191
|
+
message.numExecs = numIters - 1;
|
|
192
|
+
message.offset = 1;
|
|
193
|
+
}
|
|
194
|
+
if (message.numExecs > 0) {
|
|
195
|
+
await this._protocol._processMessage(message);
|
|
196
|
+
statement.requiresFullExecute = false;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
// if a define is required, send an additional request to the database
|
|
200
|
+
if (statement.requiresDefine && statement.sql) {
|
|
201
|
+
statement.requiresFullExecute = true;
|
|
202
|
+
await this._protocol._processMessage(message);
|
|
203
|
+
statement.requiresFullExecute = false;
|
|
204
|
+
statement.requiresDefine = false;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
// process results
|
|
208
|
+
const result = {};
|
|
209
|
+
if (statement.numQueryVars > 0) {
|
|
210
|
+
result.resultSet = message.resultSet;
|
|
211
|
+
} else {
|
|
212
|
+
statement.bufferRowIndex = 0;
|
|
213
|
+
const outBinds = thinUtil.getOutBinds(statement, numIters,
|
|
214
|
+
executeManyFlag);
|
|
215
|
+
if (outBinds) {
|
|
216
|
+
result.outBinds = outBinds;
|
|
217
|
+
}
|
|
218
|
+
if (executeManyFlag) {
|
|
219
|
+
if (!statement.isPlSql) {
|
|
220
|
+
result.rowsAffected = statement.rowCount;
|
|
221
|
+
delete statement.rowCount;
|
|
222
|
+
}
|
|
223
|
+
if (options.dmlRowCounts) {
|
|
224
|
+
result.dmlRowCounts = options.dmlRowCounts;
|
|
225
|
+
}
|
|
226
|
+
if (options.batchErrors) {
|
|
227
|
+
result.batchErrors = options.batchErrors;
|
|
228
|
+
}
|
|
229
|
+
} else {
|
|
230
|
+
if (statement.isPlSql && options.implicitResultSet) {
|
|
231
|
+
result.implicitResults = options.implicitResultSet;
|
|
232
|
+
}
|
|
233
|
+
if (statement.lastRowid) {
|
|
234
|
+
result.lastRowid = statement.lastRowid;
|
|
235
|
+
delete statement.lastRowid;
|
|
236
|
+
}
|
|
237
|
+
if (statement.isPlSql) {
|
|
238
|
+
if (statement.rowCount) {
|
|
239
|
+
result.rowsAffected = statement.rowCount;
|
|
240
|
+
}
|
|
241
|
+
} else {
|
|
242
|
+
result.rowsAffected = statement.rowCount || 0;
|
|
243
|
+
}
|
|
244
|
+
if (statement.rowCount) {
|
|
245
|
+
delete statement.rowCount;
|
|
246
|
+
}
|
|
247
|
+
}
|
|
248
|
+
this._returnStatement(statement);
|
|
249
|
+
}
|
|
250
|
+
|
|
251
|
+
return result;
|
|
252
|
+
}
|
|
253
|
+
|
|
154
254
|
//---------------------------------------------------------------------------
|
|
155
255
|
// _parseElementType()
|
|
156
256
|
//
|
|
@@ -443,10 +543,6 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
443
543
|
await this._protocol.breakMessage();
|
|
444
544
|
}
|
|
445
545
|
|
|
446
|
-
_healthStatus() {
|
|
447
|
-
return this.nscon.recvInbandNotif();
|
|
448
|
-
}
|
|
449
|
-
|
|
450
546
|
isHealthy() {
|
|
451
547
|
try {
|
|
452
548
|
if (this.nscon.recvInbandNotif() === 0)
|
|
@@ -461,6 +557,26 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
461
557
|
return (this._pool) ? true : false;
|
|
462
558
|
}
|
|
463
559
|
|
|
560
|
+
//---------------------------------------------------------------------------
|
|
561
|
+
// getConnectionCookieByUUID()
|
|
562
|
+
//
|
|
563
|
+
// It fetches from map which keeps keyname as UUID+ServiceName.
|
|
564
|
+
// UUID identifies the CDB instance and ServiceName identifies the
|
|
565
|
+
// entity within a PDB which uniquely identifies a pdb instance.
|
|
566
|
+
//---------------------------------------------------------------------------
|
|
567
|
+
getConnectionCookieByUUID(uuid) {
|
|
568
|
+
let cookie;
|
|
569
|
+
if (uuid) {
|
|
570
|
+
const key = uuid + ((this.serviceName) ? this.serviceName : this.sid);
|
|
571
|
+
cookie = connectionCookies.get(key);
|
|
572
|
+
if (!cookie) {
|
|
573
|
+
cookie = {};
|
|
574
|
+
connectionCookies.set(key, cookie);
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
return cookie;
|
|
578
|
+
}
|
|
579
|
+
|
|
464
580
|
/**
|
|
465
581
|
*
|
|
466
582
|
* @param {object} params Configuration of the connection
|
|
@@ -499,22 +615,32 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
499
615
|
this._clientInfoModified = false;
|
|
500
616
|
this._module = "";
|
|
501
617
|
this._moduleModified = false;
|
|
618
|
+
this._drcpEnabled = false;
|
|
502
619
|
this.serviceName = '';
|
|
503
620
|
this.remoteAddress = '';
|
|
504
|
-
this.privilege = params.privilege;
|
|
505
621
|
this.comboKey = null; // used in changePassword API
|
|
506
622
|
|
|
507
623
|
this.nscon = new nsi();
|
|
508
624
|
finalizationRegistry.register(this, this.nscon);
|
|
509
625
|
await this.nscon.connect(params);
|
|
510
626
|
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
627
|
+
let serverType;
|
|
628
|
+
if (this.isPooled()) {
|
|
629
|
+
serverType = params._connInfo[0];
|
|
630
|
+
this.serviceName = params._connInfo[2];
|
|
631
|
+
this.purity = params._connInfo[3] | constants.PURITY_DEFAULT;
|
|
632
|
+
this.sid = params._connInfo[4];
|
|
633
|
+
} else {
|
|
634
|
+
serverType = this.nscon.getOption(sqlNetConstants.SERVERTYPE);
|
|
635
|
+
this.serviceName = this.nscon.getOption(sqlNetConstants.SVCNAME);
|
|
636
|
+
this.sid = this.nscon.getOption(sqlNetConstants.SID);
|
|
637
|
+
this.purity = this.nscon.getOption(sqlNetConstants.PURITY) | constants.PURITY_DEFAULT;
|
|
638
|
+
}
|
|
639
|
+
if (serverType) {
|
|
640
|
+
this._drcpEnabled = serverType.toLowerCase() === 'pooled';
|
|
641
|
+
}
|
|
516
642
|
this.remoteAddress = this.nscon.getOption(sqlNetConstants.REMOTEADDR);
|
|
517
|
-
this.
|
|
643
|
+
this.connectionClass = params.connectionClass;
|
|
518
644
|
|
|
519
645
|
/*
|
|
520
646
|
* if drcp is used, use purity = NEW as the default purity for
|
|
@@ -538,13 +664,41 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
538
664
|
}
|
|
539
665
|
|
|
540
666
|
try {
|
|
541
|
-
|
|
542
|
-
|
|
543
|
-
|
|
544
|
-
|
|
545
|
-
|
|
546
|
-
|
|
547
|
-
|
|
667
|
+
const cookie = this.getConnectionCookieByUUID(this.nscon.dbUUID);
|
|
668
|
+
this.nscon.dbUUID = null;
|
|
669
|
+
const protocolMessage = new messages.ProtocolMessage(this);
|
|
670
|
+
const dataTypeMessage = new messages.DataTypeMessage(this);
|
|
671
|
+
const authMessage = new messages.AuthMessage(this, params);
|
|
672
|
+
let sentCookie = false;
|
|
673
|
+
if (cookie && cookie.populated) {
|
|
674
|
+
const cookieMessage = new messages.ConnectionCookieMessage(this);
|
|
675
|
+
cookieMessage.cookie = cookie;
|
|
676
|
+
cookieMessage.protocolMessage = protocolMessage;
|
|
677
|
+
cookieMessage.dataTypeMessage = dataTypeMessage;
|
|
678
|
+
cookieMessage.authMessage = authMessage;
|
|
679
|
+
await this._protocol._processMessage(cookieMessage);
|
|
680
|
+
sentCookie = true;
|
|
681
|
+
} else {
|
|
682
|
+
await this._protocol._processMessage(protocolMessage);
|
|
683
|
+
}
|
|
684
|
+
if (!sentCookie || !cookie.populated) {
|
|
685
|
+
await this._protocol._processMessage(dataTypeMessage);
|
|
686
|
+
// Does OSESSKEY for non-token Authentication else OAUTH
|
|
687
|
+
await this._protocol._processMessage(authMessage);
|
|
688
|
+
if (cookie && !cookie.populated) {
|
|
689
|
+
cookie.protocolVersion = protocolMessage.serverVersion;
|
|
690
|
+
cookie.serverBanner = protocolMessage.serverBanner;
|
|
691
|
+
cookie.charsetID = this._protocol.caps.charSetID;
|
|
692
|
+
cookie.ncharsetID = this._protocol.caps.nCharsetId;
|
|
693
|
+
cookie.flags = protocolMessage.serverFlags;
|
|
694
|
+
cookie.compileCaps = Buffer.from(protocolMessage.serverCompileCaps);
|
|
695
|
+
cookie.runtimeCaps = Buffer.from(protocolMessage.serverRunTimeCaps);
|
|
696
|
+
cookie.populated = true;
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
if (!params.token) { // non-token Authentication
|
|
700
|
+
await this._protocol._processMessage(authMessage); // OAUTH
|
|
701
|
+
}
|
|
548
702
|
} catch (err) {
|
|
549
703
|
this.nscon.disconnect();
|
|
550
704
|
throw err;
|
|
@@ -614,7 +768,7 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
614
768
|
// option is true
|
|
615
769
|
//---------------------------------------------------------------------------
|
|
616
770
|
_prepare(sql, options) {
|
|
617
|
-
|
|
771
|
+
const statement = this._getStatement(sql, options.keepInStmtCache);
|
|
618
772
|
statement.bufferRowIndex = 0;
|
|
619
773
|
statement.bufferRowCount = 0;
|
|
620
774
|
statement.lastRowIndex = 0;
|
|
@@ -626,8 +780,8 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
626
780
|
// Binds the values by user to the statement object
|
|
627
781
|
//---------------------------------------------------------------------------
|
|
628
782
|
async _bind(stmt, variable, pos = 0) {
|
|
629
|
-
|
|
630
|
-
|
|
783
|
+
const bindInfoDict = stmt.bindInfoDict;
|
|
784
|
+
const bindInfoList = stmt.bindInfoList;
|
|
631
785
|
|
|
632
786
|
/*
|
|
633
787
|
* For PL/SQL blocks, if the size of a string or bytes object exceeds
|
|
@@ -650,8 +804,8 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
650
804
|
if (val === null) {
|
|
651
805
|
return null;
|
|
652
806
|
}
|
|
653
|
-
|
|
654
|
-
|
|
807
|
+
const data = await val.getData();
|
|
808
|
+
const len = val._length;
|
|
655
809
|
if (data && len > maxSize) {
|
|
656
810
|
errors.throwErr(errors.ERR_INSUFFICIENT_BUFFER_FOR_BINDS);
|
|
657
811
|
}
|
|
@@ -662,7 +816,7 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
662
816
|
if (variable.type === types.DB_TYPE_CLOB ||
|
|
663
817
|
variable.type === types.DB_TYPE_NCLOB ||
|
|
664
818
|
variable.type === types.DB_TYPE_BLOB) {
|
|
665
|
-
for (
|
|
819
|
+
for (const [index, val] of variable.values.entries()) {
|
|
666
820
|
if (!(val instanceof ThinLobImpl)) {
|
|
667
821
|
if (val && val.length > 0) {
|
|
668
822
|
const lobImpl = new ThinLobImpl();
|
|
@@ -693,7 +847,7 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
693
847
|
stmt._setVariable(bindInfo, variable);
|
|
694
848
|
});
|
|
695
849
|
} else {
|
|
696
|
-
|
|
850
|
+
const bindInfo = bindInfoList[pos - 1];
|
|
697
851
|
stmt._setVariable(bindInfo, variable);
|
|
698
852
|
}
|
|
699
853
|
}
|
|
@@ -716,30 +870,10 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
716
870
|
return resultSet;
|
|
717
871
|
}
|
|
718
872
|
|
|
719
|
-
//---------------------------------------------------------------------------
|
|
720
|
-
// Prepares the sql given by user and binds the value to the statement object
|
|
721
|
-
//---------------------------------------------------------------------------
|
|
722
|
-
async _prepareAndBind(sql, binds, options, isParse = false) {
|
|
723
|
-
const stmt = this._prepare(sql, options);
|
|
724
|
-
let position = 0;
|
|
725
|
-
if (!isParse) {
|
|
726
|
-
const numBinds = stmt.bindInfoList.length;
|
|
727
|
-
const numVars = binds.length;
|
|
728
|
-
if (numBinds !== numVars && (numVars === 0 || !binds[0].name)) {
|
|
729
|
-
errors.throwErr(errors.ERR_WRONG_NUMBER_OF_POSITIONAL_BINDS, numBinds, numVars);
|
|
730
|
-
}
|
|
731
|
-
for (const variable of binds) {
|
|
732
|
-
await this._bind(stmt, variable, position + 1);
|
|
733
|
-
position += 1;
|
|
734
|
-
}
|
|
735
|
-
}
|
|
736
|
-
return stmt;
|
|
737
|
-
}
|
|
738
|
-
|
|
739
873
|
//---------------------------------------------------------------------------
|
|
740
874
|
// Clears the statement cache for the connection
|
|
741
875
|
//---------------------------------------------------------------------------
|
|
742
|
-
|
|
876
|
+
resetStatementCache() {
|
|
743
877
|
this.statementCache.clear();
|
|
744
878
|
this._cursorsToClose.clear();
|
|
745
879
|
}
|
|
@@ -756,139 +890,46 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
756
890
|
}
|
|
757
891
|
|
|
758
892
|
//---------------------------------------------------------------------------
|
|
759
|
-
//
|
|
760
|
-
//
|
|
761
|
-
// information
|
|
893
|
+
// getStatementInfo()
|
|
894
|
+
//
|
|
895
|
+
// Parses the SQL statement and returns information about the statement.
|
|
762
896
|
//---------------------------------------------------------------------------
|
|
763
897
|
async getStatementInfo(sql) {
|
|
764
|
-
|
|
765
|
-
let result = {};
|
|
766
|
-
let statement = await this._prepareAndBind(sql, null, options, true);
|
|
767
|
-
options.connection = this;
|
|
768
|
-
// parse the statement (but not for DDL which doesn't support it)
|
|
769
|
-
if (!statement.isDdl) {
|
|
770
|
-
const message = new messages.ExecuteMessage(this, statement, options);
|
|
771
|
-
message.parseOnly = true;
|
|
772
|
-
await this._protocol._processMessage(message);
|
|
773
|
-
}
|
|
774
|
-
if (statement.numQueryVars > 0) {
|
|
775
|
-
result.metaData = thinUtil.getMetadataMany(statement.queryVars);
|
|
776
|
-
}
|
|
777
|
-
result.bindNames = Array.from(statement.bindInfoDict.keys());
|
|
778
|
-
result.statementType = statement.statementType;
|
|
779
|
-
return result;
|
|
780
|
-
}
|
|
781
|
-
|
|
782
|
-
//---------------------------------------------------------------------------
|
|
783
|
-
// Prepares the sql given by the user,
|
|
784
|
-
// calls the OAL8 RPC that executes a SQL statement and returns the results.
|
|
785
|
-
//---------------------------------------------------------------------------
|
|
786
|
-
async execute(sql, numIters, binds, options, executeManyFlag) {
|
|
898
|
+
const options = {};
|
|
787
899
|
const result = {};
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
793
|
-
|
|
794
|
-
|
|
795
|
-
message.numExecs = 1;
|
|
796
|
-
await this._protocol._processMessage(message);
|
|
797
|
-
statement.requiresFullExecute = false;
|
|
798
|
-
|
|
799
|
-
// if a define is required, send an additional request to the database
|
|
800
|
-
if (statement.requiresDefine && statement.sql) {
|
|
801
|
-
statement.requiresFullExecute = true;
|
|
802
|
-
await this._protocol._processMessage(message);
|
|
803
|
-
statement.requiresFullExecute = false;
|
|
804
|
-
statement.requiresDefine = false;
|
|
805
|
-
}
|
|
806
|
-
|
|
807
|
-
// process message results
|
|
808
|
-
if (statement.numQueryVars > 0) {
|
|
809
|
-
result.resultSet = message.resultSet;
|
|
810
|
-
} else {
|
|
811
|
-
statement.bufferRowIndex = 0;
|
|
812
|
-
const bindVars = thinUtil.getBindVars(statement);
|
|
813
|
-
const outBinds = thinUtil.getExecuteOutBinds(bindVars);
|
|
814
|
-
if (outBinds) {
|
|
815
|
-
result.outBinds = outBinds;
|
|
816
|
-
}
|
|
817
|
-
if (statement.isPlSql) {
|
|
818
|
-
if (options.implicitResultSet) {
|
|
819
|
-
result.implicitResults = options.implicitResultSet;
|
|
820
|
-
}
|
|
821
|
-
}
|
|
822
|
-
if (statement.lastRowid) {
|
|
823
|
-
result.lastRowid = statement.lastRowid;
|
|
824
|
-
delete statement.lastRowid;
|
|
825
|
-
}
|
|
826
|
-
if (statement.isPlSql) {
|
|
827
|
-
if (statement.rowCount) {
|
|
828
|
-
result.rowsAffected = statement.rowCount;
|
|
829
|
-
}
|
|
830
|
-
} else {
|
|
831
|
-
result.rowsAffected = statement.rowCount || 0;
|
|
900
|
+
const statement = this._prepare(sql, options);
|
|
901
|
+
options.connection = this;
|
|
902
|
+
try {
|
|
903
|
+
if (!statement.isDdl) {
|
|
904
|
+
const message = new messages.ExecuteMessage(this, statement, options);
|
|
905
|
+
message.parseOnly = true;
|
|
906
|
+
await this._protocol._processMessage(message);
|
|
832
907
|
}
|
|
833
|
-
if (statement.
|
|
834
|
-
|
|
908
|
+
if (statement.numQueryVars > 0) {
|
|
909
|
+
result.metaData = thinUtil.getMetadataMany(statement.queryVars);
|
|
835
910
|
}
|
|
911
|
+
result.bindNames = Array.from(statement.bindInfoDict.keys());
|
|
912
|
+
result.statementType = statement.statementType;
|
|
913
|
+
return result;
|
|
914
|
+
} finally {
|
|
836
915
|
this._returnStatement(statement);
|
|
837
916
|
}
|
|
838
|
-
|
|
839
|
-
return result;
|
|
840
917
|
}
|
|
841
918
|
|
|
842
919
|
//---------------------------------------------------------------------------
|
|
843
|
-
//
|
|
920
|
+
// execute()
|
|
844
921
|
//
|
|
845
|
-
//
|
|
846
|
-
// statement multiple times and returns the results.
|
|
922
|
+
// Calls the RPC that executes a SQL statement and returns the results.
|
|
847
923
|
//---------------------------------------------------------------------------
|
|
848
|
-
async
|
|
849
|
-
const statement =
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
|
|
856
|
-
message.numExecs = numIters;
|
|
857
|
-
message.arrayDmlRowCounts = options.dmlRowCounts;
|
|
858
|
-
message.batchErrors = options.batchErrors;
|
|
859
|
-
if (statement.isPlSql && statement.requiresFullExecute) {
|
|
860
|
-
message.numExecs = 1;
|
|
861
|
-
await this._protocol._processMessage(message);
|
|
862
|
-
statement.requiresFullExecute = false;
|
|
863
|
-
message.numExecs = numIters - 1;
|
|
864
|
-
message.offset = 1;
|
|
865
|
-
}
|
|
866
|
-
if (message.numExecs > 0) {
|
|
867
|
-
await this._protocol._processMessage(message);
|
|
868
|
-
}
|
|
869
|
-
|
|
870
|
-
// process results
|
|
871
|
-
const returnObj = {};
|
|
872
|
-
statement.bufferRowIndex = 0;
|
|
873
|
-
const bindVars = thinUtil.getBindVars(statement);
|
|
874
|
-
const outBinds = thinUtil.getExecuteManyOutBinds(bindVars, numIters);
|
|
875
|
-
if (outBinds) {
|
|
876
|
-
returnObj.outBinds = outBinds;
|
|
877
|
-
}
|
|
878
|
-
const rowsAffected = !statement.isPlSql ? statement.rowCount : undefined;
|
|
879
|
-
if (rowsAffected) {
|
|
880
|
-
returnObj.rowsAffected = rowsAffected;
|
|
881
|
-
delete statement.rowCount;
|
|
882
|
-
}
|
|
883
|
-
if (options.dmlRowCounts) {
|
|
884
|
-
returnObj.dmlRowCounts = options.dmlRowCounts;
|
|
885
|
-
}
|
|
886
|
-
if (options.batchErrors) {
|
|
887
|
-
returnObj.batchErrors = options.batchErrors;
|
|
924
|
+
async execute(sql, numIters, binds, options, executeManyFlag) {
|
|
925
|
+
const statement = this._prepare(sql, options);
|
|
926
|
+
try {
|
|
927
|
+
return await this._execute(statement, numIters, binds, options,
|
|
928
|
+
executeManyFlag);
|
|
929
|
+
} catch (err) {
|
|
930
|
+
this._returnStatement(statement);
|
|
931
|
+
throw err;
|
|
888
932
|
}
|
|
889
|
-
this._returnStatement(statement);
|
|
890
|
-
|
|
891
|
-
return returnObj;
|
|
892
933
|
}
|
|
893
934
|
|
|
894
935
|
//---------------------------------------------------------------------------
|
|
@@ -1038,6 +1079,12 @@ class ThinConnectionImpl extends ConnectionImpl {
|
|
|
1038
1079
|
return '';
|
|
1039
1080
|
}
|
|
1040
1081
|
|
|
1082
|
+
//---------------------------------------------------------------------------
|
|
1083
|
+
// Returns the Oracle Database instance name associated with the connection.
|
|
1084
|
+
//---------------------------------------------------------------------------
|
|
1085
|
+
getInstanceName() {
|
|
1086
|
+
return this.instanceName;
|
|
1087
|
+
}
|
|
1041
1088
|
}
|
|
1042
1089
|
|
|
1043
1090
|
module.exports = ThinConnectionImpl;
|
package/lib/thin/dbObject.js
CHANGED
|
@@ -367,7 +367,10 @@ class ThinDbObjectImpl extends DbObjectImpl {
|
|
|
367
367
|
case types.DB_TYPE_NCHAR:
|
|
368
368
|
return buf.readStr(constants.CSFRM_NCHAR);
|
|
369
369
|
case types.DB_TYPE_RAW:
|
|
370
|
-
|
|
370
|
+
value = buf.readBytesWithLength();
|
|
371
|
+
if (value !== null)
|
|
372
|
+
value = Buffer.from(value);
|
|
373
|
+
return value;
|
|
371
374
|
case types.DB_TYPE_BINARY_DOUBLE:
|
|
372
375
|
return buf.readBinaryDouble();
|
|
373
376
|
case types.DB_TYPE_BINARY_FLOAT:
|