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
|
@@ -0,0 +1,377 @@
|
|
|
1
|
+
// Copyright (c) 2025, 2026, Oracle and/or its affiliates.
|
|
2
|
+
|
|
3
|
+
//-----------------------------------------------------------------------------
|
|
4
|
+
//
|
|
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:
|
|
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.
|
|
15
|
+
// You may obtain a copy of the License at
|
|
16
|
+
//
|
|
17
|
+
// https://www.apache.org/licenses/LICENSE-2.0
|
|
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.
|
|
22
|
+
// See the License for the specific language governing permissions and
|
|
23
|
+
// limitations under the License.
|
|
24
|
+
//
|
|
25
|
+
//-----------------------------------------------------------------------------
|
|
26
|
+
|
|
27
|
+
"use strict";
|
|
28
|
+
|
|
29
|
+
const Message = require("./base.js");
|
|
30
|
+
const constants = require("../constants.js");
|
|
31
|
+
const errors = require("../../../errors.js");
|
|
32
|
+
const { Buffer } = require("buffer");
|
|
33
|
+
const types = require("../../../types.js");
|
|
34
|
+
const { BaseBuffer } = require("../../../impl/datahandlers/buffer.js");
|
|
35
|
+
const vector = require("../../../impl/datahandlers/vector.js");
|
|
36
|
+
const oson = require("../../../impl/datahandlers/oson.js");
|
|
37
|
+
const transformer = require("../../../transformer.js");
|
|
38
|
+
|
|
39
|
+
class DirectPathPiece {
|
|
40
|
+
constructor() {
|
|
41
|
+
this.isFast = false;
|
|
42
|
+
this.isFirst = false;
|
|
43
|
+
this.isLast = false;
|
|
44
|
+
this.isSplitWithPrev = false;
|
|
45
|
+
this.isSplitWithNext = false;
|
|
46
|
+
this.flags = 0;
|
|
47
|
+
this.numSegments = 0;
|
|
48
|
+
this.length = 0;
|
|
49
|
+
this.data = null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
finalize(buf) {
|
|
53
|
+
this.length = buf.pos;
|
|
54
|
+
this.data = Buffer.from(buf.buf.slice(0, buf.pos));
|
|
55
|
+
buf.pos = 0;
|
|
56
|
+
if (this.isFirst) {
|
|
57
|
+
this.flags |= constants.TNS_DPLS_ROW_HEADER_FIRST;
|
|
58
|
+
} else if (this.isSplitWithPrev) {
|
|
59
|
+
this.flags |= constants.TNS_DPLS_ROW_HEADER_SPLIT_WITH_PREV;
|
|
60
|
+
}
|
|
61
|
+
if (this.isLast) {
|
|
62
|
+
this.flags |= constants.TNS_DPLS_ROW_HEADER_LAST;
|
|
63
|
+
} else if (this.isSplitWithNext) {
|
|
64
|
+
this.flags |= constants.TNS_DPLS_ROW_HEADER_SPLIT_WITH_NEXT;
|
|
65
|
+
}
|
|
66
|
+
if (this.isFastRow()) {
|
|
67
|
+
this.flags |= constants.TNS_DPLS_ROW_HEADER_FAST_ROW;
|
|
68
|
+
this.flags |= constants.TNS_DPLS_ROW_HEADER_FAST_PIECE;
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
headerLength() {
|
|
73
|
+
let length = 2;
|
|
74
|
+
if (this.isFastRow()) {
|
|
75
|
+
length += 2;
|
|
76
|
+
}
|
|
77
|
+
return length;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
isFastRow() {
|
|
81
|
+
return this.isFirst && this.isLast && this.isFast;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
writeToMessage(buf) {
|
|
85
|
+
buf.writeUInt8(this.flags);
|
|
86
|
+
if (this.isFastRow()) {
|
|
87
|
+
buf.writeUInt16BE(this.length + this.headerLength());
|
|
88
|
+
}
|
|
89
|
+
buf.writeUInt8(this.numSegments);
|
|
90
|
+
buf.writeBytes(this.data);
|
|
91
|
+
}
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
class PieceBuffer extends BaseBuffer {
|
|
95
|
+
constructor(connection) {
|
|
96
|
+
super(Buffer.alloc(constants.TNS_DPLS_MAX_PIECE_SIZE));
|
|
97
|
+
this.connection = connection;
|
|
98
|
+
this.currentPiece = null;
|
|
99
|
+
this.totalPieceLength = 0;
|
|
100
|
+
this.pieces = [];
|
|
101
|
+
this._encodingTempBuf = new BaseBuffer(
|
|
102
|
+
Buffer.alloc(constants.TNS_DPLS_MAX_BUFFER_SIZE_FACTOR)
|
|
103
|
+
);
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
_writeMoreData() {
|
|
107
|
+
this._finalizePiece();
|
|
108
|
+
this.currentPiece = new DirectPathPiece();
|
|
109
|
+
}
|
|
110
|
+
|
|
111
|
+
_finalizePiece() {
|
|
112
|
+
this.currentPiece.finalize(this);
|
|
113
|
+
this.pieces.push(this.currentPiece);
|
|
114
|
+
const newLength =
|
|
115
|
+
this.totalPieceLength +
|
|
116
|
+
this.currentPiece.length +
|
|
117
|
+
this.currentPiece.headerLength();
|
|
118
|
+
if (newLength > constants.TNS_DPLS_MAX_MESSAGE_SIZE)
|
|
119
|
+
errors.throwErr(errors.ERR_DPL_TOO_MUCH_DATA);
|
|
120
|
+
this.totalPieceLength = newLength;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
// Overloads the already existing function in BaseBuffer for DPL specs
|
|
124
|
+
// This also handles writing length of the encoding done in addColumnValue().
|
|
125
|
+
_writeRawBytesAndLength(value, numBytes) {
|
|
126
|
+
let bytesLeft = this.maxSize - this.pos;
|
|
127
|
+
if (numBytes <= constants.TNS_DPLS_MAX_SHORT_LENGTH) {
|
|
128
|
+
if (numBytes + 1 > bytesLeft) {
|
|
129
|
+
this._finalizePiece();
|
|
130
|
+
this.currentPiece = new DirectPathPiece();
|
|
131
|
+
}
|
|
132
|
+
this.writeUInt8(numBytes);
|
|
133
|
+
if (numBytes > 0) {
|
|
134
|
+
this.writeBytes(value);
|
|
135
|
+
}
|
|
136
|
+
this.currentPiece.numSegments += 1;
|
|
137
|
+
} else {
|
|
138
|
+
let startPos = 0;
|
|
139
|
+
while (numBytes + 3 > bytesLeft) {
|
|
140
|
+
const bytesToWrite = bytesLeft - 3;
|
|
141
|
+
this.writeUInt8(constants.TNS_LONG_LENGTH_INDICATOR);
|
|
142
|
+
this.writeUInt16BE(bytesToWrite);
|
|
143
|
+
this.writeBytes(value.subarray(startPos, startPos + bytesToWrite));
|
|
144
|
+
startPos += bytesToWrite;
|
|
145
|
+
numBytes -= bytesToWrite;
|
|
146
|
+
bytesLeft = this.maxSize;
|
|
147
|
+
this.currentPiece.isSplitWithNext = true;
|
|
148
|
+
this.currentPiece.numSegments += 1;
|
|
149
|
+
this._finalizePiece();
|
|
150
|
+
this.currentPiece = new DirectPathPiece();
|
|
151
|
+
this.currentPiece.isSplitWithPrev = numBytes > 0;
|
|
152
|
+
}
|
|
153
|
+
if (numBytes > 0) {
|
|
154
|
+
this.currentPiece.numSegments += 1;
|
|
155
|
+
this.writeUInt8(constants.TNS_LONG_LENGTH_INDICATOR);
|
|
156
|
+
this.writeUInt16BE(numBytes);
|
|
157
|
+
this.writeBytes(value.subarray(startPos));
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
addColumnValue(metadata, value, caps) {
|
|
163
|
+
if (this.currentPiece.numSegments === 255) {
|
|
164
|
+
this._finalizePiece();
|
|
165
|
+
this.currentPiece = new DirectPathPiece();
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
if (!metadata.type.isFast) {
|
|
169
|
+
this.currentPiece.isFast = false;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
if (value === null) {
|
|
173
|
+
if (!metadata.fetchInfo.nullable)
|
|
174
|
+
errors.throwErr(
|
|
175
|
+
errors.ERR_NULLS_NOT_ALLOWED,
|
|
176
|
+
metadata.fetchInfo.dbColumnName,
|
|
177
|
+
metadata.rowNum
|
|
178
|
+
);
|
|
179
|
+
this.writeUInt8(constants.TNS_NULL_LENGTH_INDICATOR);
|
|
180
|
+
this.currentPiece.numSegments += 1;
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
// Reset the temporary encoding buffer for each column, as it's reused
|
|
185
|
+
this._encodingTempBuf.pos = 0;
|
|
186
|
+
|
|
187
|
+
const oraType = metadata.type;
|
|
188
|
+
let columnDataBuffer;
|
|
189
|
+
|
|
190
|
+
value = transformer.transformValueIn(
|
|
191
|
+
{
|
|
192
|
+
type: oraType,
|
|
193
|
+
maxSize: metadata.maxSize,
|
|
194
|
+
checkSize: true,
|
|
195
|
+
},
|
|
196
|
+
value,
|
|
197
|
+
{
|
|
198
|
+
allowArray: false,
|
|
199
|
+
pos: metadata.rowNum + 1,
|
|
200
|
+
}
|
|
201
|
+
);
|
|
202
|
+
|
|
203
|
+
// TODO use oraTypeNum similar to python for simple int check.
|
|
204
|
+
// Writing only the encoding (data bytes) on buffers for column values
|
|
205
|
+
if (
|
|
206
|
+
[
|
|
207
|
+
types.DB_TYPE_CHAR,
|
|
208
|
+
types.DB_TYPE_VARCHAR,
|
|
209
|
+
types.DB_TYPE_NCHAR,
|
|
210
|
+
types.DB_TYPE_NVARCHAR,
|
|
211
|
+
types.DB_TYPE_LONG,
|
|
212
|
+
types.DB_TYPE_LONG_NVARCHAR,
|
|
213
|
+
].includes(oraType)
|
|
214
|
+
) {
|
|
215
|
+
// Encode the data bytes directly after checking charset for strings
|
|
216
|
+
if (oraType._csfrm === constants.CSFRM_NCHAR) {
|
|
217
|
+
caps.checkNCharsetId();
|
|
218
|
+
columnDataBuffer = Buffer.from(
|
|
219
|
+
value,
|
|
220
|
+
constants.TNS_ENCODING_UTF16
|
|
221
|
+
).swap16();
|
|
222
|
+
} else {
|
|
223
|
+
caps.checkCharsetId();
|
|
224
|
+
columnDataBuffer = Buffer.from(value);
|
|
225
|
+
}
|
|
226
|
+
} else if (
|
|
227
|
+
[
|
|
228
|
+
types.DB_TYPE_RAW,
|
|
229
|
+
types.DB_TYPE_LONG_RAW
|
|
230
|
+
].includes(oraType)
|
|
231
|
+
) {
|
|
232
|
+
// Encode the data bytes directly for raw/long types
|
|
233
|
+
columnDataBuffer = Buffer.from(value);
|
|
234
|
+
// Encode the data bytes into a temporary buffer for Oracle types
|
|
235
|
+
} else if (oraType === types.DB_TYPE_NUMBER) {
|
|
236
|
+
this._encodingTempBuf.writeOracleNumber(value.toString(), false);
|
|
237
|
+
} else if (oraType === types.DB_TYPE_BINARY_DOUBLE) {
|
|
238
|
+
this._encodingTempBuf.writeBinaryDouble(value);
|
|
239
|
+
} else if (oraType === types.DB_TYPE_BINARY_FLOAT) {
|
|
240
|
+
this._encodingTempBuf.writeBinaryFloat(value);
|
|
241
|
+
} else if (
|
|
242
|
+
[
|
|
243
|
+
types.DB_TYPE_DATE,
|
|
244
|
+
types.DB_TYPE_TIMESTAMP,
|
|
245
|
+
types.DB_TYPE_TIMESTAMP_LTZ,
|
|
246
|
+
types.DB_TYPE_TIMESTAMP_TZ,
|
|
247
|
+
].includes(oraType)
|
|
248
|
+
) {
|
|
249
|
+
this._encodingTempBuf.writeOracleDate(value, oraType, false);
|
|
250
|
+
} else if (oraType === types.DB_TYPE_INTERVAL_DS) {
|
|
251
|
+
this._encodingTempBuf.writeOracleIntervalDS(value, false);
|
|
252
|
+
} else if (oraType === types.DB_TYPE_INTERVAL_YM) {
|
|
253
|
+
this._encodingTempBuf.writeOracleIntervalYM(value, false);
|
|
254
|
+
} else if (oraType === types.DB_TYPE_BOOLEAN) {
|
|
255
|
+
// Needs clarity as normal boolean encoding causes corruption
|
|
256
|
+
if (value) {
|
|
257
|
+
this._encodingTempBuf.writeUInt8(0x01);
|
|
258
|
+
} else {
|
|
259
|
+
this._encodingTempBuf.writeUInt8(0x00);
|
|
260
|
+
}
|
|
261
|
+
} else if (oraType === types.DB_TYPE_JSON) {
|
|
262
|
+
const encoder = new oson.OsonEncoder();
|
|
263
|
+
columnDataBuffer = encoder.encode(
|
|
264
|
+
value,
|
|
265
|
+
this.connection._osonMaxFieldSize
|
|
266
|
+
);
|
|
267
|
+
} else if (oraType === types.DB_TYPE_VECTOR) {
|
|
268
|
+
const encoder = new vector.VectorEncoder();
|
|
269
|
+
columnDataBuffer = encoder.encode(value);
|
|
270
|
+
} else {
|
|
271
|
+
errors.throwErr(
|
|
272
|
+
errors.ERR_UNSUPPORTED_DATA_TYPE,
|
|
273
|
+
oraType.oraTypeNum,
|
|
274
|
+
metadata.columnNum
|
|
275
|
+
);
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
// If the type was an Oracle Type we had written the data on a temporary
|
|
279
|
+
// BaseBuffer, so we copy the data to our temporaryBuffer
|
|
280
|
+
if (!columnDataBuffer)
|
|
281
|
+
columnDataBuffer = this._encodingTempBuf.buf.slice(
|
|
282
|
+
0,
|
|
283
|
+
this._encodingTempBuf.pos
|
|
284
|
+
);
|
|
285
|
+
|
|
286
|
+
this._writeRawBytesAndLength(columnDataBuffer, columnDataBuffer.length);
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
finishRow() {
|
|
290
|
+
this.currentPiece.isLast = true;
|
|
291
|
+
this._finalizePiece();
|
|
292
|
+
this.currentPiece = null;
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
startRow() {
|
|
296
|
+
this.currentPiece = new DirectPathPiece();
|
|
297
|
+
this.currentPiece.isFirst = true;
|
|
298
|
+
this.currentPiece.isFast = true;
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
|
|
302
|
+
class DirectPathLoadStreamMessage extends Message {
|
|
303
|
+
constructor(connection) {
|
|
304
|
+
super(connection);
|
|
305
|
+
this.caps = connection._protocol.caps;
|
|
306
|
+
this.totalPieceLength = 0;
|
|
307
|
+
this.cursorId = 0;
|
|
308
|
+
this.rowPieces = [];
|
|
309
|
+
this.functionCode = constants.TNS_FUNC_DIRECT_PATH_LOAD_STREAM;
|
|
310
|
+
}
|
|
311
|
+
|
|
312
|
+
_calculatePieces(data, columnMetadata) {
|
|
313
|
+
// Probably better to maintain a MAX_BUFFER_SIZE_FACTOR in types.js
|
|
314
|
+
const numRows = data.length;
|
|
315
|
+
const buf = new PieceBuffer(this.connection);
|
|
316
|
+
|
|
317
|
+
for (let rowNum = 0; rowNum < numRows; rowNum++) {
|
|
318
|
+
const row = data[rowNum];
|
|
319
|
+
if (row.length !== columnMetadata.length) {
|
|
320
|
+
errors.throwErr(
|
|
321
|
+
errors.ERR_WRONG_NUMBER_OF_BINDS,
|
|
322
|
+
columnMetadata.length,
|
|
323
|
+
row.length
|
|
324
|
+
);
|
|
325
|
+
}
|
|
326
|
+
buf.startRow();
|
|
327
|
+
for (let colNum = 0; colNum < columnMetadata.length; colNum++) {
|
|
328
|
+
const metadata = columnMetadata[colNum];
|
|
329
|
+
metadata.rowNum = rowNum;
|
|
330
|
+
const value = row[colNum];
|
|
331
|
+
buf.addColumnValue(metadata, value, this.caps);
|
|
332
|
+
}
|
|
333
|
+
buf.finishRow();
|
|
334
|
+
}
|
|
335
|
+
|
|
336
|
+
this.totalPieceLength = buf.totalPieceLength;
|
|
337
|
+
this.rowPieces = buf.pieces;
|
|
338
|
+
}
|
|
339
|
+
|
|
340
|
+
processErrorInfo(buf) {
|
|
341
|
+
super.processErrorInfo(buf);
|
|
342
|
+
if (this.errorInfo.num === constants.TNS_ERR_NO_DATA_FOUND) {
|
|
343
|
+
this.errorInfo.num = 0;
|
|
344
|
+
this.errorOccurred = false;
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
processReturnParameter(buf) {
|
|
349
|
+
const numOutValues = buf.readUB2();
|
|
350
|
+
for (let i = 0; i < numOutValues; i++) {
|
|
351
|
+
buf.skipBytes(4);
|
|
352
|
+
}
|
|
353
|
+
}
|
|
354
|
+
|
|
355
|
+
encode(buf) {
|
|
356
|
+
this.writeFunctionHeader(buf);
|
|
357
|
+
buf.writeUB2(this.cursorId);
|
|
358
|
+
buf.writeUInt8(1); // pointer (buffer)
|
|
359
|
+
buf.writeUB4(this.totalPieceLength);
|
|
360
|
+
buf.writeUB4(constants.TNS_DP_STREAM_VERSION);
|
|
361
|
+
buf.writeUInt8(0); // pointer (input values)
|
|
362
|
+
buf.writeUB4(0); // number of input values
|
|
363
|
+
buf.writeUInt8(1); // pointer (output values)
|
|
364
|
+
buf.writeUInt8(1); // pointer (output values length)
|
|
365
|
+
|
|
366
|
+
for (const piece of this.rowPieces) {
|
|
367
|
+
piece.writeToMessage(buf);
|
|
368
|
+
}
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
prepare(cursorId, data, columnMetadata) {
|
|
372
|
+
this.cursorId = cursorId;
|
|
373
|
+
this._calculatePieces(data, columnMetadata);
|
|
374
|
+
}
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
module.exports = DirectPathLoadStreamMessage;
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// Copyright (c) 2025, Oracle and/or its affiliates.
|
|
2
|
+
|
|
3
|
+
//-----------------------------------------------------------------------------
|
|
4
|
+
//
|
|
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:
|
|
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.
|
|
15
|
+
// You may obtain a copy of the License at
|
|
16
|
+
//
|
|
17
|
+
// https://www.apache.org/licenses/LICENSE-2.0
|
|
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.
|
|
22
|
+
// See the License for the specific language governing permissions and
|
|
23
|
+
// limitations under the License.
|
|
24
|
+
//
|
|
25
|
+
//-----------------------------------------------------------------------------
|
|
26
|
+
|
|
27
|
+
'use strict';
|
|
28
|
+
|
|
29
|
+
const BaseMessage = require('./base.js');
|
|
30
|
+
const constants = require('../constants.js');
|
|
31
|
+
|
|
32
|
+
class DirectPathOpMessage extends BaseMessage {
|
|
33
|
+
|
|
34
|
+
constructor(connection) {
|
|
35
|
+
super(connection);
|
|
36
|
+
this.cursorId = 0;
|
|
37
|
+
this.opCode = 0;
|
|
38
|
+
this.functionCode = constants.TNS_FUNC_DIRECT_PATH_OP;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
processReturnParameter(buf) {
|
|
42
|
+
const numOutValues = buf.readUB2();
|
|
43
|
+
for (let i = 0; i < numOutValues; i++) {
|
|
44
|
+
buf.skipUB4();
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
encode(buf) {
|
|
49
|
+
this.writeFunctionHeader(buf);
|
|
50
|
+
buf.writeUB4(this.opCode);
|
|
51
|
+
buf.writeUB2(this.cursorId);
|
|
52
|
+
buf.writeUInt8(0); // pointer (input values)
|
|
53
|
+
buf.writeUB4(0); // number of input values
|
|
54
|
+
buf.writeUInt8(1); // pointer (output values)
|
|
55
|
+
buf.writeUInt8(1); // pointer (output values length)
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
prepare(cursorId, opCode) {
|
|
59
|
+
this.cursorId = cursorId;
|
|
60
|
+
this.opCode = opCode;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
module.exports = DirectPathOpMessage;
|
|
@@ -0,0 +1,158 @@
|
|
|
1
|
+
// Copyright (c) 2025, Oracle and/or its affiliates.
|
|
2
|
+
|
|
3
|
+
//-----------------------------------------------------------------------------
|
|
4
|
+
//
|
|
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:
|
|
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.
|
|
15
|
+
// You may obtain a copy of the License at
|
|
16
|
+
//
|
|
17
|
+
// https://www.apache.org/licenses/LICENSE-2.0
|
|
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.
|
|
22
|
+
// See the License for the specific language governing permissions and
|
|
23
|
+
// limitations under the License.
|
|
24
|
+
//
|
|
25
|
+
//-----------------------------------------------------------------------------
|
|
26
|
+
|
|
27
|
+
'use strict';
|
|
28
|
+
|
|
29
|
+
const BaseMessage = require('./base.js');
|
|
30
|
+
const constants = require('../constants.js');
|
|
31
|
+
const errors = require('../../../errors.js');
|
|
32
|
+
const types = require('../../../types.js');
|
|
33
|
+
|
|
34
|
+
class DirectPathPrepareMessage extends BaseMessage {
|
|
35
|
+
|
|
36
|
+
constructor(connection) {
|
|
37
|
+
super(connection);
|
|
38
|
+
this.schemaName = null;
|
|
39
|
+
this.tableName = null;
|
|
40
|
+
this.columnNames = [];
|
|
41
|
+
this.columnMetadata = [];
|
|
42
|
+
this.cursorId = 0;
|
|
43
|
+
this.inValues = new Array(constants.TNS_DPP_IN_MAX_PARAMS).fill(0);
|
|
44
|
+
this.inValuesLength = 0;
|
|
45
|
+
this.outValues = null;
|
|
46
|
+
this.outValuesLength = 0;
|
|
47
|
+
this.functionCode = constants.TNS_FUNC_DIRECT_PATH_PREPARE;
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
//---------------------------------------------------------------------------
|
|
51
|
+
// _setInValue()
|
|
52
|
+
// Sets the value in the input array and updates the maximum value set.
|
|
53
|
+
//---------------------------------------------------------------------------
|
|
54
|
+
_setInValue(key, value) {
|
|
55
|
+
this.inValues[key] = value;
|
|
56
|
+
this.inValuesLength = Math.max(this.inValuesLength, key + 1);
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
//---------------------------------------------------------------------------
|
|
60
|
+
// _writeKeywordParam()
|
|
61
|
+
// Writes a keyword parameter to the buffer.
|
|
62
|
+
//---------------------------------------------------------------------------
|
|
63
|
+
_writeKeywordParam(buf, index, value) {
|
|
64
|
+
const valueBytes = Buffer.from(value, 'utf-8');
|
|
65
|
+
buf.writeUB2(0); // text length (placeholder?)
|
|
66
|
+
buf.writeUB2(valueBytes.length);
|
|
67
|
+
buf.writeBytesWithLength(valueBytes);
|
|
68
|
+
buf.writeUB2(index);
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
//---------------------------------------------------------------------------
|
|
72
|
+
// write()
|
|
73
|
+
// Write the message to the given buffer.
|
|
74
|
+
//---------------------------------------------------------------------------
|
|
75
|
+
encode(buf) {
|
|
76
|
+
// Initialize input array
|
|
77
|
+
this._setInValue(constants.TNS_DPP_IN_INDEX_INTERFACE_VERSION, constants.TNS_DP_INTERFACE_VERSION);
|
|
78
|
+
this._setInValue(constants.TNS_DPP_IN_INDEX_STREAM_VERSION, constants.TNS_DP_STREAM_VERSION);
|
|
79
|
+
this._setInValue(constants.TNS_DPP_IN_INDEX_LOCK_WAIT, 1);
|
|
80
|
+
this._setInValue(constants.TNS_DPP_KW_INDEX_NFOBJ_OID_POS, 0xffff);
|
|
81
|
+
this._setInValue(constants.TNS_DPP_KW_INDEX_NFOBJ_SID_POS, 0xffff);
|
|
82
|
+
this._setInValue(constants.TNS_DPP_KW_INDEX_NFOBJ_VARRAY_INDEX, 0xffff);
|
|
83
|
+
|
|
84
|
+
// Write message
|
|
85
|
+
this.writeFunctionHeader(buf);
|
|
86
|
+
const keywordParametersLength = this.columnNames.length + 2;
|
|
87
|
+
buf.writeUB4(constants.TNS_DPP_OP_CODE_LOAD); // op code
|
|
88
|
+
buf.writeUInt8(1); // keyword parameters (pointer)
|
|
89
|
+
buf.writeUB4(keywordParametersLength);
|
|
90
|
+
buf.writeUInt8(1); // input array (pointer)
|
|
91
|
+
buf.writeUB2(this.inValuesLength);
|
|
92
|
+
buf.writeUInt8(1); // metadata (pointer)
|
|
93
|
+
buf.writeUInt8(1); // metadata length (pointer)
|
|
94
|
+
buf.writeUInt8(1); // parameters (pointer)
|
|
95
|
+
buf.writeUInt8(1); // parameters length (pointer)
|
|
96
|
+
buf.writeUInt8(1); // output array (pointer)
|
|
97
|
+
buf.writeUInt8(1); // output array length (pointer)
|
|
98
|
+
|
|
99
|
+
this._writeKeywordParam(buf, constants.TNS_DPP_KW_INDEX_SCHEMA_NAME, this.schemaName);
|
|
100
|
+
this._writeKeywordParam(buf, constants.TNS_DPP_KW_INDEX_OBJECT_NAME, this.tableName);
|
|
101
|
+
for (const name of this.columnNames) {
|
|
102
|
+
this._writeKeywordParam(buf, constants.TNS_DPP_KW_INDEX_COLUMN_NAME, name);
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
for (let i = 0; i < this.inValuesLength; i++) {
|
|
106
|
+
buf.writeUB4(this.inValues[i]);
|
|
107
|
+
}
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
//---------------------------------------------------------------------------
|
|
111
|
+
// processColumnInfo()
|
|
112
|
+
// Process column metadata returned by the database. CLOB and BLOB are
|
|
113
|
+
// always treated as strings and bytes when using direct path load.
|
|
114
|
+
//---------------------------------------------------------------------------
|
|
115
|
+
processColumnInfo(buf, columnNum) {
|
|
116
|
+
const metadata = super.processColumnInfo(buf, columnNum);
|
|
117
|
+
if (metadata.type === types.DB_TYPE_CLOB) {
|
|
118
|
+
let csfrm = metadata.type._csfrm;
|
|
119
|
+
if (csfrm === constants.CSFRM_IMPLICIT) {
|
|
120
|
+
const caps = this.connection._protocol.caps;
|
|
121
|
+
// character set ids < 800 are all single-byte character sets
|
|
122
|
+
// while character set ids >= 800 are all multi-byte character sets
|
|
123
|
+
if (caps.charsetId >= 800)
|
|
124
|
+
csfrm = constants.CSFRM_NCHAR;
|
|
125
|
+
}
|
|
126
|
+
metadata.type = types.getTypeByOraTypeNum(types.DB_TYPE_LONG._oraTypeNum,
|
|
127
|
+
csfrm);
|
|
128
|
+
} else if (metadata.type === types.DB_TYPE_BLOB) {
|
|
129
|
+
metadata.type = types.DB_TYPE_LONG_RAW;
|
|
130
|
+
}
|
|
131
|
+
return metadata;
|
|
132
|
+
}
|
|
133
|
+
|
|
134
|
+
//---------------------------------------------------------------------------
|
|
135
|
+
// processReturnParameter()
|
|
136
|
+
// Process the return parameters sent by the database.
|
|
137
|
+
//---------------------------------------------------------------------------
|
|
138
|
+
processReturnParameter(buf) {
|
|
139
|
+
const numColumns = buf.readUB4();
|
|
140
|
+
this.columnMetadata = [];
|
|
141
|
+
for (let i = 0; i < numColumns; i++) {
|
|
142
|
+
this.columnMetadata.push(this.processColumnInfo(buf, i));
|
|
143
|
+
}
|
|
144
|
+
const numParams = buf.readUB2();
|
|
145
|
+
if (numParams > 0) {
|
|
146
|
+
errors.throwErr(errors.ERR_UNEXPECTED_DATA, 'directPathLoad numParams');
|
|
147
|
+
}
|
|
148
|
+
this.outValuesLength = buf.readUB2();
|
|
149
|
+
this.outValues = [];
|
|
150
|
+
for (let i = 0; i < this.outValuesLength; i++) {
|
|
151
|
+
this.outValues.push(buf.readUB4());
|
|
152
|
+
}
|
|
153
|
+
this.cursorId = this.outValues[constants.TNS_DPP_OUT_INDEX_CURSOR];
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
module.exports = DirectPathPrepareMessage;
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
// Copyright (c) 2026, Oracle and/or its affiliates.
|
|
2
|
+
|
|
3
|
+
//-----------------------------------------------------------------------------
|
|
4
|
+
//
|
|
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:
|
|
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.
|
|
15
|
+
// You may obtain a copy of the License at
|
|
16
|
+
//
|
|
17
|
+
// https://www.apache.org/licenses/LICENSE-2.0
|
|
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.
|
|
22
|
+
// See the License for the specific language governing permissions and
|
|
23
|
+
// limitations under the License.
|
|
24
|
+
//
|
|
25
|
+
//-----------------------------------------------------------------------------
|
|
26
|
+
|
|
27
|
+
'use strict';
|
|
28
|
+
|
|
29
|
+
const Message = require("./base.js");
|
|
30
|
+
const constants = require("../constants.js");
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Executes endPipeline RPC
|
|
34
|
+
*
|
|
35
|
+
* @class EndPipelineMessage
|
|
36
|
+
* @extends {Message}
|
|
37
|
+
*/
|
|
38
|
+
class EndPipelineMessage extends Message {
|
|
39
|
+
|
|
40
|
+
constructor(connImpl) {
|
|
41
|
+
super(connImpl);
|
|
42
|
+
this.functionCode = constants.TNS_FUNC_PIPELINE_END;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
//-------------------------------------------------------------------------
|
|
46
|
+
// encode()
|
|
47
|
+
//
|
|
48
|
+
// Write the RPC to perform pipeline end operation in the database
|
|
49
|
+
//-------------------------------------------------------------------------
|
|
50
|
+
encode(buf) {
|
|
51
|
+
this.writeFunctionHeader(buf);
|
|
52
|
+
buf.writeUB4(0); // ID (unused)
|
|
53
|
+
}
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
module.exports = EndPipelineMessage;
|