oracledb 6.9.0 → 7.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.
- package/LICENSE.txt +1 -1
- package/NOTICE.txt +1 -1
- package/README.md +9 -9
- package/build/Release/oracledb-7.0.0-darwin-arm64.node +0 -0
- package/build/Release/oracledb-7.0.0-darwin-arm64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-7.0.0-js-buildinfo.txt +1 -0
- package/build/Release/oracledb-7.0.0-linux-arm64.node +0 -0
- package/build/Release/oracledb-7.0.0-linux-arm64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-7.0.0-linux-x64.node +0 -0
- package/build/Release/oracledb-7.0.0-linux-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-7.0.0-win32-x64.node +0 -0
- package/build/Release/oracledb-7.0.0-win32-x64.node-buildinfo.txt +1 -0
- package/eslint.config.js +39 -0
- package/lib/aqDeqOptions.js +18 -1
- package/lib/aqQueue.js +10 -6
- package/lib/connection.js +418 -39
- package/lib/dbObject.js +25 -4
- package/lib/endUserSecurityContext.js +176 -0
- package/lib/errors.js +99 -8
- package/lib/impl/aqDeqOptions.js +10 -1
- package/lib/impl/connection.js +76 -2
- package/lib/impl/datahandlers/buffer.js +68 -5
- package/lib/impl/datahandlers/oson.js +7 -2
- package/lib/impl/datahandlers/vector.js +25 -5
- package/lib/impl/lob.js +9 -0
- package/lib/impl/parserHelpers.js +443 -0
- package/lib/impl/resultset.js +1 -1
- package/lib/impl/sodaDocument.js +5 -14
- package/lib/lob.js +27 -14
- package/lib/obfuscation.js +97 -0
- package/lib/oracledb.js +163 -49
- package/lib/parser.js +204 -0
- package/lib/pipeline.js +113 -0
- package/lib/pool.js +203 -147
- package/lib/poolStatistics.js +1 -1
- package/lib/resultset.js +42 -21
- package/lib/settings.js +1 -0
- package/lib/sodaCollection.js +12 -8
- package/lib/sodaDatabase.js +35 -8
- package/lib/sodaDocument.js +24 -6
- package/lib/sodaOperation.js +7 -6
- package/lib/thin/aq.js +475 -0
- package/lib/thin/connection.js +518 -54
- package/lib/thin/dbObject.js +7 -1
- package/lib/thin/lob.js +20 -1
- package/lib/thin/pool.js +42 -62
- package/lib/thin/protocol/capabilities.js +21 -4
- package/lib/thin/protocol/constants.js +143 -2
- package/lib/thin/protocol/encryptDecrypt.js +45 -10
- package/lib/thin/protocol/messages/aqArray.js +238 -0
- package/lib/thin/protocol/messages/aqBase.js +305 -0
- package/lib/thin/protocol/messages/aqDeq.js +164 -0
- package/lib/thin/protocol/messages/aqEnq.js +135 -0
- package/lib/thin/protocol/messages/auth.js +18 -28
- package/lib/thin/protocol/messages/base.js +245 -4
- package/lib/thin/protocol/messages/dataType.js +8 -3
- package/lib/thin/protocol/messages/directPathLoadStream.js +377 -0
- package/lib/thin/protocol/messages/directPathOp.js +65 -0
- package/lib/thin/protocol/messages/directPathPrepare.js +158 -0
- package/lib/thin/protocol/messages/endPipeline.js +56 -0
- package/lib/thin/protocol/messages/execute.js +9 -7
- package/lib/thin/protocol/messages/index.js +9 -1
- package/lib/thin/protocol/messages/protocol.js +2 -2
- package/lib/thin/protocol/messages/withData.js +10 -142
- package/lib/thin/protocol/packet.js +120 -28
- package/lib/thin/protocol/protocol.js +110 -25
- package/lib/thin/protocol/utils.js +1 -26
- package/lib/thin/resultSet.js +13 -19
- package/lib/thin/sqlnet/ezConnectResolver.js +2 -2
- package/lib/thin/sqlnet/networkSession.js +63 -41
- package/lib/thin/sqlnet/ntTcp.js +24 -0
- package/lib/thin/sqlnet/nvStrToNvPair.js +50 -25
- package/lib/thin/sqlnet/packet.js +25 -4
- package/lib/thin/sqlnet/paramParser.js +10 -7
- package/lib/thin/statementCache.js +2 -4
- package/lib/traceHandler.js +59 -2
- package/lib/transformer.js +8 -3
- package/lib/types.js +36 -22
- package/lib/util.js +6 -19
- package/lib/version.js +3 -3
- package/package/install.js +5 -5
- package/package/prunebinaries.js +1 -1
- package/package.json +1 -1
- package/plugins/configProviders/awsCommon.js +125 -0
- package/plugins/configProviders/awss3/index.js +138 -0
- package/plugins/configProviders/awssecretsmanager/index.js +147 -0
- package/plugins/configProviders/azure/index.js +7 -5
- package/plugins/token/extensionAzure/index.js +0 -1
- package/plugins/token/extensionOci/index.js +0 -1
- package/build/Release/oracledb-6.9.0-darwin-arm64.node +0 -0
- package/build/Release/oracledb-6.9.0-darwin-arm64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.9.0-darwin-x64.node +0 -0
- package/build/Release/oracledb-6.9.0-darwin-x64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.9.0-js-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.9.0-linux-arm64.node +0 -0
- package/build/Release/oracledb-6.9.0-linux-arm64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.9.0-linux-x64.node +0 -0
- package/build/Release/oracledb-6.9.0-linux-x64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.9.0-win32-x64.node +0 -0
- package/build/Release/oracledb-6.9.0-win32-x64.node-buildinfo.txt +0 -1
package/lib/connection.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright (c) 2016,
|
|
1
|
+
// Copyright (c) 2016, 2026, Oracle and/or its affiliates.
|
|
2
2
|
|
|
3
3
|
//-----------------------------------------------------------------------------
|
|
4
4
|
//
|
|
@@ -44,6 +44,11 @@ const settings = require('./settings.js');
|
|
|
44
44
|
const transformer = require('./transformer.js');
|
|
45
45
|
const types = require('./types.js');
|
|
46
46
|
const oson = require('./impl/datahandlers/oson.js');
|
|
47
|
+
const traceHandler = require('./traceHandler.js');
|
|
48
|
+
const EndUserSecurityContext = require('./endUserSecurityContext.js');
|
|
49
|
+
|
|
50
|
+
const APP_CONTEXT_KEY_MAX_BYTES = 128;
|
|
51
|
+
const APP_CONTEXT_VALUE_MAX_BYTES = 4 * 1000;
|
|
47
52
|
|
|
48
53
|
// global mapping of subscriptions; these cannot be tied to a particular
|
|
49
54
|
// connection or pool since subscriptions can be created with one connection
|
|
@@ -58,7 +63,7 @@ const defaultNumberConverter = (v) => (v === null) ? null : parseFloat(v);
|
|
|
58
63
|
//
|
|
59
64
|
// Determines the converter associated with each DB type and its metadata.
|
|
60
65
|
// This function is called once during metadata construction and the
|
|
61
|
-
// converters are invoked when
|
|
66
|
+
// converters are invoked when retrieving DBObject values.
|
|
62
67
|
//---------------------------------------------------------------------------
|
|
63
68
|
function _determineDbObjTypeConverter(metadata, options) {
|
|
64
69
|
// clear any previous converter functions that may have been
|
|
@@ -290,6 +295,9 @@ class Connection extends EventEmitter {
|
|
|
290
295
|
// function identifying an object type
|
|
291
296
|
if (bindUnit.type !== undefined) {
|
|
292
297
|
if (typeof bindUnit.type === 'string') {
|
|
298
|
+
if (this._impl.pipelineMode) {
|
|
299
|
+
errors.throwErr(errors.ERR_PIPELINE_DBOBJECTS_NOT_SUPPORTED);
|
|
300
|
+
}
|
|
293
301
|
bindInfo.type = types.DB_TYPE_OBJECT;
|
|
294
302
|
bindInfo.typeClass = await this._getDbObjectClassForName(bindUnit.type);
|
|
295
303
|
bindInfo.objType = bindInfo.typeClass._objType;
|
|
@@ -369,6 +377,8 @@ class Connection extends EventEmitter {
|
|
|
369
377
|
}
|
|
370
378
|
if (bindInfo.type === types.DB_TYPE_OBJECT &&
|
|
371
379
|
bindInfo.typeClass === undefined) {
|
|
380
|
+
if (this._impl.pipelineMode)
|
|
381
|
+
errors.throwErr(errors.ERR_PIPELINE_DBOBJECTS_NOT_SUPPORTED);
|
|
372
382
|
bindInfo.typeClass = await this._getDbObjectClass(value._objType);
|
|
373
383
|
bindInfo.objType = bindInfo.typeClass._objType;
|
|
374
384
|
}
|
|
@@ -827,7 +837,13 @@ class Connection extends EventEmitter {
|
|
|
827
837
|
|
|
828
838
|
this._closing = true;
|
|
829
839
|
try {
|
|
830
|
-
|
|
840
|
+
// If connection is part of a pool, notify the pool of its availability
|
|
841
|
+
if (this._pool) {
|
|
842
|
+
await this._pool._release(this._impl, options);
|
|
843
|
+
traceHandler.getTraceInstance()?.onPoolRelease(this._pool);
|
|
844
|
+
} else {
|
|
845
|
+
await this._impl.close(options);
|
|
846
|
+
}
|
|
831
847
|
} finally {
|
|
832
848
|
this._closing = false;
|
|
833
849
|
}
|
|
@@ -839,7 +855,12 @@ class Connection extends EventEmitter {
|
|
|
839
855
|
}
|
|
840
856
|
}
|
|
841
857
|
this._dbObjectClasses.clear();
|
|
842
|
-
|
|
858
|
+
}
|
|
859
|
+
|
|
860
|
+
async _commit() {
|
|
861
|
+
errors.assertArgCount(arguments, 0, 0);
|
|
862
|
+
errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
|
|
863
|
+
await this._impl.commit();
|
|
843
864
|
}
|
|
844
865
|
|
|
845
866
|
//---------------------------------------------------------------------------
|
|
@@ -848,9 +869,7 @@ class Connection extends EventEmitter {
|
|
|
848
869
|
// Commits the current transaction.
|
|
849
870
|
//---------------------------------------------------------------------------
|
|
850
871
|
async commit() {
|
|
851
|
-
|
|
852
|
-
errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
|
|
853
|
-
await this._impl.commit();
|
|
872
|
+
await this._commit.apply(this, arguments);
|
|
854
873
|
}
|
|
855
874
|
|
|
856
875
|
//---------------------------------------------------------------------------
|
|
@@ -938,6 +957,27 @@ class Connection extends EventEmitter {
|
|
|
938
957
|
return decoder.decode();
|
|
939
958
|
}
|
|
940
959
|
|
|
960
|
+
setEndUserSecurityContext(context) {
|
|
961
|
+
errors.assertArgCount(arguments, 1, 1);
|
|
962
|
+
errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
|
|
963
|
+
|
|
964
|
+
if (typeof this.protocol !== 'string' || this.protocol !== 'TCPS') {
|
|
965
|
+
errors.throwErr(errors.ERR_END_USER_SECURITY_CONTEXT_REQUIRES_TCPS);
|
|
966
|
+
}
|
|
967
|
+
|
|
968
|
+
errors.assertParamValue(
|
|
969
|
+
context instanceof EndUserSecurityContext,
|
|
970
|
+
1
|
|
971
|
+
);
|
|
972
|
+
|
|
973
|
+
this._impl.setEndUserSecurityContext(context);
|
|
974
|
+
}
|
|
975
|
+
|
|
976
|
+
clearEndUserSecurityContext() {
|
|
977
|
+
errors.assertArgCount(arguments, 0, 0);
|
|
978
|
+
errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
|
|
979
|
+
this._impl.clearEndUserSecurityContext();
|
|
980
|
+
}
|
|
941
981
|
|
|
942
982
|
//---------------------------------------------------------------------------
|
|
943
983
|
// encode()
|
|
@@ -949,12 +989,7 @@ class Connection extends EventEmitter {
|
|
|
949
989
|
return encoder.encode(transformer.transformJsonValue(value), this._impl._osonMaxFieldNameSize);
|
|
950
990
|
}
|
|
951
991
|
|
|
952
|
-
|
|
953
|
-
// execute()
|
|
954
|
-
//
|
|
955
|
-
// Executes a SQL statement and returns the results.
|
|
956
|
-
//---------------------------------------------------------------------------
|
|
957
|
-
async execute(sql, a2, a3) {
|
|
992
|
+
async _processExecuteArgs(sql, a2, a3) {
|
|
958
993
|
const numIters = 1;
|
|
959
994
|
let binds = [];
|
|
960
995
|
let options = {};
|
|
@@ -989,50 +1024,100 @@ class Connection extends EventEmitter {
|
|
|
989
1024
|
}
|
|
990
1025
|
this._addDefaultsToExecOpts(options);
|
|
991
1026
|
|
|
1027
|
+
return {sql, numIters, binds, options, executeManyFlag: false};
|
|
1028
|
+
}
|
|
1029
|
+
|
|
1030
|
+
async _execute() {
|
|
1031
|
+
|
|
1032
|
+
// process arguments
|
|
1033
|
+
const { sql, numIters, binds, options, executeManyFlag } =
|
|
1034
|
+
await this._processExecuteArgs.apply(this, arguments);
|
|
1035
|
+
|
|
992
1036
|
// perform actual execute
|
|
993
1037
|
let result;
|
|
994
1038
|
try {
|
|
995
1039
|
if (this._impl._callLevelTraceData) {
|
|
996
1040
|
this._impl._callLevelTraceData.statement = sql;
|
|
997
1041
|
}
|
|
998
|
-
result = await this._impl.execute(sql, numIters, binds, options,
|
|
1042
|
+
result = await this._impl.execute(sql, numIters, binds, options,
|
|
1043
|
+
executeManyFlag);
|
|
999
1044
|
} catch (err) {
|
|
1000
1045
|
if (err.errorNum === 1406)
|
|
1001
1046
|
errors.throwErr(errors.ERR_INSUFFICIENT_BUFFER_FOR_BINDS);
|
|
1002
1047
|
throw err;
|
|
1003
1048
|
}
|
|
1004
1049
|
|
|
1005
|
-
|
|
1050
|
+
return await this._transformExecuteResult(result, options);
|
|
1051
|
+
}
|
|
1052
|
+
|
|
1053
|
+
//---------------------------------------------------------------------------
|
|
1054
|
+
// execute()
|
|
1055
|
+
//
|
|
1056
|
+
// Executes a SQL statement and returns the results.
|
|
1057
|
+
//---------------------------------------------------------------------------
|
|
1058
|
+
async execute() {
|
|
1059
|
+
return await this._execute.apply(this, arguments);
|
|
1060
|
+
}
|
|
1061
|
+
|
|
1062
|
+
async _handleFetchForExecuteInPipeline(result, options) {
|
|
1006
1063
|
if (result.warning) {
|
|
1007
1064
|
result.warning = errors.transformErr(result.warning);
|
|
1008
1065
|
}
|
|
1009
1066
|
|
|
1010
|
-
// process queries; if a result set is not desired, fetch all of the rows
|
|
1011
|
-
// from the result set and then destroy the result set
|
|
1012
1067
|
if (result.resultSet !== undefined) {
|
|
1013
|
-
|
|
1014
|
-
|
|
1015
|
-
result.
|
|
1016
|
-
|
|
1017
|
-
|
|
1018
|
-
|
|
1068
|
+
// just close resultSet for pipelineOp.opType 'execute'
|
|
1069
|
+
// To fetch rows, 'fetch*' used instead in pipeline mode
|
|
1070
|
+
await result.resultSet.close();
|
|
1071
|
+
delete result.resultSet;
|
|
1072
|
+
}
|
|
1073
|
+
|
|
1074
|
+
this._processOutBinds(result, options);
|
|
1075
|
+
await this._processImplicitResults(result, options);
|
|
1076
|
+
}
|
|
1077
|
+
|
|
1078
|
+
async _handleFetchInPipeline(result, resultSet, fetchOpPipeline) {
|
|
1079
|
+
let shouldClose = false;
|
|
1080
|
+
try {
|
|
1081
|
+
if (fetchOpPipeline.opType === 'fetchOne') {
|
|
1082
|
+
const row = await resultSet._getRow();
|
|
1083
|
+
result.rows = row ? [row] : [];
|
|
1084
|
+
shouldClose = true;
|
|
1085
|
+
} else if (fetchOpPipeline.opType === 'fetchMany') {
|
|
1086
|
+
if (fetchOpPipeline.numRows === 0)
|
|
1087
|
+
result.rows = [];
|
|
1088
|
+
else {
|
|
1089
|
+
const maxRows = resultSet._impl.maxRows;
|
|
1090
|
+
const rowsToFetch = (maxRows > 0) ?
|
|
1091
|
+
Math.min(fetchOpPipeline.numRows, maxRows) :
|
|
1092
|
+
fetchOpPipeline.numRows;
|
|
1093
|
+
result.rows = await resultSet._doGetRows(rowsToFetch);
|
|
1094
|
+
}
|
|
1095
|
+
shouldClose = true;
|
|
1096
|
+
} else
|
|
1097
|
+
// fallback to fetchAll
|
|
1019
1098
|
result.rows = await resultSet._getAllRows();
|
|
1020
|
-
|
|
1021
|
-
|
|
1099
|
+
} finally {
|
|
1100
|
+
if (shouldClose)
|
|
1101
|
+
await resultSet._close();
|
|
1102
|
+
delete result.resultSet;
|
|
1022
1103
|
}
|
|
1104
|
+
}
|
|
1023
1105
|
|
|
1024
|
-
|
|
1106
|
+
_processOutBinds(result, options) {
|
|
1025
1107
|
if (result.outBinds !== undefined) {
|
|
1026
1108
|
for (const [key, value] of Object.entries(result.outBinds)) {
|
|
1027
1109
|
const val = this._transformOutBind(value, options);
|
|
1028
1110
|
result.outBinds[key] = val;
|
|
1029
1111
|
}
|
|
1030
1112
|
}
|
|
1113
|
+
}
|
|
1031
1114
|
|
|
1032
|
-
|
|
1033
|
-
// array size fixed, or, if a result set is not requested, that all rows
|
|
1034
|
-
// are fetched
|
|
1115
|
+
async _processImplicitResults(result, options, fetchOpPipeline) {
|
|
1035
1116
|
if (result.implicitResults) {
|
|
1117
|
+
if (fetchOpPipeline) {
|
|
1118
|
+
delete result.implicitResults;
|
|
1119
|
+
return;
|
|
1120
|
+
}
|
|
1036
1121
|
for (const [key, impl] of Object.entries(result.implicitResults)) {
|
|
1037
1122
|
const resultSet = new ResultSet();
|
|
1038
1123
|
resultSet._setup(this, impl);
|
|
@@ -1043,16 +1128,47 @@ class Connection extends EventEmitter {
|
|
|
1043
1128
|
}
|
|
1044
1129
|
}
|
|
1045
1130
|
}
|
|
1131
|
+
}
|
|
1132
|
+
|
|
1133
|
+
async _transformExecuteResult(result, options, fetchOpPipeline) {
|
|
1134
|
+
// convert ORA errors to NJS
|
|
1135
|
+
if (result.warning) {
|
|
1136
|
+
result.warning = errors.transformErr(result.warning);
|
|
1137
|
+
}
|
|
1138
|
+
|
|
1139
|
+
// process queries; if a result set is not desired, fetch all of the rows
|
|
1140
|
+
// from the result set and then destroy the result set
|
|
1141
|
+
if (result.resultSet !== undefined) {
|
|
1142
|
+
const resultSet = new ResultSet();
|
|
1143
|
+
resultSet._setup(this, result.resultSet);
|
|
1144
|
+
result.metaData = resultSet._impl.metaData;
|
|
1145
|
+
if (!fetchOpPipeline) {
|
|
1146
|
+
if (options.resultSet) {
|
|
1147
|
+
result.resultSet = resultSet;
|
|
1148
|
+
} else {
|
|
1149
|
+
// for fetchAll, _getAllRows() get rows from buffered rows and
|
|
1150
|
+
// then perform as many round trips as are required to
|
|
1151
|
+
// complete the fetch
|
|
1152
|
+
result.rows = await resultSet._getAllRows();
|
|
1153
|
+
delete result.resultSet;
|
|
1154
|
+
}
|
|
1155
|
+
} else {
|
|
1156
|
+
await this._handleFetchInPipeline(result, resultSet, fetchOpPipeline);
|
|
1157
|
+
}
|
|
1158
|
+
}
|
|
1159
|
+
|
|
1160
|
+
// process output binds
|
|
1161
|
+
this._processOutBinds(result, options);
|
|
1162
|
+
|
|
1163
|
+
// process implicit results; ensure all implicit results have their fetch
|
|
1164
|
+
// array size fixed, or, if a result set is not requested, that all rows
|
|
1165
|
+
// are fetched
|
|
1166
|
+
await this._processImplicitResults(result, options, fetchOpPipeline);
|
|
1046
1167
|
|
|
1047
1168
|
return (result);
|
|
1048
1169
|
}
|
|
1049
1170
|
|
|
1050
|
-
|
|
1051
|
-
// executeMany()
|
|
1052
|
-
//
|
|
1053
|
-
// Executes a SQL statement multiple times and returns the results.
|
|
1054
|
-
//---------------------------------------------------------------------------
|
|
1055
|
-
async executeMany(sql, bindsOrNumIters, a3) {
|
|
1171
|
+
async _processExecuteManyArgs(sql, bindsOrNumIters, userOptions) {
|
|
1056
1172
|
let options = {};
|
|
1057
1173
|
let binds = [];
|
|
1058
1174
|
let numIters;
|
|
@@ -1060,7 +1176,7 @@ class Connection extends EventEmitter {
|
|
|
1060
1176
|
errors.assertArgCount(arguments, 2, 3);
|
|
1061
1177
|
errors.assertParamValue(typeof sql === 'string', 1);
|
|
1062
1178
|
if (arguments.length == 3) {
|
|
1063
|
-
options = this._verifyExecOpts(
|
|
1179
|
+
options = this._verifyExecOpts(userOptions, true);
|
|
1064
1180
|
}
|
|
1065
1181
|
this._addDefaultsToExecOpts(options);
|
|
1066
1182
|
if (typeof bindsOrNumIters === 'number') {
|
|
@@ -1079,9 +1195,24 @@ class Connection extends EventEmitter {
|
|
|
1079
1195
|
}
|
|
1080
1196
|
errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
|
|
1081
1197
|
|
|
1082
|
-
|
|
1083
|
-
|
|
1198
|
+
if (this._impl._callLevelTraceData) {
|
|
1199
|
+
this._impl._callLevelTraceData.statement = sql;
|
|
1200
|
+
}
|
|
1201
|
+
|
|
1202
|
+
return {sql, numIters, binds, options, executeManyFlag: true};
|
|
1203
|
+
}
|
|
1204
|
+
|
|
1205
|
+
async _executeMany() {
|
|
1206
|
+
const { sql, numIters, binds, options, executeManyFlag }
|
|
1207
|
+
= await this._processExecuteManyArgs.apply(this, arguments);
|
|
1208
|
+
|
|
1209
|
+
const result = await this._impl.execute(sql, numIters, binds,
|
|
1210
|
+
options, executeManyFlag);
|
|
1084
1211
|
|
|
1212
|
+
return this._transformExecuteManyResult(result, options);
|
|
1213
|
+
}
|
|
1214
|
+
|
|
1215
|
+
_transformExecuteManyResult(result, options) {
|
|
1085
1216
|
// convert ORA warnings to NJS
|
|
1086
1217
|
if (result.warning) {
|
|
1087
1218
|
result.warning = errors.transformErr(result.warning);
|
|
@@ -1100,6 +1231,15 @@ class Connection extends EventEmitter {
|
|
|
1100
1231
|
return result;
|
|
1101
1232
|
}
|
|
1102
1233
|
|
|
1234
|
+
//---------------------------------------------------------------------------
|
|
1235
|
+
// executeMany()
|
|
1236
|
+
//
|
|
1237
|
+
// Executes a SQL statement multiple times and returns the results.
|
|
1238
|
+
//---------------------------------------------------------------------------
|
|
1239
|
+
async executeMany() {
|
|
1240
|
+
return await this._executeMany.apply(this, arguments);
|
|
1241
|
+
}
|
|
1242
|
+
|
|
1103
1243
|
//---------------------------------------------------------------------------
|
|
1104
1244
|
// externalName
|
|
1105
1245
|
//
|
|
@@ -1135,6 +1275,23 @@ class Connection extends EventEmitter {
|
|
|
1135
1275
|
return this._impl && this._impl.getDbName();
|
|
1136
1276
|
}
|
|
1137
1277
|
|
|
1278
|
+
//---------------------------------------------------------------------------
|
|
1279
|
+
// pdbName (READONLY)
|
|
1280
|
+
//
|
|
1281
|
+
// Property for identifying the container associated with connection.
|
|
1282
|
+
//---------------------------------------------------------------------------
|
|
1283
|
+
get pdbName() {
|
|
1284
|
+
return this._impl && this._impl.getPdbName();
|
|
1285
|
+
}
|
|
1286
|
+
|
|
1287
|
+
//---------------------------------------------------------------------------
|
|
1288
|
+
// dbUniqueName (READONLY)
|
|
1289
|
+
//
|
|
1290
|
+
// Property for identifying the DB_UNIQUE_NAME of the Oracle Database.
|
|
1291
|
+
//---------------------------------------------------------------------------
|
|
1292
|
+
get dbUniqueName() {
|
|
1293
|
+
return this._impl && this._impl.getDbUniqueName();
|
|
1294
|
+
}
|
|
1138
1295
|
//---------------------------------------------------------------------------
|
|
1139
1296
|
// hostName (READONLY)
|
|
1140
1297
|
//
|
|
@@ -1457,7 +1614,7 @@ class Connection extends EventEmitter {
|
|
|
1457
1614
|
//---------------------------------------------------------------------------
|
|
1458
1615
|
// resumeSessionlessTransaction()
|
|
1459
1616
|
//
|
|
1460
|
-
// Resume an existing
|
|
1617
|
+
// Resume an existing sessionless transaction using given transactionId
|
|
1461
1618
|
//---------------------------------------------------------------------------
|
|
1462
1619
|
async resumeSessionlessTransaction(transactionId, options = {}) {
|
|
1463
1620
|
errors.assertArgCount(arguments, 1, 2);
|
|
@@ -1777,6 +1934,157 @@ class Connection extends EventEmitter {
|
|
|
1777
1934
|
await this._impl.tpcRollback(normalizedXid);
|
|
1778
1935
|
}
|
|
1779
1936
|
|
|
1937
|
+
//---------------------------------------------------------------------------
|
|
1938
|
+
// directPathLoad()
|
|
1939
|
+
//
|
|
1940
|
+
// Performs a direct path load into the specified table.
|
|
1941
|
+
//---------------------------------------------------------------------------
|
|
1942
|
+
async directPathLoad(schema, table, columns, data) {
|
|
1943
|
+
errors.assertArgCount(arguments, 4, 5);
|
|
1944
|
+
errors.assertParamValue(typeof schema === 'string', 1);
|
|
1945
|
+
errors.assertParamValue(typeof table === 'string', 2);
|
|
1946
|
+
errors.assertParamValue(Array.isArray(columns) && columns.length, 3);
|
|
1947
|
+
if (!Array.isArray(data) || !data.every(Array.isArray))
|
|
1948
|
+
errors.throwErr(errors.ERR_DPL_INVALID_ROW_DATA);
|
|
1949
|
+
errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
|
|
1950
|
+
return await this._impl.directPathLoad(schema, table, columns, data);
|
|
1951
|
+
}
|
|
1952
|
+
|
|
1953
|
+
_createFetchTypeHandler(fetchLobs) {
|
|
1954
|
+
if (fetchLobs) {
|
|
1955
|
+
// Returning undefined → default behavior → LOB locators
|
|
1956
|
+
return undefined;
|
|
1957
|
+
}
|
|
1958
|
+
// Auto-fetch LOBs
|
|
1959
|
+
return (metadata) => {
|
|
1960
|
+
switch (metadata.dbType) {
|
|
1961
|
+
case types.DB_TYPE_CLOB:
|
|
1962
|
+
case types.DB_TYPE_NCLOB:
|
|
1963
|
+
return { type: types.DB_TYPE_VARCHAR };
|
|
1964
|
+
|
|
1965
|
+
case types.DB_TYPE_BLOB:
|
|
1966
|
+
return { type: types.DB_TYPE_RAW };
|
|
1967
|
+
|
|
1968
|
+
default:
|
|
1969
|
+
return undefined;
|
|
1970
|
+
}
|
|
1971
|
+
};
|
|
1972
|
+
}
|
|
1973
|
+
|
|
1974
|
+
async _runPipelineOpWithoutPipelining(resultImpl) {
|
|
1975
|
+
const op = resultImpl.op;
|
|
1976
|
+
const opType = op.opType;
|
|
1977
|
+
let res = {};
|
|
1978
|
+
if (opType === 'commit') {
|
|
1979
|
+
res = await this._commit();
|
|
1980
|
+
} else if (opType === 'execute') {
|
|
1981
|
+
res = await this._execute(op.statement, op.parameters, op.options);
|
|
1982
|
+
if (res.rows) {
|
|
1983
|
+
res.rows = undefined;
|
|
1984
|
+
}
|
|
1985
|
+
} else if (opType === 'executeMany')
|
|
1986
|
+
res = await this._executeMany(op.statement, op.parameters, op.options);
|
|
1987
|
+
else if (['fetchOne', 'fetchMany', 'fetchAll'].includes(opType)) {
|
|
1988
|
+
|
|
1989
|
+
// Force a ResultSet and then fetch rows according to the requested
|
|
1990
|
+
// fetch variant in non-pipeline flow.
|
|
1991
|
+
op.options.resultSet = true;
|
|
1992
|
+
op.options.fetchTypeHandler = this._createFetchTypeHandler(op.fetchLobs);
|
|
1993
|
+
let shouldClose = false;
|
|
1994
|
+
try {
|
|
1995
|
+
res = await this._execute(op.statement, op.parameters, op.options);
|
|
1996
|
+
if (opType === 'fetchOne') {
|
|
1997
|
+
const row = await res.resultSet._getRow();
|
|
1998
|
+
res.rows = row ? [row] : [];
|
|
1999
|
+
shouldClose = true;
|
|
2000
|
+
} else if (opType === 'fetchMany') {
|
|
2001
|
+
if (op.numRows === 0) {
|
|
2002
|
+
res.rows = [];
|
|
2003
|
+
} else {
|
|
2004
|
+
const maxRows = res.resultSet._impl.maxRows;
|
|
2005
|
+
const rowsToFetch = (maxRows > 0) ?
|
|
2006
|
+
Math.min(op.numRows, maxRows) :
|
|
2007
|
+
op.numRows;
|
|
2008
|
+
res.rows = await res.resultSet._doGetRows(rowsToFetch);
|
|
2009
|
+
}
|
|
2010
|
+
shouldClose = true;
|
|
2011
|
+
} else if (opType === 'fetchAll') {
|
|
2012
|
+
res.rows = await res.resultSet._getAllRows();
|
|
2013
|
+
}
|
|
2014
|
+
} finally {
|
|
2015
|
+
if (shouldClose)
|
|
2016
|
+
await res.resultSet._close();
|
|
2017
|
+
delete res.resultSet;
|
|
2018
|
+
}
|
|
2019
|
+
} else
|
|
2020
|
+
errors.throwErr(errors.ERR_PIPELINE_OPERATION_NOT_SUPPORTED, opType);
|
|
2021
|
+
resultImpl.result = res;
|
|
2022
|
+
}
|
|
2023
|
+
|
|
2024
|
+
async _runPipelineWithoutPipelining(resultsImpl, continueOnError) {
|
|
2025
|
+
const savedCallTimeout = this.callTimeout;
|
|
2026
|
+
try {
|
|
2027
|
+
|
|
2028
|
+
// For consistency with protocol-level pipelining, do not enforce
|
|
2029
|
+
// call timeout while executing the fallback non-pipelined flow.
|
|
2030
|
+
if (savedCallTimeout > 0)
|
|
2031
|
+
this.callTimeout = 0;
|
|
2032
|
+
for (const resultImpl of resultsImpl) {
|
|
2033
|
+
try {
|
|
2034
|
+
await this._runPipelineOpWithoutPipelining(resultImpl);
|
|
2035
|
+
} catch (err) {
|
|
2036
|
+
if (!continueOnError)
|
|
2037
|
+
throw (err);
|
|
2038
|
+
resultImpl.error = err;
|
|
2039
|
+
}
|
|
2040
|
+
}
|
|
2041
|
+
return this._buildPipelineResults(resultsImpl);
|
|
2042
|
+
} finally {
|
|
2043
|
+
if (savedCallTimeout > 0)
|
|
2044
|
+
this.callTimeout = savedCallTimeout;
|
|
2045
|
+
}
|
|
2046
|
+
}
|
|
2047
|
+
|
|
2048
|
+
_buildPipelineResults(resultsImpl) {
|
|
2049
|
+
const results = [];
|
|
2050
|
+
for (let i = 0; i < resultsImpl.length; i++) {
|
|
2051
|
+
results[i] = resultsImpl[i].result;
|
|
2052
|
+
if (resultsImpl[i].error) {
|
|
2053
|
+
if (!results[i]) results[i] = {};
|
|
2054
|
+
results[i].error = resultsImpl[i].error;
|
|
2055
|
+
}
|
|
2056
|
+
}
|
|
2057
|
+
return results;
|
|
2058
|
+
}
|
|
2059
|
+
|
|
2060
|
+
//---------------------------------------------------------------------------
|
|
2061
|
+
// runPipeline()
|
|
2062
|
+
//
|
|
2063
|
+
// It runs the list of operations and returns an result array.
|
|
2064
|
+
//---------------------------------------------------------------------------
|
|
2065
|
+
async runPipeline(pipeline, continueOnError = false) {
|
|
2066
|
+
errors.assertArgCount(arguments, 1, 2);
|
|
2067
|
+
errors.assertParamValue(typeof continueOnError === 'boolean', 2);
|
|
2068
|
+
errors.assertParamValue(pipeline?.constructor?.name === 'Pipeline', 1);
|
|
2069
|
+
// validate connection state
|
|
2070
|
+
errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
|
|
2071
|
+
const results = [];
|
|
2072
|
+
for (const op of pipeline.operations) {
|
|
2073
|
+
// sample result (will be filled with corresponding operation result,
|
|
2074
|
+
// like rows, rowsAffected, metadata, error)
|
|
2075
|
+
results.push({op, result: {}});
|
|
2076
|
+
}
|
|
2077
|
+
|
|
2078
|
+
// Use protocol-level pipelining only when the server supports it and
|
|
2079
|
+
// when there is more than one operation to benefit from batching.
|
|
2080
|
+
if (this._impl.supportsPipelining() && pipeline.operations.length > 1)
|
|
2081
|
+
return await this._impl.runPipelineWithPipelining(this, results,
|
|
2082
|
+
continueOnError);
|
|
2083
|
+
else
|
|
2084
|
+
return await this._runPipelineWithoutPipelining(results,
|
|
2085
|
+
continueOnError);
|
|
2086
|
+
}
|
|
2087
|
+
|
|
1780
2088
|
//---------------------------------------------------------------------------
|
|
1781
2089
|
// unsubscribe()
|
|
1782
2090
|
//
|
|
@@ -1796,6 +2104,75 @@ class Connection extends EventEmitter {
|
|
|
1796
2104
|
}, 0);
|
|
1797
2105
|
}
|
|
1798
2106
|
|
|
2107
|
+
//---------------------------------------------------------------------------
|
|
2108
|
+
// appContext()
|
|
2109
|
+
//
|
|
2110
|
+
// Add Application Context, keyValues identified by name, namespaceName.
|
|
2111
|
+
//---------------------------------------------------------------------------
|
|
2112
|
+
appContext(namespaceName, keyValues) {
|
|
2113
|
+
errors.assertArgCount([namespaceName, keyValues], 2, 2);
|
|
2114
|
+
errors.assertParamValue(typeof namespaceName === 'string', 1);
|
|
2115
|
+
if (namespaceName.length === 0) {
|
|
2116
|
+
errors.throwErr(errors.ERR_APP_CONTEXT_EMPTY_NAMESPACE);
|
|
2117
|
+
}
|
|
2118
|
+
|
|
2119
|
+
// Passing null/undefined/[] currently leaves existing entries intact in
|
|
2120
|
+
// thick mode and triggers an error in thin mode.
|
|
2121
|
+
// It does not clear the context; use clearAppContext() explicitly
|
|
2122
|
+
// when you need to remove keys.
|
|
2123
|
+
if (keyValues === null || keyValues === undefined) {
|
|
2124
|
+
keyValues = [];
|
|
2125
|
+
}
|
|
2126
|
+
errors.assertParamValue(Array.isArray(keyValues), 2);
|
|
2127
|
+
|
|
2128
|
+
for (const entry of keyValues) {
|
|
2129
|
+
errors.assertParamValue(nodbUtil.isObject(entry) && !Array.isArray(entry), 2);
|
|
2130
|
+
const entries = Object.entries(entry);
|
|
2131
|
+
const [entryKey, entryValue] = entries[0] ?? [];
|
|
2132
|
+
|
|
2133
|
+
errors.assert(entries.length === 1 &&
|
|
2134
|
+
typeof entryKey === 'string' &&
|
|
2135
|
+
typeof entryValue === 'string',
|
|
2136
|
+
errors.ERR_APP_CONTEXT_INVALID_KEY_VALUE,
|
|
2137
|
+
typeof entryKey,
|
|
2138
|
+
typeof entryValue);
|
|
2139
|
+
|
|
2140
|
+
const keyLength = Buffer.byteLength(entryKey);
|
|
2141
|
+
errors.assert(keyLength <= APP_CONTEXT_KEY_MAX_BYTES,
|
|
2142
|
+
errors.ERR_APP_CONTEXT_KEY_TOO_LONG,
|
|
2143
|
+
keyLength,
|
|
2144
|
+
APP_CONTEXT_KEY_MAX_BYTES);
|
|
2145
|
+
|
|
2146
|
+
const valueLength = Buffer.byteLength(entryValue);
|
|
2147
|
+
errors.assert(valueLength <= APP_CONTEXT_VALUE_MAX_BYTES,
|
|
2148
|
+
errors.ERR_APP_CONTEXT_VALUE_TOO_LONG,
|
|
2149
|
+
valueLength,
|
|
2150
|
+
APP_CONTEXT_VALUE_MAX_BYTES);
|
|
2151
|
+
}
|
|
2152
|
+
|
|
2153
|
+
this._impl.appContext(namespaceName, keyValues);
|
|
2154
|
+
}
|
|
2155
|
+
|
|
2156
|
+
//---------------------------------------------------------------------------
|
|
2157
|
+
// clearAppContext()
|
|
2158
|
+
//
|
|
2159
|
+
// Clears the Application Context, keyValues identified by name.
|
|
2160
|
+
//---------------------------------------------------------------------------
|
|
2161
|
+
clearAppContext(namespaceName) {
|
|
2162
|
+
errors.assertArgCount([namespaceName], 1, 1);
|
|
2163
|
+
errors.assertParamValue(typeof namespaceName === 'string', 1);
|
|
2164
|
+
this._impl.clearAppContext(namespaceName);
|
|
2165
|
+
}
|
|
2166
|
+
|
|
2167
|
+
//---------------------------------------------------------------------------
|
|
2168
|
+
// Symbol.asyncDispose
|
|
2169
|
+
//
|
|
2170
|
+
// Implement explicit resource management.
|
|
2171
|
+
//---------------------------------------------------------------------------
|
|
2172
|
+
async [Symbol.asyncDispose]() {
|
|
2173
|
+
await this.close();
|
|
2174
|
+
}
|
|
2175
|
+
|
|
1799
2176
|
}
|
|
1800
2177
|
|
|
1801
2178
|
// adjust functions to support the old callback style and to serialize calls
|
|
@@ -1811,12 +2188,14 @@ nodbUtil.wrapFns(Connection.prototype,
|
|
|
1811
2188
|
"close",
|
|
1812
2189
|
"commit",
|
|
1813
2190
|
"createLob",
|
|
2191
|
+
"directPathLoad",
|
|
1814
2192
|
"execute",
|
|
1815
2193
|
"executeMany",
|
|
1816
2194
|
"getDbObjectClass",
|
|
1817
2195
|
"getQueue",
|
|
1818
2196
|
"getStatementInfo",
|
|
1819
2197
|
"ping",
|
|
2198
|
+
"runPipeline",
|
|
1820
2199
|
"resumeSessionlessTransaction",
|
|
1821
2200
|
"rollback",
|
|
1822
2201
|
"shutdown",
|