oracledb 6.5.1 → 6.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +2 -2
- package/build/Release/oracledb-6.6.0-darwin-arm64.node +0 -0
- package/build/Release/oracledb-6.6.0-darwin-arm64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.6.0-darwin-x64.node +0 -0
- package/build/Release/oracledb-6.6.0-darwin-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.6.0-js-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.6.0-linux-arm64.node +0 -0
- package/build/Release/oracledb-6.6.0-linux-arm64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.6.0-linux-x64.node +0 -0
- package/build/Release/oracledb-6.6.0-linux-x64.node-buildinfo.txt +1 -0
- package/build/Release/oracledb-6.6.0-win32-x64.node +0 -0
- package/build/Release/oracledb-6.6.0-win32-x64.node-buildinfo.txt +1 -0
- package/examples/README.md +2 -0
- package/lib/configProviders/azure.js +167 -0
- package/lib/configProviders/base.js +99 -0
- package/lib/configProviders/ociobject.js +203 -0
- package/lib/connection.js +28 -12
- package/lib/constants.js +1 -0
- package/lib/errors.js +56 -1
- package/lib/impl/datahandlers/constants.js +3 -1
- package/lib/impl/datahandlers/vector.js +24 -9
- package/lib/impl/lob.js +27 -0
- package/lib/impl/resultset.js +26 -1
- package/lib/lob.js +52 -1
- package/lib/oracledb.js +54 -0
- package/lib/thin/connection.js +232 -16
- package/lib/thin/dbObject.js +4 -0
- package/lib/thin/lob.js +193 -1
- package/lib/thin/pool.js +15 -0
- package/lib/thin/protocol/capabilities.js +2 -0
- package/lib/thin/protocol/constants.js +29 -1
- package/lib/thin/protocol/messages/index.js +5 -1
- package/lib/thin/protocol/messages/lobOp.js +17 -5
- package/lib/thin/protocol/messages/transactionChangeState.js +99 -0
- package/lib/thin/protocol/messages/transactionSwitch.js +139 -0
- package/lib/thin/protocol/messages/withData.js +26 -6
- package/lib/thin/sqlnet/networkSession.js +2 -1
- package/lib/thin/sqlnet/paramParser.js +87 -50
- package/lib/thin/sqlnet/sessionAtts.js +13 -1
- package/lib/transformer.js +1 -2
- package/lib/types.js +1 -1
- package/lib/util.js +34 -2
- package/lib/version.js +2 -2
- package/package.json +1 -1
- package/build/Release/oracledb-6.5.1-darwin-x64.node +0 -0
- package/build/Release/oracledb-6.5.1-darwin-x64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.5.1-js-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.5.1-linux-arm64.node +0 -0
- package/build/Release/oracledb-6.5.1-linux-arm64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.5.1-linux-x64.node +0 -0
- package/build/Release/oracledb-6.5.1-linux-x64.node-buildinfo.txt +0 -1
- package/build/Release/oracledb-6.5.1-win32-x64.node +0 -0
- package/build/Release/oracledb-6.5.1-win32-x64.node-buildinfo.txt +0 -1
package/README.md
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
# node-oracledb version 6.
|
|
1
|
+
# node-oracledb version 6.6.0
|
|
2
2
|
|
|
3
3
|
The node-oracledb add-on for Node.js powers high performance Oracle Database
|
|
4
4
|
applications. Applications can be written in TypeScript, or directly in
|
|
5
5
|
JavaScript.
|
|
6
6
|
|
|
7
|
-
Use node-oracledb 6.
|
|
7
|
+
Use node-oracledb 6.6.0 to connect Node.js 14.6, or later, to Oracle
|
|
8
8
|
Database. Older versions of node-oracledb may work with older versions of
|
|
9
9
|
Node.js.
|
|
10
10
|
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
oracledb-6.6.0-darwin-arm64.node v22.2.0 6e81601d4d09137e859660fbbe090e1b272adbb2 5f182c720d6541c3b267d5d370f606f90b5b0c38 Wed, 17 Jul 2024 06:45:24 GMT
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
oracledb-6.6.0-darwin-x64.node v20.11.1 6e81601d4d09137e859660fbbe090e1b272adbb2 5f182c720d6541c3b267d5d370f606f90b5b0c38 Wed, 17 Jul 2024 04:43:48 GMT
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
6e81601d4d09137e859660fbbe090e1b272adbb2
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
oracledb-6.6.0-linux-arm64.node v20.12.2 6e81601d4d09137e859660fbbe090e1b272adbb2 5f182c720d6541c3b267d5d370f606f90b5b0c38 Wed, 17 Jul 2024 07:10:04 GMT
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
oracledb-6.6.0-linux-x64.node v16.20.2 6e81601d4d09137e859660fbbe090e1b272adbb2 5f182c720d6541c3b267d5d370f606f90b5b0c38 Wed, 17 Jul 2024 07:13:04 GMT
|
|
Binary file
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
oracledb-6.6.0-win32-x64.node v18.16.0 6e81601d4d09137e859660fbbe090e1b272adbb2 5f182c720d6541c3b267d5d370f606f90b5b0c38 Wed, 17 Jul 2024 07:26:50 GMT
|
package/examples/README.md
CHANGED
|
@@ -106,6 +106,7 @@ File Name | Description
|
|
|
106
106
|
[`plsqlproc.js`](plsqlproc.js) | How to call a PL/SQL procedure
|
|
107
107
|
[`plsqlrecord.js`](plsqlrecord.js) | Shows binding of PL/SQL RECORDS
|
|
108
108
|
[`plsqlvarrayrecord.js`](plsqlvarrayrecord.js) | Shows binding a VARRAY of RECORD in PL/SQL
|
|
109
|
+
[`plsqlrowtype.js`](plsqlrowtype.js) | Shows binding of PL/SQL %ROWTYPE object
|
|
109
110
|
[`raw.js`](raw.js) | Shows using a Buffer to insert and select a RAW
|
|
110
111
|
[`refcursor.js`](refcursor.js) | Shows using a ResultSet to fetch rows from a REF CURSOR
|
|
111
112
|
[`refcursortoquerystream.js`](refcursortoquerystream.js) | Converts a REF CURSOR returned from `execute()` to a query stream.
|
|
@@ -134,3 +135,4 @@ File Name | Description
|
|
|
134
135
|
[`vectortype2.js`](vectortype2.js) | Insert data into VECTOR columns and verify vector operations.
|
|
135
136
|
[`version.js`](version.js) | Shows the node-oracledb version attributes
|
|
136
137
|
[`webapp.js`](webapp.js) | A simple web application using a connection pool
|
|
138
|
+
[`xmltypeInDbObject.js`](xmltypeInDbObject.js) | Work with XMLType data in DbObject (Thin mode only)
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
// Copyright (c) 2024, 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
|
+
let AppConfigurationClient;
|
|
30
|
+
let ClientSecretCredential, ClientCertificateCredential, ChainedTokenCredential, ManagedIdentityCredential, EnvironmentCredential;
|
|
31
|
+
const errors = require("../errors.js");
|
|
32
|
+
const { base } = require("./base.js");
|
|
33
|
+
|
|
34
|
+
class AzureProvider extends base {
|
|
35
|
+
constructor(provider_arg, urlExtendedPart) {
|
|
36
|
+
super(urlExtendedPart);
|
|
37
|
+
this._addParam("appconfigname", provider_arg);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
//---------------------------------------------------------------------------
|
|
41
|
+
// init()
|
|
42
|
+
//
|
|
43
|
+
// Require/import modules from azure
|
|
44
|
+
//---------------------------------------------------------------------------
|
|
45
|
+
init() {
|
|
46
|
+
({AppConfigurationClient } = require("@azure/app-configuration"));
|
|
47
|
+
({ClientSecretCredential, ClientCertificateCredential, ChainedTokenCredential, ManagedIdentityCredential, EnvironmentCredential} = require("@azure/identity"));
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
//---------------------------------------------------------------------------
|
|
51
|
+
// _withChainedTokenCredential()
|
|
52
|
+
//
|
|
53
|
+
// Use of ChainedTokenCredential class which provides the ability to link
|
|
54
|
+
// together multiple credential instances to be tried sequentially when authenticating.
|
|
55
|
+
// Default authentication to try when no authentication parameter is given by the user
|
|
56
|
+
//---------------------------------------------------------------------------
|
|
57
|
+
_withChainedTokenCredential() {
|
|
58
|
+
const tokens = [];
|
|
59
|
+
if ((this.paramMap.get("azure_client_secret")))
|
|
60
|
+
tokens.push(new ClientSecretCredential(this.paramMap.get("azure_tenant_id"), this.paramMap.get("azure_client_id"), this.paramMap.get("azure_client_secret")));
|
|
61
|
+
if ((this.paramMap.get("azure_client_certificate_path")))
|
|
62
|
+
tokens.push(new ClientCertificateCredential(this.paramMap.get("azure_tenant_id"), this.paramMap.get("azure_client_id"), this.paramMap.get("azure_client_certificate_path")));
|
|
63
|
+
if ((this.paramMap.get('azure_managed_identity_client_id')))
|
|
64
|
+
tokens.push(this.paramMap.get('azure_managed_identity_client_id'));
|
|
65
|
+
tokens.push(new EnvironmentCredential());
|
|
66
|
+
const credential = new ChainedTokenCredential(...tokens);
|
|
67
|
+
return credential;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
//---------------------------------------------------------------------------
|
|
71
|
+
// _returnCredential()
|
|
72
|
+
//
|
|
73
|
+
// Returns credential to access Azure Config Store on the basis of
|
|
74
|
+
// authentication parameters given by the user.
|
|
75
|
+
//---------------------------------------------------------------------------
|
|
76
|
+
_returnCredential() {
|
|
77
|
+
let auth = null;
|
|
78
|
+
if (this.paramMap.get('authentication')) {
|
|
79
|
+
auth = this.paramMap.get('authentication').toUpperCase();
|
|
80
|
+
}
|
|
81
|
+
if (auth && !(auth == 'AZURE_DEFAULT')) {
|
|
82
|
+
// do the given authentication
|
|
83
|
+
if (auth == 'AZURE_SERVICE_PRINCIPAL') {
|
|
84
|
+
if (this.paramMap.get("azure_client_certificate_path"))
|
|
85
|
+
return new ClientCertificateCredential(this.paramMap.get("azure_tenant_id"), this.paramMap.get("azure_client_id"), this.paramMap.get("azure_client_certificate_path"));
|
|
86
|
+
else if (this.paramMap.get("azure_client_secret"))
|
|
87
|
+
return new ClientSecretCredential(this.paramMap.get("azure_tenant_id"), this.paramMap.get("azure_client_id"), this.paramMap.get("azure_client_secret"));
|
|
88
|
+
else
|
|
89
|
+
errors.throwErr(errors.ERR_AZURE_SERVICE_PRINCIPAL_AUTH_FAILED);
|
|
90
|
+
} else if (auth == 'AZURE_MANAGED_IDENTITY') {
|
|
91
|
+
return new ManagedIdentityCredential(this.paramMap.get('azure_managed_identity_client_id'));
|
|
92
|
+
} else {
|
|
93
|
+
errors.throwErr(errors.ERR_AZURE_CONFIG_PROVIDER_AUTH_FAILED, auth);
|
|
94
|
+
}
|
|
95
|
+
} else {
|
|
96
|
+
//return default token credential
|
|
97
|
+
return this._withChainedTokenCredential();
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
//---------------------------------------------------------------------------
|
|
102
|
+
// _getConfigurationSetting()
|
|
103
|
+
//
|
|
104
|
+
// Get configuration setting from the config provider given a key
|
|
105
|
+
//and an optional label
|
|
106
|
+
//---------------------------------------------------------------------------
|
|
107
|
+
async _getConfigurationSetting(client, key, label) {
|
|
108
|
+
return await client.getConfigurationSetting({ key: key, label: label });
|
|
109
|
+
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
async returnConfig() {
|
|
113
|
+
const configObject = {};
|
|
114
|
+
const label = this.paramMap.get("label");
|
|
115
|
+
const credential = this._returnCredential();
|
|
116
|
+
// azure config store
|
|
117
|
+
const client = new AppConfigurationClient(
|
|
118
|
+
"https://" + this.paramMap.get("appconfigname"), // ex: <https://<your appconfig resource>.azconfig.io>
|
|
119
|
+
credential
|
|
120
|
+
);
|
|
121
|
+
// retrieve connect_description
|
|
122
|
+
configObject.connectString = (await this._getConfigurationSetting(client, this.paramMap.get("key") + 'connect_descriptor', label)).value;
|
|
123
|
+
|
|
124
|
+
// retrieve node-oracledb parameters
|
|
125
|
+
try {
|
|
126
|
+
const params = (await this._getConfigurationSetting(client, this.paramMap.get("key") + 'node-oracledb', label)).value;
|
|
127
|
+
const obj = JSON.parse(params);
|
|
128
|
+
for (const key in obj) {
|
|
129
|
+
var val = obj[key];
|
|
130
|
+
configObject[key] = val;
|
|
131
|
+
}
|
|
132
|
+
} catch {
|
|
133
|
+
configObject['node-oracledb'] = null;
|
|
134
|
+
}
|
|
135
|
+
try {
|
|
136
|
+
// retrieve user
|
|
137
|
+
configObject.user = (await this._getConfigurationSetting(client, this.paramMap.get("key") + 'user', label)).value;
|
|
138
|
+
} catch {
|
|
139
|
+
configObject.user = null;
|
|
140
|
+
}
|
|
141
|
+
//retrieve password
|
|
142
|
+
let pwdJson = null;
|
|
143
|
+
try {
|
|
144
|
+
pwdJson = await this._getConfigurationSetting(client, this.paramMap.get("key") + 'password', label);
|
|
145
|
+
} catch {
|
|
146
|
+
configObject.password = null;
|
|
147
|
+
}
|
|
148
|
+
if (pwdJson) {
|
|
149
|
+
let obj;
|
|
150
|
+
try {
|
|
151
|
+
obj = JSON.parse(pwdJson.value);
|
|
152
|
+
} catch {
|
|
153
|
+
obj = pwdJson.value;
|
|
154
|
+
}
|
|
155
|
+
if (obj.uri) {
|
|
156
|
+
const { SecretClient } = require("@azure/keyvault-secrets");
|
|
157
|
+
const vault_detail = await this._parsePwd(obj.uri);
|
|
158
|
+
const client1 = new SecretClient(vault_detail[0], credential);
|
|
159
|
+
configObject.password = (await client1.getSecret(vault_detail[1])).value;
|
|
160
|
+
} else {
|
|
161
|
+
configObject.password = pwdJson.value;
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return configObject;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
module.exports = AzureProvider;
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// Copyright (c) 2024, 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
|
+
class base {
|
|
30
|
+
constructor(url) {
|
|
31
|
+
const params = new URLSearchParams(url);
|
|
32
|
+
this.paramMap = new URLSearchParams([...params].map(([key, value]) => [key.toLowerCase(), value])); //parse the extended part and store parameters in Map
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/**
|
|
36
|
+
* Sets precedence for different parameters in cloudConfig/userConfig
|
|
37
|
+
* @param {cloudConfig} object - object retreived from cloud
|
|
38
|
+
* @param {userConfig} object - user input Object
|
|
39
|
+
*/
|
|
40
|
+
modifyOptionsPrecedence(cloudConfig, userConfig) {
|
|
41
|
+
// create a copy of userConfig object
|
|
42
|
+
userConfig = { ...userConfig };
|
|
43
|
+
if (!userConfig.user)
|
|
44
|
+
userConfig.user = cloudConfig.user;
|
|
45
|
+
if (!userConfig.password)
|
|
46
|
+
userConfig.password = cloudConfig.password;
|
|
47
|
+
if (cloudConfig.connectString) {
|
|
48
|
+
userConfig.connectString = cloudConfig.connectString;
|
|
49
|
+
userConfig.connectionString = undefined;
|
|
50
|
+
}
|
|
51
|
+
if (cloudConfig.poolMin)
|
|
52
|
+
userConfig.poolMin = cloudConfig.poolMin;
|
|
53
|
+
if (cloudConfig.poolMax)
|
|
54
|
+
userConfig.poolMax = cloudConfig.poolMax;
|
|
55
|
+
if (cloudConfig.poolIncrement)
|
|
56
|
+
userConfig.poolIncrement = cloudConfig.poolIncrement;
|
|
57
|
+
if (cloudConfig.poolTimeout)
|
|
58
|
+
userConfig.poolTimeout = cloudConfig.poolTimeout;
|
|
59
|
+
if (cloudConfig.poolPingInterval)
|
|
60
|
+
userConfig.poolPingInterval = cloudConfig.poolPingInterval;
|
|
61
|
+
if (cloudConfig.poolPingTimeout)
|
|
62
|
+
userConfig.poolPingTimeout = cloudConfig.poolPingTimeout;
|
|
63
|
+
if (cloudConfig.stmtCacheSize)
|
|
64
|
+
userConfig.stmtCacheSize = cloudConfig.stmtCacheSize;
|
|
65
|
+
if (cloudConfig.prefetchRows)
|
|
66
|
+
userConfig.prefetchRows = cloudConfig.prefetchRows;
|
|
67
|
+
if (cloudConfig.lobPrefetch)
|
|
68
|
+
userConfig.lobPrefetch = cloudConfig.lobPrefetch;
|
|
69
|
+
|
|
70
|
+
return userConfig;
|
|
71
|
+
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
//---------------------------------------------------------------------------
|
|
75
|
+
// _addParam()
|
|
76
|
+
// Adds key,value pairs to the Map
|
|
77
|
+
//---------------------------------------------------------------------------
|
|
78
|
+
_addParam(key, value) {
|
|
79
|
+
const aliasKeyName = key.toLowerCase();
|
|
80
|
+
this.paramMap.set(aliasKeyName, value);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
//---------------------------------------------------------------------------
|
|
84
|
+
// _parsePwd()
|
|
85
|
+
// Parse password which is in url format
|
|
86
|
+
// “uri”:“https://mykeyvault.vault.azure.net/secrets/secretkey”}
|
|
87
|
+
//---------------------------------------------------------------------------
|
|
88
|
+
_parsePwd(str) {
|
|
89
|
+
const vault_uri = new RegExp("(?<vault_url>https://[A-Za-z0-9._-]+)/secrets/(?<secretKey>[A-Za-z][A-Za-z0-9-]*)$", 'g');
|
|
90
|
+
const vault_detail = [];
|
|
91
|
+
for (const match of str.matchAll(vault_uri)) {
|
|
92
|
+
vault_detail[0] = match.groups.vault_url;
|
|
93
|
+
vault_detail[1] = match.groups.secretKey;
|
|
94
|
+
}
|
|
95
|
+
return vault_detail;
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
}
|
|
99
|
+
module.exports = {base};
|
|
@@ -0,0 +1,203 @@
|
|
|
1
|
+
// Copyright (c) 2024, 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
|
+
const errors = require("../errors.js");
|
|
29
|
+
const { base } = require("./base.js");
|
|
30
|
+
const fs = require('fs');
|
|
31
|
+
|
|
32
|
+
const cloud_net_naming_pattern_oci = new RegExp("(?<objservername>[A-Za-z0-9._-]+)/n/" + "(?<namespace>[A-Za-z0-9._-]+)/b/" + "(?<bucketname>[A-Za-z0-9._-]+)/o/" + "(?<filename>[A-Za-z0-9._-]+)" + "(/c/(?<alias>.+))?$");
|
|
33
|
+
// object to store module references that will be populated by init()
|
|
34
|
+
const oci = {};
|
|
35
|
+
|
|
36
|
+
class OCIProvider extends base {
|
|
37
|
+
constructor(provider_arg, urlExtendedPart) {
|
|
38
|
+
super(urlExtendedPart);
|
|
39
|
+
const match = provider_arg.match(cloud_net_naming_pattern_oci);
|
|
40
|
+
if (match) {
|
|
41
|
+
this._addParam("objservername", match.groups.objservername);
|
|
42
|
+
this._addParam("namespace", match.groups.namespace);
|
|
43
|
+
this._addParam("bucketname", match.groups.bucketname);
|
|
44
|
+
this._addParam("filename", match.groups.filename);
|
|
45
|
+
if (match.groups.alias)
|
|
46
|
+
this._addParam("alias", match.groups.alias);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
//---------------------------------------------------------------------------
|
|
51
|
+
// init()
|
|
52
|
+
//
|
|
53
|
+
// Require/import modules from ociobject
|
|
54
|
+
//---------------------------------------------------------------------------
|
|
55
|
+
init() {
|
|
56
|
+
oci.common = require('oci-common');
|
|
57
|
+
oci.objectstorage = require('oci-objectstorage');
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
//---------------------------------------------------------------------------
|
|
61
|
+
// _streamToString()
|
|
62
|
+
//
|
|
63
|
+
// Converts data stored in a Readable stream to string
|
|
64
|
+
//---------------------------------------------------------------------------
|
|
65
|
+
async _streamToString(stream) {
|
|
66
|
+
const chunks = [];
|
|
67
|
+
for await (const chunk of stream) {
|
|
68
|
+
chunks.push(Buffer.from(chunk));
|
|
69
|
+
}
|
|
70
|
+
return Buffer.concat(chunks).toString("utf-8");
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
//---------------------------------------------------------------------------
|
|
74
|
+
// _returnCredential()
|
|
75
|
+
//
|
|
76
|
+
// Returns credential to access OCI Object Store on the basis of
|
|
77
|
+
// authentication parameters given by the user.
|
|
78
|
+
//---------------------------------------------------------------------------
|
|
79
|
+
async _returnCredential() {
|
|
80
|
+
let provider = null;
|
|
81
|
+
let auth = null;
|
|
82
|
+
if (this.paramMap.get('authentication')) {
|
|
83
|
+
auth = this.paramMap.get('authentication').toUpperCase();
|
|
84
|
+
}
|
|
85
|
+
// authentication parameter given and its not OCI_DEFAULT
|
|
86
|
+
if (auth && !(auth == 'OCI_DEFAULT')) {
|
|
87
|
+
if (auth == 'OCI_INSTANCE_PRINCIPAL') {
|
|
88
|
+
provider = await new oci.common.InstancePrincipalsAuthenticationDetailsProviderBuilder().build();
|
|
89
|
+
} else if (auth == 'OCI_RESOURCE_PRINCIPAL') {
|
|
90
|
+
provider = await new oci.common.ResourcePrincipalAuthenticationDetailsProvider.builder();
|
|
91
|
+
} else
|
|
92
|
+
errors.throwErr(errors.ERR_OCIOBJECT_CONFIG_PROVIDER_AUTH_FAILED, auth);
|
|
93
|
+
} else {
|
|
94
|
+
// default authentication
|
|
95
|
+
try {
|
|
96
|
+
//authentication parameters exist in the configurationFile
|
|
97
|
+
provider = new oci.common.ConfigFileAuthenticationDetailsProvider(
|
|
98
|
+
this.paramMap.get("oci_profile_path"), //default path ~/.oci/config
|
|
99
|
+
this.paramMap.get("oci_profile")
|
|
100
|
+
);
|
|
101
|
+
} catch (err) {
|
|
102
|
+
//throw error for wrong profile or wrong path
|
|
103
|
+
if (!this.paramMap.get("oci_tenancy") || !this.paramMap.get("oci_user")) {
|
|
104
|
+
throw (err);
|
|
105
|
+
}
|
|
106
|
+
// authentication parameters are directly given in the connectString
|
|
107
|
+
const publicKey = fs.readFileSync(this.paramMap.get('oci_key_file'), { encoding: "utf8" });
|
|
108
|
+
const region = this.retrieveRegion(this.paramMap.get('objservername'));
|
|
109
|
+
provider = new oci.common.SimpleAuthenticationDetailsProvider(
|
|
110
|
+
this.paramMap.get("oci_tenancy"),
|
|
111
|
+
this.paramMap.get("oci_user"),
|
|
112
|
+
this.paramMap.get("oci_fingerprint"),
|
|
113
|
+
publicKey,
|
|
114
|
+
undefined,
|
|
115
|
+
oci.common.Region[region]
|
|
116
|
+
);
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
return provider;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
//---------------------------------------------------------------------------
|
|
123
|
+
// returnConfig()
|
|
124
|
+
//
|
|
125
|
+
// Returns config stored in the OCI Object Store and
|
|
126
|
+
// parses and gets password field stored in OCI/Azure Vault
|
|
127
|
+
//---------------------------------------------------------------------------
|
|
128
|
+
async returnConfig() {
|
|
129
|
+
const configObject = {};
|
|
130
|
+
const credential = await this._returnCredential();
|
|
131
|
+
// oci object store
|
|
132
|
+
const client_oci = new (oci.objectstorage).ObjectStorageClient({
|
|
133
|
+
authenticationDetailsProvider: credential
|
|
134
|
+
});
|
|
135
|
+
const getObjectRequest = {
|
|
136
|
+
objectName: this.paramMap.get('filename'),
|
|
137
|
+
bucketName: this.paramMap.get('bucketname'),
|
|
138
|
+
namespaceName: this.paramMap.get('namespace')
|
|
139
|
+
};
|
|
140
|
+
let credential1;
|
|
141
|
+
const getObjectResponse = await client_oci.getObject(getObjectRequest);
|
|
142
|
+
const resp = await this._streamToString(getObjectResponse.value);
|
|
143
|
+
// Entire object we get from OCI Object Storage
|
|
144
|
+
let obj = JSON.parse(resp);
|
|
145
|
+
const userAlias = this.paramMap.get('alias');
|
|
146
|
+
if (userAlias) {
|
|
147
|
+
obj = obj[userAlias];
|
|
148
|
+
}
|
|
149
|
+
const pmSection = 'node-oracledb';
|
|
150
|
+
const params = obj[pmSection];
|
|
151
|
+
for (const key in params) {
|
|
152
|
+
var val = params[key];
|
|
153
|
+
configObject[key] = val;
|
|
154
|
+
}
|
|
155
|
+
configObject.connectString = obj.connect_descriptor;
|
|
156
|
+
configObject.user = obj.user;
|
|
157
|
+
if (obj.password) {
|
|
158
|
+
if (obj.password.type == "vault-azure") {
|
|
159
|
+
if (obj.password.authentication) {
|
|
160
|
+
const { SecretClient } = require("@azure/keyvault-secrets");
|
|
161
|
+
const {ClientSecretCredential, ClientCertificateCredential} = require("@azure/identity");
|
|
162
|
+
if (obj.password.authentication.azure_client_secret)
|
|
163
|
+
credential1 = new ClientSecretCredential(obj.password.authentication.azure_tenant_id, obj.password.authentication.azure_client_id, obj.password.authentication.azure_client_secret);
|
|
164
|
+
else if (obj.password.authentication.azure_client_certificate_path)
|
|
165
|
+
credential1 = new ClientCertificateCredential(obj.password.authentication.azure_tenant_id, obj.password.authentication.azure_client_id, obj.password.authentication.azure_client_certificate_path);
|
|
166
|
+
else
|
|
167
|
+
errors.throwErr(errors.ERR_AZURE_VAULT_AUTH_FAILED);
|
|
168
|
+
const vault_detail = await this._parsePwd(obj.password.value);
|
|
169
|
+
const client1 = new SecretClient(vault_detail[0], credential1);
|
|
170
|
+
configObject.password = (await client1.getSecret(vault_detail[1])).value;
|
|
171
|
+
} else {
|
|
172
|
+
errors.throwErr(errors.ERR_AZURE_VAULT_AUTH_FAILED);
|
|
173
|
+
}
|
|
174
|
+
} else if (obj.password.type == "vault-oci") {
|
|
175
|
+
const secrets = require('oci-secrets');
|
|
176
|
+
const secretClientOci = new secrets.SecretsClient({
|
|
177
|
+
authenticationDetailsProvider: credential
|
|
178
|
+
});
|
|
179
|
+
const getSecretBundleRequest = {
|
|
180
|
+
secretId: obj.password.value
|
|
181
|
+
};
|
|
182
|
+
const getSecretBundleResponse = await secretClientOci.getSecretBundle(getSecretBundleRequest);
|
|
183
|
+
configObject.password = getSecretBundleResponse.secretBundle.secretBundleContent.content;
|
|
184
|
+
} else if (obj.password) {
|
|
185
|
+
configObject.password = obj.password;
|
|
186
|
+
}
|
|
187
|
+
} else {
|
|
188
|
+
configObject.password = null;
|
|
189
|
+
}
|
|
190
|
+
return configObject;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
//---------------------------------------------------------------------------
|
|
194
|
+
// retrieveRegion(objservername)
|
|
195
|
+
//
|
|
196
|
+
// returns region from the given objservername.
|
|
197
|
+
//---------------------------------------------------------------------------
|
|
198
|
+
retrieveRegion(objservername) {
|
|
199
|
+
const arr = objservername.split(".");
|
|
200
|
+
return arr[1].toUpperCase().replaceAll('-', '_');
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
module.exports = OCIProvider;
|
package/lib/connection.js
CHANGED
|
@@ -202,9 +202,7 @@ class Connection extends EventEmitter {
|
|
|
202
202
|
typeof value === 'boolean' ||
|
|
203
203
|
typeof value === 'bigint' ||
|
|
204
204
|
Array.isArray(value) ||
|
|
205
|
-
value
|
|
206
|
-
value instanceof Float64Array ||
|
|
207
|
-
value instanceof Int8Array ||
|
|
205
|
+
nodbUtil.isVectorValue(value) ||
|
|
208
206
|
Buffer.isBuffer(value) ||
|
|
209
207
|
util.types.isDate(value) ||
|
|
210
208
|
value instanceof Lob ||
|
|
@@ -1412,7 +1410,7 @@ class Connection extends EventEmitter {
|
|
|
1412
1410
|
async tpcBegin(xid, flag, timeout) {
|
|
1413
1411
|
errors.assertArgCount(arguments, 1, 3);
|
|
1414
1412
|
errors.assertParamValue(nodbUtil.isXid(xid), 1);
|
|
1415
|
-
|
|
1413
|
+
const normalizedXid = nodbUtil.normalizeXid(xid);
|
|
1416
1414
|
if (arguments.length < 3) {
|
|
1417
1415
|
timeout = 60; // seconds
|
|
1418
1416
|
} else {
|
|
@@ -1423,9 +1421,14 @@ class Connection extends EventEmitter {
|
|
|
1423
1421
|
flag = constants.TPC_BEGIN_NEW;
|
|
1424
1422
|
} else {
|
|
1425
1423
|
errors.assertParamValue(typeof flag === 'number', 2);
|
|
1424
|
+
const options = [constants.TPC_BEGIN_NEW, constants.TPC_BEGIN_JOIN,
|
|
1425
|
+
constants.TPC_BEGIN_RESUME, constants.TPC_BEGIN_PROMOTE];
|
|
1426
|
+
if (options.indexOf(flag) < 0) {
|
|
1427
|
+
errors.throwErr(errors.ERR_INVALID_TPC_BEGIN_FLAGS);
|
|
1428
|
+
}
|
|
1426
1429
|
}
|
|
1427
1430
|
errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
|
|
1428
|
-
await this._impl.tpcBegin(
|
|
1431
|
+
await this._impl.tpcBegin(normalizedXid, flag, timeout);
|
|
1429
1432
|
}
|
|
1430
1433
|
|
|
1431
1434
|
//---------------------------------------------------------------------------
|
|
@@ -1441,11 +1444,13 @@ class Connection extends EventEmitter {
|
|
|
1441
1444
|
} else {
|
|
1442
1445
|
errors.assertParamValue(typeof onePhase === 'boolean', 2);
|
|
1443
1446
|
}
|
|
1447
|
+
let normalizedXid;
|
|
1444
1448
|
if (arguments.length >= 1) {
|
|
1445
1449
|
errors.assertParamValue(nodbUtil.isXid(xid), 1);
|
|
1450
|
+
normalizedXid = nodbUtil.normalizeXid(xid);
|
|
1446
1451
|
}
|
|
1447
1452
|
errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
|
|
1448
|
-
await this._impl.tpcCommit(
|
|
1453
|
+
await this._impl.tpcCommit(normalizedXid, onePhase);
|
|
1449
1454
|
}
|
|
1450
1455
|
|
|
1451
1456
|
//---------------------------------------------------------------------------
|
|
@@ -1460,14 +1465,19 @@ class Connection extends EventEmitter {
|
|
|
1460
1465
|
flag = constants.TPC_END_NORMAL;
|
|
1461
1466
|
} else {
|
|
1462
1467
|
errors.assertParamValue(typeof flag === 'number', 2);
|
|
1468
|
+
const options = [constants.TPC_END_NORMAL, constants.TPC_END_SUSPEND];
|
|
1469
|
+
if (!options.includes(flag)) {
|
|
1470
|
+
errors.throwErr(errors.ERR_INVALID_TPC_END_FLAGS);
|
|
1471
|
+
}
|
|
1463
1472
|
}
|
|
1464
|
-
|
|
1473
|
+
let normalizedXid;
|
|
1465
1474
|
if (arguments.length >= 1) {
|
|
1466
1475
|
errors.assertParamValue(nodbUtil.isXid(xid), 1);
|
|
1476
|
+
normalizedXid = nodbUtil.normalizeXid(xid);
|
|
1467
1477
|
}
|
|
1468
1478
|
errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
|
|
1469
1479
|
|
|
1470
|
-
await this._impl.tpcEnd(
|
|
1480
|
+
await this._impl.tpcEnd(normalizedXid, flag);
|
|
1471
1481
|
}
|
|
1472
1482
|
|
|
1473
1483
|
//---------------------------------------------------------------------------
|
|
@@ -1479,9 +1489,10 @@ class Connection extends EventEmitter {
|
|
|
1479
1489
|
async tpcForget(xid) {
|
|
1480
1490
|
errors.assertArgCount(arguments, 1, 1);
|
|
1481
1491
|
errors.assertParamValue(nodbUtil.isXid(xid), 1);
|
|
1492
|
+
const normalizedXid = nodbUtil.normalizeXid(xid);
|
|
1482
1493
|
errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
|
|
1483
1494
|
|
|
1484
|
-
await this._impl.tpcForget(
|
|
1495
|
+
await this._impl.tpcForget(normalizedXid);
|
|
1485
1496
|
}
|
|
1486
1497
|
|
|
1487
1498
|
//---------------------------------------------------------------------------
|
|
@@ -1491,12 +1502,14 @@ class Connection extends EventEmitter {
|
|
|
1491
1502
|
//---------------------------------------------------------------------------
|
|
1492
1503
|
async tpcPrepare(xid) {
|
|
1493
1504
|
errors.assertArgCount(arguments, 0, 1);
|
|
1505
|
+
let normalizedXid;
|
|
1494
1506
|
if (arguments.length >= 1) {
|
|
1495
1507
|
errors.assertParamValue(nodbUtil.isXid(xid), 1);
|
|
1508
|
+
normalizedXid = nodbUtil.normalizeXid(xid);
|
|
1496
1509
|
}
|
|
1497
1510
|
errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
|
|
1498
1511
|
|
|
1499
|
-
return await this._impl.tpcPrepare(
|
|
1512
|
+
return await this._impl.tpcPrepare(normalizedXid);
|
|
1500
1513
|
}
|
|
1501
1514
|
|
|
1502
1515
|
//---------------------------------------------------------------------------
|
|
@@ -1541,12 +1554,14 @@ class Connection extends EventEmitter {
|
|
|
1541
1554
|
//---------------------------------------------------------------------------
|
|
1542
1555
|
async tpcRollback(xid) {
|
|
1543
1556
|
errors.assertArgCount(arguments, 0, 1);
|
|
1557
|
+
let normalizedXid;
|
|
1544
1558
|
if (arguments.length == 1) {
|
|
1545
1559
|
errors.assertParamValue(nodbUtil.isXid(xid), 1);
|
|
1560
|
+
normalizedXid = nodbUtil.normalizeXid(xid);
|
|
1546
1561
|
}
|
|
1547
1562
|
errors.assert(this._impl, errors.ERR_INVALID_CONNECTION);
|
|
1548
1563
|
|
|
1549
|
-
await this._impl.tpcRollback(
|
|
1564
|
+
await this._impl.tpcRollback(normalizedXid);
|
|
1550
1565
|
}
|
|
1551
1566
|
|
|
1552
1567
|
//---------------------------------------------------------------------------
|
|
@@ -1570,6 +1585,8 @@ class Connection extends EventEmitter {
|
|
|
1570
1585
|
// NOTE: breakExecution() should not be serialized
|
|
1571
1586
|
Connection.prototype.break =
|
|
1572
1587
|
nodbUtil.callbackify(Connection.prototype.breakExecution);
|
|
1588
|
+
Connection.prototype.tpcRecover =
|
|
1589
|
+
nodbUtil.callbackify(Connection.prototype.tpcRecover);
|
|
1573
1590
|
nodbUtil.wrapFns(Connection.prototype,
|
|
1574
1591
|
"changePassword",
|
|
1575
1592
|
"close",
|
|
@@ -1590,7 +1607,6 @@ nodbUtil.wrapFns(Connection.prototype,
|
|
|
1590
1607
|
"tpcEnd",
|
|
1591
1608
|
"tpcForget",
|
|
1592
1609
|
"tpcPrepare",
|
|
1593
|
-
"tpcRecover",
|
|
1594
1610
|
"tpcRollback",
|
|
1595
1611
|
"unsubscribe");
|
|
1596
1612
|
|