oracledb 6.10.0 → 7.0.1
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.1-darwin-arm64.node +0 -0
- package/build/Release/oracledb-7.0.1-darwin-arm64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-7.0.1-js-buildinfo.txt +1 -0
- package/build/Release/oracledb-7.0.1-linux-arm64.node +0 -0
- package/build/Release/oracledb-7.0.1-linux-arm64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-7.0.1-linux-x64.node +0 -0
- package/build/Release/oracledb-7.0.1-linux-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-7.0.1-win32-x64.node +0 -0
- package/build/Release/oracledb-7.0.1-win32-x64.node-buildinfo.txt +1 -0
- package/lib/aqDeqOptions.js +4 -4
- package/lib/aqEnqOptions.js +2 -2
- package/lib/aqQueue.js +11 -6
- package/lib/connection.js +407 -40
- package/lib/endUserSecurityContext.js +169 -0
- package/lib/errors.js +108 -5
- package/lib/impl/connection.js +76 -2
- package/lib/impl/datahandlers/buffer.js +19 -5
- package/lib/impl/datahandlers/vector.js +25 -5
- package/lib/impl/lob.js +9 -0
- package/lib/impl/parserHelpers.js +447 -0
- package/lib/impl/resultset.js +1 -1
- package/lib/lob.js +27 -14
- package/lib/obfuscation.js +97 -0
- package/lib/oracledb.js +148 -43
- package/lib/parser.js +204 -0
- package/lib/pipeline.js +113 -0
- package/lib/pool.js +16 -1
- package/lib/resultset.js +42 -21
- package/lib/settings.js +1 -0
- package/lib/thin/connection.js +461 -53
- package/lib/thin/dbObject.js +10 -4
- package/lib/thin/lob.js +20 -1
- package/lib/thin/pool.js +43 -63
- package/lib/thin/protocol/capabilities.js +18 -3
- package/lib/thin/protocol/constants.js +82 -2
- package/lib/thin/protocol/encryptDecrypt.js +43 -8
- package/lib/thin/protocol/messages/aqArray.js +2 -2
- package/lib/thin/protocol/messages/aqBase.js +2 -2
- package/lib/thin/protocol/messages/auth.js +6 -1
- package/lib/thin/protocol/messages/base.js +246 -5
- 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 -143
- package/lib/thin/protocol/packet.js +115 -24
- 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 +4 -4
- package/lib/thin/sqlnet/navNodes.js +4 -2
- package/lib/thin/sqlnet/networkSession.js +78 -50
- package/lib/thin/sqlnet/ntTcp.js +24 -0
- package/lib/thin/sqlnet/nvStrToNvPair.js +50 -25
- package/lib/thin/sqlnet/packet.js +49 -8
- package/lib/thin/sqlnet/paramParser.js +10 -7
- package/lib/thin/sqlnet/sessionAtts.js +2 -2
- package/lib/thin/statementCache.js +2 -4
- package/lib/traceHandler.js +59 -2
- package/lib/transformer.js +8 -3
- package/lib/types.js +35 -21
- package/lib/util.js +6 -6
- package/lib/version.js +4 -4
- 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 +4 -5
- package/plugins/token/extensionAzure/index.js +0 -1
- package/plugins/token/extensionOci/index.js +0 -1
- package/build/Release/oracledb-6.10.0-darwin-arm64.node +0 -0
- package/build/Release/oracledb-6.10.0-darwin-arm64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.10.0-darwin-x64.node +0 -0
- package/build/Release/oracledb-6.10.0-darwin-x64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.10.0-js-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.10.0-linux-arm64.node +0 -0
- package/build/Release/oracledb-6.10.0-linux-arm64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.10.0-linux-x64.node +0 -0
- package/build/Release/oracledb-6.10.0-linux-x64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.10.0-win32-x64.node +0 -0
- package/build/Release/oracledb-6.10.0-win32-x64.node-buildinfo.txt +0 -1
|
@@ -0,0 +1,169 @@
|
|
|
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 { Buffer } = require('buffer');
|
|
30
|
+
const errors = require('./errors.js');
|
|
31
|
+
const oson = require('./impl/datahandlers/oson.js');
|
|
32
|
+
const { ObfuscatedValue } = require('./obfuscation.js');
|
|
33
|
+
const transformer = require('./transformer.js');
|
|
34
|
+
|
|
35
|
+
const DEFAULT_MAX_FIELD_NAME_SIZE = 65535;
|
|
36
|
+
const DEFAULT_MAX_PAYLOAD_LENGTH = 65535;
|
|
37
|
+
|
|
38
|
+
function hasNonEmptyText(value) {
|
|
39
|
+
return (typeof value === 'string') && value.trim().length > 0;
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/*
|
|
43
|
+
Represents the credential set an application associates with an end user.
|
|
44
|
+
|
|
45
|
+
Required properties
|
|
46
|
+
- databaseAccessToken: non-empty string accepted by the database driver.
|
|
47
|
+
- endUserToken or endUserName: exactly one must be supplied as a string.
|
|
48
|
+
|
|
49
|
+
Optional properties
|
|
50
|
+
- key: look-up identifier the database maps to stored context attributes; may be
|
|
51
|
+
supplied only with endUserName.
|
|
52
|
+
- dataRoles: data roles enabled/disabled by the application logic, rather
|
|
53
|
+
than a database security policy.
|
|
54
|
+
- attributes: Attributes are contained in JSON objects conforming
|
|
55
|
+
to a JSON schema of an END USER CONTEXT declared in the database.
|
|
56
|
+
|
|
57
|
+
*/
|
|
58
|
+
class EndUserSecurityContext {
|
|
59
|
+
constructor(options) {
|
|
60
|
+
errors.assertArgCount(arguments, 1, 1);
|
|
61
|
+
errors.assertParamValue(
|
|
62
|
+
typeof options === 'object' && options !== null && !Array.isArray(options),
|
|
63
|
+
1
|
|
64
|
+
);
|
|
65
|
+
|
|
66
|
+
const {
|
|
67
|
+
databaseAccessToken,
|
|
68
|
+
endUserToken,
|
|
69
|
+
endUserName,
|
|
70
|
+
key,
|
|
71
|
+
dataRoles,
|
|
72
|
+
attributes
|
|
73
|
+
} = options;
|
|
74
|
+
const hasEndUserToken = endUserToken !== undefined && endUserToken !== null;
|
|
75
|
+
const hasEndUserName = endUserName !== undefined && endUserName !== null;
|
|
76
|
+
const hasKey = key !== undefined && key !== null;
|
|
77
|
+
|
|
78
|
+
// The database access token is always required, and the end user must be
|
|
79
|
+
// identified either by token or by name, but not both.
|
|
80
|
+
errors.assertParamValue(hasNonEmptyText(databaseAccessToken), 1);
|
|
81
|
+
errors.assertParamValue(
|
|
82
|
+
(hasEndUserToken && !hasEndUserName && !hasKey) ||
|
|
83
|
+
(!hasEndUserToken && hasEndUserName), 1);
|
|
84
|
+
|
|
85
|
+
// When supplied, token/name/key values must contain non-whitespace text.
|
|
86
|
+
if (hasEndUserToken) {
|
|
87
|
+
errors.assertParamValue(hasNonEmptyText(endUserToken), 1);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
if (hasEndUserName) {
|
|
91
|
+
errors.assertParamValue(hasNonEmptyText(endUserName), 1);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
if (hasKey) {
|
|
95
|
+
errors.assertParamValue(hasEndUserName, 1);
|
|
96
|
+
errors.assertParamValue(hasNonEmptyText(key), 1);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const payload = {
|
|
100
|
+
ver: '1.0',
|
|
101
|
+
database_access_token: databaseAccessToken
|
|
102
|
+
};
|
|
103
|
+
|
|
104
|
+
if (endUserToken != null) {
|
|
105
|
+
payload.end_user_token = endUserToken;
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
if (endUserName != null) {
|
|
109
|
+
payload.end_user_name = endUserName;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (key != null) {
|
|
113
|
+
payload.end_user_contextid = key;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
// Data roles are optional, but must be passed as an array when present.
|
|
117
|
+
if (dataRoles != null) {
|
|
118
|
+
errors.assertParamValue(Array.isArray(dataRoles), 1);
|
|
119
|
+
payload.data_roles = Array.from(dataRoles);
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Attributes are encoded as name/value entries expected by the OSON payload.
|
|
123
|
+
if (attributes != null) {
|
|
124
|
+
errors.assertParamValue(
|
|
125
|
+
typeof attributes === 'object' && !Array.isArray(attributes),
|
|
126
|
+
1
|
|
127
|
+
);
|
|
128
|
+
payload.attributes = Object.entries(attributes).map(
|
|
129
|
+
([name, values]) => ({ name, values }));
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
this._payloadStore = new ObfuscatedValue();
|
|
133
|
+
this._encodeAndStorePayload(payload);
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
_encodePayload(value) {
|
|
137
|
+
const encoder = new oson.OsonEncoder();
|
|
138
|
+
return encoder.encode(
|
|
139
|
+
transformer.transformJsonValue(value),
|
|
140
|
+
DEFAULT_MAX_FIELD_NAME_SIZE
|
|
141
|
+
);
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
_encodeAndStorePayload(payload) {
|
|
145
|
+
const encodedPayload =
|
|
146
|
+
this._encodePayload(payload);
|
|
147
|
+
this.setEncodedPayload(encodedPayload);
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
setEncodedPayload(encodedPayload) {
|
|
151
|
+
errors.assertParamValue(Buffer.isBuffer(encodedPayload), 1);
|
|
152
|
+
const payloadLength = encodedPayload.length;
|
|
153
|
+
if (payloadLength > DEFAULT_MAX_PAYLOAD_LENGTH) {
|
|
154
|
+
encodedPayload.fill(0);
|
|
155
|
+
errors.throwErr(
|
|
156
|
+
errors.ERR_INVALID_END_USER_SECURITY_CONTEXT_LENGTH,
|
|
157
|
+
payloadLength
|
|
158
|
+
);
|
|
159
|
+
}
|
|
160
|
+
this._payloadStore.set(encodedPayload, { returnBuffer: true });
|
|
161
|
+
encodedPayload.fill(0);
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
getDeobfuscatedValue() {
|
|
165
|
+
return this._payloadStore.get({ returnBuffer: true });
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
module.exports = EndUserSecurityContext;
|
package/lib/errors.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright (c) 2022,
|
|
1
|
+
// Copyright (c) 2022, 2026, Oracle and/or its affiliates.
|
|
2
2
|
//-----------------------------------------------------------------------------
|
|
3
3
|
//
|
|
4
4
|
// This software is dual-licensed to you under the Universal Permissive License
|
|
@@ -180,6 +180,25 @@ const ERR_SESSIONLESS_ALREADY_ACTIVE = 171;
|
|
|
180
180
|
const ERR_SESSIONLESS_INACTIVE = 172;
|
|
181
181
|
const ERR_INVALID_SERVER_RESPONSE = 173;
|
|
182
182
|
const ERR_PAYLOAD_CANNOT_BE_ENQUEUED = 174;
|
|
183
|
+
const ERR_NULLS_NOT_ALLOWED = 175;
|
|
184
|
+
const ERR_DPL_TOO_MUCH_DATA = 176;
|
|
185
|
+
const ERR_DPL_INVALID_ROW_DATA = 177;
|
|
186
|
+
const ERR_PIPELINE_OPERATION_NOT_SUPPORTED = 178;
|
|
187
|
+
const ERR_PIPELINE_MISMATCHED_TOKEN = 179;
|
|
188
|
+
const ERR_PIPELINE_DBOBJECTS_NOT_SUPPORTED = 180;
|
|
189
|
+
const ERR_PIPELINE_LARGE_BUFFERS_NOT_SUPPORTED = 181;
|
|
190
|
+
const ERR_PIPELINE_EXEC_OPTION_NOT_SUPPORTED = 182;
|
|
191
|
+
const ERR_INVALID_SQL_NAME = 183;
|
|
192
|
+
const ERR_APP_CONTEXT_EMPTY_NAMESPACE = 184;
|
|
193
|
+
const ERR_APP_CONTEXT_INVALID_KEY_VALUE = 185;
|
|
194
|
+
const ERR_APP_CONTEXT_KEY_TOO_LONG = 186;
|
|
195
|
+
const ERR_APP_CONTEXT_VALUE_TOO_LONG = 187;
|
|
196
|
+
const ERR_UNSUPPORTED_KEY_LENGTH = 188;
|
|
197
|
+
const ERR_INVALID_END_USER_SECURITY_CONTEXT_LENGTH = 189;
|
|
198
|
+
const ERR_END_USER_SECURITY_CONTEXT_REQUIRES_TCPS = 190;
|
|
199
|
+
const ERR_UNSUPPORTED_DEEP_DATA_SECURITY_FEATURE = 191;
|
|
200
|
+
const ERR_CHAR_CS_NOT_SUPPORTED = 192;
|
|
201
|
+
const ERR_INVALID_PROPERTY_LENGTH = 193;
|
|
183
202
|
|
|
184
203
|
// Oracle Net layer errors start from 500
|
|
185
204
|
const ERR_CONNECTION_CLOSED = 500;
|
|
@@ -203,6 +222,7 @@ const ERR_INVALID_SERVICE_NAME = 518;
|
|
|
203
222
|
const ERR_INVALID_SID = 519;
|
|
204
223
|
const ERR_TNS_NAMES_FILE_MISSING = 520;
|
|
205
224
|
const ERR_CONNECTION_EOF = 521;
|
|
225
|
+
const ERR_CONNECT_DESCRIPTOR_LIMIT_EXCEEDED = 522;
|
|
206
226
|
const ERR_CONFIG_PROVIDER_FAILED_TO_RETRIEVE_CONFIG = 523;
|
|
207
227
|
const ERR_REGISTER_HOOKFN_CONFIGPROVIDER = 524;
|
|
208
228
|
const ERR_WALLET_TYPE_NOT_SUPPORTED = 529;
|
|
@@ -212,6 +232,7 @@ const ERR_ANO_STATUS = 532;
|
|
|
212
232
|
const ERR_ANO_NEGOTIATION = 533;
|
|
213
233
|
const ERR_DATA_COMPRESSION = 534;
|
|
214
234
|
const ERR_CONFIG_PROVIDER_PARAM_TYPE = 535;
|
|
235
|
+
const ERR_TOO_MANY_REDIRECTS = 536;
|
|
215
236
|
|
|
216
237
|
// Oracle SUCCESS_WITH_INFO warning start from 700
|
|
217
238
|
const WRN_COMPILATION_CREATE = 700;
|
|
@@ -256,6 +277,7 @@ adjustErrorXref.set("ORA-12583", ERR_CONNECTION_CLOSED);
|
|
|
256
277
|
adjustErrorXref.set("ORA-27146", ERR_CONNECTION_CLOSED);
|
|
257
278
|
adjustErrorXref.set("ORA-28511", ERR_CONNECTION_CLOSED);
|
|
258
279
|
adjustErrorXref.set("ORA-56600", ERR_CONNECTION_CLOSED);
|
|
280
|
+
adjustErrorXref.set("ORA-24315", ERR_APP_CONTEXT_EMPTY_NAMESPACE);
|
|
259
281
|
adjustErrorXref.set("ORA-24338", ERR_INVALID_REF_CURSOR);
|
|
260
282
|
adjustErrorXref.set("ORA-25708", ERR_TOKEN_HAS_EXPIRED);
|
|
261
283
|
adjustErrorXref.set("ORA-24344", WRN_COMPILATION_CREATE);
|
|
@@ -389,7 +411,7 @@ messages.set(ERR_CONN_TOKEN_BASED_AUTH, // NJS-086
|
|
|
389
411
|
messages.set(ERR_TOKEN_HAS_EXPIRED, // NJS-087
|
|
390
412
|
'access token has expired');
|
|
391
413
|
messages.set(ERR_NOT_IMPLEMENTED, // NJS-089
|
|
392
|
-
'%s is not supported by node-oracledb in
|
|
414
|
+
'%s is not supported by node-oracledb in %s mode');
|
|
393
415
|
messages.set(ERR_INIT_ORACLE_CLIENT_ARGS, // NJS-090
|
|
394
416
|
'initOracleClient() was already called with different arguments');
|
|
395
417
|
messages.set(ERR_MISSING_FILE, // NJS-091
|
|
@@ -546,7 +568,44 @@ messages.set(ERR_INVALID_SERVER_RESPONSE, //NJS-173
|
|
|
546
568
|
'Invalid server response to connection request');
|
|
547
569
|
messages.set(ERR_PAYLOAD_CANNOT_BE_ENQUEUED, // NJS-174
|
|
548
570
|
"Payload cannot be enqueued since it does not match the payload type supported by the queue");
|
|
549
|
-
|
|
571
|
+
messages.set(ERR_NULLS_NOT_ALLOWED, // NJS-175
|
|
572
|
+
'Value for column %s may not be null on row %d');
|
|
573
|
+
messages.set(ERR_DPL_TOO_MUCH_DATA, // NJS-176
|
|
574
|
+
'The maximum size of a Direct Path load has been exceeded');
|
|
575
|
+
messages.set(ERR_DPL_INVALID_ROW_DATA, // NJS-177
|
|
576
|
+
'The row data provided for Direct Path load is Invalid. Expected a 2D array (Array of Arrays) representing rows and columns.');
|
|
577
|
+
messages.set(ERR_PIPELINE_OPERATION_NOT_SUPPORTED, // NJS-178
|
|
578
|
+
'Unsupported pipeline operation type: %s');
|
|
579
|
+
messages.set(ERR_PIPELINE_MISMATCHED_TOKEN, // NJS-179
|
|
580
|
+
'Pipeline internal error: token number %d does not match expected token number %d');
|
|
581
|
+
messages.set(ERR_PIPELINE_DBOBJECTS_NOT_SUPPORTED, // NJS-180
|
|
582
|
+
'Oracle Database Object types are not supported in pipeline mode');
|
|
583
|
+
messages.set(ERR_PIPELINE_LARGE_BUFFERS_NOT_SUPPORTED, // NJS-181
|
|
584
|
+
'PL/SQL blocks with string/bytes object size greater than 32k are not supported in pipeline mode');
|
|
585
|
+
messages.set(ERR_PIPELINE_EXEC_OPTION_NOT_SUPPORTED, // NJS-182
|
|
586
|
+
`Execute option '%s' is not supported in pipeline mode`);
|
|
587
|
+
messages.set(ERR_INVALID_SQL_NAME, // NJS-183
|
|
588
|
+
'invalid SQL name: embedded double quotes are not allowed');
|
|
589
|
+
messages.set(ERR_APP_CONTEXT_EMPTY_NAMESPACE, // NJS-184
|
|
590
|
+
'The namespace can not be empty for Application Context');
|
|
591
|
+
messages.set(ERR_APP_CONTEXT_INVALID_KEY_VALUE, // NJS-185
|
|
592
|
+
'Invalid Application Context entry: both key and value must be strings. Got key=%s, value=%s');
|
|
593
|
+
messages.set(ERR_APP_CONTEXT_KEY_TOO_LONG, // NJS-186
|
|
594
|
+
'Application Context key length (%d bytes) exceeds the maximum allowed (%d bytes)');
|
|
595
|
+
messages.set(ERR_APP_CONTEXT_VALUE_TOO_LONG, // NJS-187
|
|
596
|
+
'Application Context value length (%d bytes) exceeds the maximum allowed (%d bytes)');
|
|
597
|
+
messages.set(ERR_UNSUPPORTED_KEY_LENGTH, // NJS-188
|
|
598
|
+
'Unsupported encryption key length %d');
|
|
599
|
+
messages.set(ERR_INVALID_END_USER_SECURITY_CONTEXT_LENGTH, // NJS-189
|
|
600
|
+
'Specified End User Context exceeds the maximum supported size %d');
|
|
601
|
+
messages.set(ERR_END_USER_SECURITY_CONTEXT_REQUIRES_TCPS, // NJS-190
|
|
602
|
+
'End User Context requires use of the tcps protocol');
|
|
603
|
+
messages.set(ERR_UNSUPPORTED_DEEP_DATA_SECURITY_FEATURE, // NJS-191
|
|
604
|
+
'database version does not support the Oracle Deep Data Security feature');
|
|
605
|
+
messages.set(ERR_CHAR_CS_NOT_SUPPORTED, // NJS-192
|
|
606
|
+
'Character set id %d is not supported by node-oracledb in Thin mode');
|
|
607
|
+
messages.set(ERR_INVALID_PROPERTY_LENGTH, // NJS-193
|
|
608
|
+
'The length of the parameter %s exceeds the maximum allowed length of %d');
|
|
550
609
|
|
|
551
610
|
// Oracle Net layer errors
|
|
552
611
|
|
|
@@ -592,6 +651,8 @@ messages.set(ERR_TNS_NAMES_FILE_MISSING, // NJS-520
|
|
|
592
651
|
'cannot connect to Oracle Database. File tnsnames.ora not found in %s');
|
|
593
652
|
messages.set(ERR_CONNECTION_EOF, // NJS-521
|
|
594
653
|
'connection to host %s port %d received end-of-file on communication channel. (CONNECTION_ID=%s)');
|
|
654
|
+
messages.set(ERR_CONNECT_DESCRIPTOR_LIMIT_EXCEEDED, // NJS-522
|
|
655
|
+
'connection string exceeds supported descriptor %s limit of %d');
|
|
595
656
|
messages.set(ERR_CONFIG_PROVIDER_FAILED_TO_RETRIEVE_CONFIG, // NJS-523
|
|
596
657
|
'Failed to retrieve configuration from Centralized Configuration Provider:\n %s');
|
|
597
658
|
messages.set(ERR_REGISTER_HOOKFN_CONFIGPROVIDER, // NJS-524
|
|
@@ -610,6 +671,8 @@ messages.set(ERR_DATA_COMPRESSION, 'Error during data compression/decompression:
|
|
|
610
671
|
// Oracle SUCCESS_WITH_INFO warning
|
|
611
672
|
messages.set(ERR_CONFIG_PROVIDER_PARAM_TYPE, // NJS-535
|
|
612
673
|
'Parameter does not have a valid type: %s\n');
|
|
674
|
+
messages.set(ERR_TOO_MANY_REDIRECTS, // NJS-536
|
|
675
|
+
'Too many connect redirects (limit: %d)');
|
|
613
676
|
messages.set(WRN_COMPILATION_CREATE, // NJS-700
|
|
614
677
|
'creation succeeded with compilation errors');
|
|
615
678
|
|
|
@@ -733,6 +796,21 @@ function assertParamValue(condition, parameterNum) {
|
|
|
733
796
|
assert(condition, ERR_INVALID_PARAMETER_VALUE, parameterNum);
|
|
734
797
|
}
|
|
735
798
|
|
|
799
|
+
//-----------------------------------------------------------------------------
|
|
800
|
+
// assertPropLength()
|
|
801
|
+
//
|
|
802
|
+
// Asserts that the property value is of specified type and doesn't exceed
|
|
803
|
+
// maximum specified length
|
|
804
|
+
//-----------------------------------------------------------------------------
|
|
805
|
+
function assertPropLength(value, propType, propMaxLength, propName) {
|
|
806
|
+
if (propType !== 'array')
|
|
807
|
+
assertPropValue(typeof value === propType, propName);
|
|
808
|
+
else
|
|
809
|
+
assertPropValue(Array.isArray(value), propName);
|
|
810
|
+
assert(value.length <= propMaxLength, ERR_INVALID_PROPERTY_LENGTH, propName,
|
|
811
|
+
propMaxLength);
|
|
812
|
+
}
|
|
813
|
+
|
|
736
814
|
//-----------------------------------------------------------------------------
|
|
737
815
|
// assertPropValue()
|
|
738
816
|
//
|
|
@@ -756,6 +834,9 @@ function getErr(errorNum) {
|
|
|
756
834
|
errorNum = ERR_INVALID_ERR_NUM;
|
|
757
835
|
baseText = messages.get(errorNum);
|
|
758
836
|
}
|
|
837
|
+
if (errorNum === ERR_INVALID_PACKET && args.length > 1) {
|
|
838
|
+
baseText += '. Cause: %s';
|
|
839
|
+
}
|
|
759
840
|
const errorNumStr = errorNum.toString().padStart(3, '0');
|
|
760
841
|
const code = `${ERR_PREFIX}-${errorNumStr}`;
|
|
761
842
|
args[0] = `${code}: ${baseText}`;
|
|
@@ -787,10 +868,11 @@ function throwErrWithORAError() {
|
|
|
787
868
|
//-----------------------------------------------------------------------------
|
|
788
869
|
// throwNotImplemented()
|
|
789
870
|
//
|
|
790
|
-
// Throws an error that the feature is not supported in Thin mode
|
|
871
|
+
// Throws an error that the feature is not supported in Thin/Thick mode
|
|
791
872
|
//-----------------------------------------------------------------------------
|
|
792
873
|
function throwNotImplemented(feature) {
|
|
793
|
-
|
|
874
|
+
const settings = require('./settings.js');
|
|
875
|
+
throwErr(ERR_NOT_IMPLEMENTED, feature, settings.thin ? 'Thin' : 'Thick');
|
|
794
876
|
}
|
|
795
877
|
|
|
796
878
|
|
|
@@ -855,6 +937,7 @@ function throwWrapErr(err, fnOpt) {
|
|
|
855
937
|
|
|
856
938
|
// define exports
|
|
857
939
|
module.exports = {
|
|
940
|
+
ERR_TOO_MANY_REDIRECTS,
|
|
858
941
|
ERR_INTEGRITY_ERROR_CODES,
|
|
859
942
|
ERR_INVALID_POOL,
|
|
860
943
|
ERR_INVALID_CONNECTION,
|
|
@@ -938,6 +1021,7 @@ module.exports = {
|
|
|
938
1021
|
ERR_NO_CONFIG_DIR,
|
|
939
1022
|
ERR_TNS_ENTRY_NOT_FOUND,
|
|
940
1023
|
ERR_CONNECTION_EOF,
|
|
1024
|
+
ERR_CONNECT_DESCRIPTOR_LIMIT_EXCEEDED,
|
|
941
1025
|
ERR_CONFIG_PROVIDER_FAILED_TO_RETRIEVE_CONFIG,
|
|
942
1026
|
ERR_CONFIG_PROVIDER_PARAM_TYPE,
|
|
943
1027
|
ERR_REGISTER_HOOKFN_CONFIGPROVIDER,
|
|
@@ -1009,6 +1093,17 @@ module.exports = {
|
|
|
1009
1093
|
ERR_SESSIONLESS_INACTIVE,
|
|
1010
1094
|
ERR_INVALID_SERVER_RESPONSE,
|
|
1011
1095
|
ERR_PAYLOAD_CANNOT_BE_ENQUEUED,
|
|
1096
|
+
ERR_NULLS_NOT_ALLOWED,
|
|
1097
|
+
ERR_DPL_TOO_MUCH_DATA,
|
|
1098
|
+
ERR_DPL_INVALID_ROW_DATA,
|
|
1099
|
+
ERR_APP_CONTEXT_INVALID_KEY_VALUE,
|
|
1100
|
+
ERR_APP_CONTEXT_KEY_TOO_LONG,
|
|
1101
|
+
ERR_APP_CONTEXT_VALUE_TOO_LONG,
|
|
1102
|
+
ERR_UNSUPPORTED_KEY_LENGTH,
|
|
1103
|
+
ERR_APP_CONTEXT_EMPTY_NAMESPACE,
|
|
1104
|
+
ERR_INVALID_END_USER_SECURITY_CONTEXT_LENGTH,
|
|
1105
|
+
ERR_END_USER_SECURITY_CONTEXT_REQUIRES_TCPS,
|
|
1106
|
+
ERR_UNSUPPORTED_DEEP_DATA_SECURITY_FEATURE,
|
|
1012
1107
|
ERR_CONNECTION_CLOSED_CODE: `${ERR_PREFIX}-${ERR_CONNECTION_CLOSED}`,
|
|
1013
1108
|
ERR_OPERATION_NOT_SUPPORTED_ON_BFILE,
|
|
1014
1109
|
ERR_OPERATION_ONLY_SUPPORTED_ON_BFILE,
|
|
@@ -1025,6 +1120,13 @@ module.exports = {
|
|
|
1025
1120
|
ERR_DB_FETCH_TYPE_HANDLER_RETURN_VALUE,
|
|
1026
1121
|
ERR_ACCESS_TOKEN,
|
|
1027
1122
|
ERR_CALLOUT_FN,
|
|
1123
|
+
ERR_PIPELINE_OPERATION_NOT_SUPPORTED,
|
|
1124
|
+
ERR_PIPELINE_MISMATCHED_TOKEN,
|
|
1125
|
+
ERR_PIPELINE_DBOBJECTS_NOT_SUPPORTED,
|
|
1126
|
+
ERR_PIPELINE_LARGE_BUFFERS_NOT_SUPPORTED,
|
|
1127
|
+
ERR_PIPELINE_EXEC_OPTION_NOT_SUPPORTED,
|
|
1128
|
+
ERR_INVALID_SQL_NAME,
|
|
1129
|
+
ERR_CHAR_CS_NOT_SUPPORTED,
|
|
1028
1130
|
WRN_COMPILATION_CREATE,
|
|
1029
1131
|
assert,
|
|
1030
1132
|
assertArgCount,
|
|
@@ -1036,6 +1138,7 @@ module.exports = {
|
|
|
1036
1138
|
assertParamPropUnsignedIntNonZero,
|
|
1037
1139
|
assertParamPropValue,
|
|
1038
1140
|
assertParamValue,
|
|
1141
|
+
assertPropLength,
|
|
1039
1142
|
assertPropValue,
|
|
1040
1143
|
getErr,
|
|
1041
1144
|
throwErr,
|
package/lib/impl/connection.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
// Copyright (c) 2022,
|
|
1
|
+
// Copyright (c) 2022, 2026, Oracle and/or its affiliates.
|
|
2
2
|
|
|
3
3
|
//-----------------------------------------------------------------------------
|
|
4
4
|
//
|
|
@@ -84,13 +84,16 @@ class ConnectionImpl {
|
|
|
84
84
|
}
|
|
85
85
|
traceConfig.serviceName = this.getServiceName();
|
|
86
86
|
traceConfig.instanceName = this.getInstanceName();
|
|
87
|
-
traceConfig.pdbName = this.
|
|
87
|
+
traceConfig.pdbName = this.getPdbName();
|
|
88
|
+
traceConfig.dbName = this.getDbName();
|
|
89
|
+
traceConfig.domainName = this.getDbDomain();
|
|
88
90
|
|
|
89
91
|
// Thick mode doesnt have these properties for now.
|
|
90
92
|
if (settings.thin) {
|
|
91
93
|
traceConfig.hostName = this.getHostName();
|
|
92
94
|
traceConfig.port = this.getPort();
|
|
93
95
|
traceConfig.protocol = this.getProtocol();
|
|
96
|
+
traceConfig.dbUniqueName = this.getDbUniqueName();
|
|
94
97
|
}
|
|
95
98
|
return traceConfig;
|
|
96
99
|
}
|
|
@@ -253,6 +256,24 @@ class ConnectionImpl {
|
|
|
253
256
|
errors.throwNotImplemented("getting db name");
|
|
254
257
|
}
|
|
255
258
|
|
|
259
|
+
//---------------------------------------------------------------------------
|
|
260
|
+
// getPdbName()
|
|
261
|
+
//
|
|
262
|
+
// Returns the name of a container associated with the connection..
|
|
263
|
+
//---------------------------------------------------------------------------
|
|
264
|
+
getPdbName() {
|
|
265
|
+
errors.throwNotImplemented("getting pdb name");
|
|
266
|
+
}
|
|
267
|
+
|
|
268
|
+
//---------------------------------------------------------------------------
|
|
269
|
+
// getDbUniqueName()
|
|
270
|
+
//
|
|
271
|
+
// Returns the Oracle Database unique name associated with the connection.
|
|
272
|
+
//---------------------------------------------------------------------------
|
|
273
|
+
getDbUniqueName() {
|
|
274
|
+
errors.throwNotImplemented("getting db unique name");
|
|
275
|
+
}
|
|
276
|
+
|
|
256
277
|
//---------------------------------------------------------------------------
|
|
257
278
|
// getDbObjectClass()
|
|
258
279
|
//
|
|
@@ -539,6 +560,24 @@ class ConnectionImpl {
|
|
|
539
560
|
errors.throwNotImplemented("setting end-to-end attribute 'module'");
|
|
540
561
|
}
|
|
541
562
|
|
|
563
|
+
//---------------------------------------------------------------------------
|
|
564
|
+
// setEndUserSecurityContext()
|
|
565
|
+
//
|
|
566
|
+
// Sets the End Security Context.
|
|
567
|
+
//---------------------------------------------------------------------------
|
|
568
|
+
setEndUserSecurityContext() {
|
|
569
|
+
errors.throwNotImplemented("setting End User Security Context");
|
|
570
|
+
}
|
|
571
|
+
|
|
572
|
+
//---------------------------------------------------------------------------
|
|
573
|
+
// clearEndUserSecurityContext()
|
|
574
|
+
//
|
|
575
|
+
// Clears the End Security Context.
|
|
576
|
+
//---------------------------------------------------------------------------
|
|
577
|
+
clearEndUserSecurityContext() {
|
|
578
|
+
errors.throwNotImplemented("clearing End User Security Context");
|
|
579
|
+
}
|
|
580
|
+
|
|
542
581
|
//---------------------------------------------------------------------------
|
|
543
582
|
// setTag()
|
|
544
583
|
//
|
|
@@ -638,6 +677,14 @@ class ConnectionImpl {
|
|
|
638
677
|
errors.throwNotImplemented("unsubscribing from events");
|
|
639
678
|
}
|
|
640
679
|
|
|
680
|
+
// supportsPipelining()
|
|
681
|
+
//
|
|
682
|
+
// Returns true if pipelining is supported.
|
|
683
|
+
//---------------------------------------------------------------------------
|
|
684
|
+
supportsPipelining() {
|
|
685
|
+
return false;
|
|
686
|
+
}
|
|
687
|
+
|
|
641
688
|
//---------------------------------------------------------------------------
|
|
642
689
|
// getHostName()
|
|
643
690
|
//
|
|
@@ -665,6 +712,33 @@ class ConnectionImpl {
|
|
|
665
712
|
errors.throwNotImplemented("getting Protocol");
|
|
666
713
|
}
|
|
667
714
|
|
|
715
|
+
//---------------------------------------------------------------------------
|
|
716
|
+
// directPathLoad()
|
|
717
|
+
//
|
|
718
|
+
// Performs a direct path load into the specified table.
|
|
719
|
+
//---------------------------------------------------------------------------
|
|
720
|
+
directPathLoad() {
|
|
721
|
+
errors.throwNotImplemented("direct path load");
|
|
722
|
+
}
|
|
723
|
+
|
|
724
|
+
//---------------------------------------------------------------------------
|
|
725
|
+
// appContext()
|
|
726
|
+
//
|
|
727
|
+
// Add Application Context, keyValues identified by name, namespaceName.
|
|
728
|
+
//---------------------------------------------------------------------------
|
|
729
|
+
appContext() {
|
|
730
|
+
errors.throwNotImplemented("setting app context");
|
|
731
|
+
}
|
|
732
|
+
|
|
733
|
+
//---------------------------------------------------------------------------
|
|
734
|
+
// clearAppContext()
|
|
735
|
+
//
|
|
736
|
+
// Clears the Application Context, keyValues identified by name.
|
|
737
|
+
//---------------------------------------------------------------------------
|
|
738
|
+
clearAppContext() {
|
|
739
|
+
errors.throwNotImplemented("clear app context");
|
|
740
|
+
}
|
|
741
|
+
|
|
668
742
|
}
|
|
669
743
|
|
|
670
744
|
// export just the class
|
|
@@ -372,12 +372,23 @@ class BaseBuffer {
|
|
|
372
372
|
//
|
|
373
373
|
// Reads a boolean value from the buffer and returns a Boolean.
|
|
374
374
|
//---------------------------------------------------------------------------
|
|
375
|
-
readBool() {
|
|
375
|
+
readBool(fromDBObject) {
|
|
376
376
|
const buf = this.readBytesWithLength();
|
|
377
377
|
if (!buf) {
|
|
378
378
|
return null;
|
|
379
379
|
}
|
|
380
|
-
|
|
380
|
+
if (fromDBObject) {
|
|
381
|
+
// inside a database object, the boolean is represented as a
|
|
382
|
+
// big endian 32-bit integer (either 0 or 1)
|
|
383
|
+
return (buf[buf.length - 1] === 1);
|
|
384
|
+
} else {
|
|
385
|
+
// outside a database object, the boolean is represented as an
|
|
386
|
+
// encoded integer (0x00 for false and 0x0101 for true); older
|
|
387
|
+
// versions like 12.1 also return 0x8101 (-1) for null values
|
|
388
|
+
// but this can safely be ignored as the null indicator is sent
|
|
389
|
+
// as a separate field afterwards.
|
|
390
|
+
return (buf[0] === 1);
|
|
391
|
+
}
|
|
381
392
|
}
|
|
382
393
|
|
|
383
394
|
//---------------------------------------------------------------------------
|
|
@@ -920,7 +931,7 @@ class BaseBuffer {
|
|
|
920
931
|
//
|
|
921
932
|
// Writes the number (in string form) in Oracle Number format to the buffer.
|
|
922
933
|
//---------------------------------------------------------------------------
|
|
923
|
-
writeOracleNumber(value) {
|
|
934
|
+
writeOracleNumber(value, writeLength = true) {
|
|
924
935
|
|
|
925
936
|
// determine if number is negative
|
|
926
937
|
let isNegative = false;
|
|
@@ -984,8 +995,11 @@ class BaseBuffer {
|
|
|
984
995
|
} else if (value.length === 0 && exponent === 0) {
|
|
985
996
|
exponentOnWire = 128;
|
|
986
997
|
}
|
|
987
|
-
let pos = this.reserveBytes(numPairs +
|
|
988
|
-
|
|
998
|
+
let pos = this.reserveBytes(numPairs + 1 + writeLength + appendSentinel);
|
|
999
|
+
|
|
1000
|
+
if (writeLength) {
|
|
1001
|
+
this.buf[pos++] = numPairs + 1 + appendSentinel;
|
|
1002
|
+
}
|
|
989
1003
|
this.buf[pos++] = exponentOnWire;
|
|
990
1004
|
for (let i = 0; i < value.length; i += 2) {
|
|
991
1005
|
const base100Digit = Number(value.substring(i, i + 2));
|
|
@@ -37,6 +37,21 @@ const types = require("../../types.js");
|
|
|
37
37
|
*/
|
|
38
38
|
class VectorDecoder extends BaseBuffer {
|
|
39
39
|
|
|
40
|
+
//---------------------------------------------------------------------------
|
|
41
|
+
// _verifyVectorDataSize()
|
|
42
|
+
//
|
|
43
|
+
// Verifies that the VECTOR image contains enough bytes for the declared
|
|
44
|
+
// element count before allocating a typed array.
|
|
45
|
+
//---------------------------------------------------------------------------
|
|
46
|
+
_verifyVectorDataSize(numElements, elementSize) {
|
|
47
|
+
const numBytes = numElements * elementSize;
|
|
48
|
+
const numBytesLeft = this.numBytesLeft();
|
|
49
|
+
if (numBytes > numBytesLeft) {
|
|
50
|
+
errors.throwErr(errors.ERR_UNEXPECTED_END_OF_DATA, numBytes,
|
|
51
|
+
numBytesLeft);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
54
|
+
|
|
40
55
|
//---------------------------------------------------------------------------
|
|
41
56
|
// decode()
|
|
42
57
|
//
|
|
@@ -56,7 +71,7 @@ class VectorDecoder extends BaseBuffer {
|
|
|
56
71
|
const flags = this.readUInt16BE();
|
|
57
72
|
const vectorFormat = this.readUInt8();
|
|
58
73
|
let numElements = this.readUInt32BE();
|
|
59
|
-
let
|
|
74
|
+
let arrayType, elementSize, sparseValue;
|
|
60
75
|
|
|
61
76
|
// For binary vector, NORM will never be present but space for NORM is reserved to keep
|
|
62
77
|
// same header lengh across the different vector formats.
|
|
@@ -69,6 +84,7 @@ class VectorDecoder extends BaseBuffer {
|
|
|
69
84
|
sparseValue = {};
|
|
70
85
|
sparseValue.numDimensions = numElements; // vector dimensions.
|
|
71
86
|
numElements = this.readUInt16BE(); // actual elements.
|
|
87
|
+
this._verifyVectorDataSize(numElements, 4);
|
|
72
88
|
sparseValue.indices = new Uint32Array(numElements);
|
|
73
89
|
for (let i = 0; i < numElements; i++) {
|
|
74
90
|
sparseValue.indices[i] = this.readUInt32BE();
|
|
@@ -76,22 +92,26 @@ class VectorDecoder extends BaseBuffer {
|
|
|
76
92
|
}
|
|
77
93
|
|
|
78
94
|
if (vectorFormat === constants.VECTOR_FORMAT_FLOAT32) {
|
|
95
|
+
arrayType = Float32Array;
|
|
79
96
|
elementSize = 4;
|
|
80
|
-
value = new Float32Array(numElements);
|
|
81
97
|
} else if (vectorFormat === constants.VECTOR_FORMAT_FLOAT64) {
|
|
98
|
+
arrayType = Float64Array;
|
|
82
99
|
elementSize = 8;
|
|
83
|
-
value = new Float64Array(numElements);
|
|
84
100
|
} else if (vectorFormat === constants.VECTOR_FORMAT_INT8) {
|
|
101
|
+
arrayType = Int8Array;
|
|
85
102
|
elementSize = 1;
|
|
86
|
-
value = new Int8Array(numElements);
|
|
87
103
|
} else if (vectorFormat === constants.VECTOR_FORMAT_BINARY) {
|
|
104
|
+
arrayType = Uint8Array;
|
|
88
105
|
elementSize = 1;
|
|
89
106
|
// The number of dimensions are assumed to be multiple of 8.
|
|
107
|
+
if (numElements % 8 !== 0)
|
|
108
|
+
errors.throwErr(errors.ERR_UNEXPECTED_DATA, numElements);
|
|
90
109
|
numElements = numElements / 8;
|
|
91
|
-
value = new Uint8Array(numElements);
|
|
92
110
|
} else {
|
|
93
111
|
errors.throwErr(errors.ERR_VECTOR_FORMAT_NOT_SUPPORTED, vectorFormat);
|
|
94
112
|
}
|
|
113
|
+
this._verifyVectorDataSize(numElements, elementSize);
|
|
114
|
+
const value = new arrayType(numElements);
|
|
95
115
|
|
|
96
116
|
if (sparseFormat) {
|
|
97
117
|
sparseValue.values = value;
|
package/lib/impl/lob.js
CHANGED
|
@@ -81,6 +81,15 @@ class LobImpl extends BaseImpl {
|
|
|
81
81
|
errors.throwNotImplemented("getting directory and filename of LOB(BFILE)");
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
+
//---------------------------------------------------------------------------
|
|
85
|
+
// trim()
|
|
86
|
+
//
|
|
87
|
+
// trims non-BFILE LOBs to a smaller size.
|
|
88
|
+
//----------------------------------------------------------------------------
|
|
89
|
+
trim() {
|
|
90
|
+
errors.throwNotImplemented("trimming LOBs");
|
|
91
|
+
}
|
|
92
|
+
|
|
84
93
|
//---------------------------------------------------------------------------
|
|
85
94
|
// read()
|
|
86
95
|
//
|