oracle thick mode support #843

This commit is contained in:
Jan Prochazka
2024-07-31 11:20:31 +02:00
parent faf6339b41
commit 5e68ce3218
11 changed files with 75 additions and 39 deletions

View File

@@ -8,6 +8,7 @@
"electron-log": "^4.4.1", "electron-log": "^4.4.1",
"electron-updater": "^4.6.1", "electron-updater": "^4.6.1",
"lodash.clonedeepwith": "^4.5.0", "lodash.clonedeepwith": "^4.5.0",
"oracledb": "^6.6.0",
"patch-package": "^6.4.7" "patch-package": "^6.4.7"
}, },
"repository": { "repository": {

View File

@@ -1944,6 +1944,11 @@ open@^7.4.2:
is-docker "^2.0.0" is-docker "^2.0.0"
is-wsl "^2.1.1" is-wsl "^2.1.1"
oracledb@^6.6.0:
version "6.6.0"
resolved "https://registry.yarnpkg.com/oracledb/-/oracledb-6.6.0.tgz#bb40adbe81a84a1e544c48af9f120c61f030e936"
integrity sha512-T3dx+o3j+tVN53wQyr4yGTmoPHLy+a2V8yb1T2PmWrsj3ZlSt2Yu1BgV2yTDqnmBZYpRi/I3yJXRCOHHD7PiyA==
os-tmpdir@~1.0.2: os-tmpdir@~1.0.2:
version "1.0.2" version "1.0.2"
resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274" resolved "https://registry.yarnpkg.com/os-tmpdir/-/os-tmpdir-1.0.2.tgz#bbe67406c79aa85c5cfec766fe5734555dfa1274"

View File

@@ -3,9 +3,10 @@ const fs = require('fs');
let fillContent = ''; let fillContent = '';
if (process.platform == 'win32') { if (process.platform == 'win32') {
fillContent += `content.msnodesqlv8 = () => require('msnodesqlv8');`; fillContent += `content.msnodesqlv8 = () => require('msnodesqlv8');\n`;
} }
fillContent += `content['better-sqlite3'] = () => require('better-sqlite3');`; fillContent += `content['better-sqlite3'] = () => require('better-sqlite3');\n`;
fillContent += `content['oracledb'] = () => require('oracledb');\n`;
const getContent = empty => ` const getContent = empty => `
// this file is generated automatically by script fillNativeModules.js, do not edit it manually // this file is generated automatically by script fillNativeModules.js, do not edit it manually

View File

@@ -52,6 +52,7 @@
"ncp": "^2.0.0", "ncp": "^2.0.0",
"node-cron": "^2.0.3", "node-cron": "^2.0.3",
"on-finished": "^2.4.1", "on-finished": "^2.4.1",
"oracledb": "^6.6.0",
"pinomin": "^1.0.4", "pinomin": "^1.0.4",
"portfinder": "^1.0.28", "portfinder": "^1.0.28",
"rimraf": "^3.0.0", "rimraf": "^3.0.0",

View File

@@ -93,6 +93,14 @@
/> />
{/if} {/if}
{#if driver?.showConnectionField('clientLibraryPath', $values)}
<FormTextField
label="Client library path"
name="clientLibraryPath"
disabled={isConnected}
/>
{/if}
{#if driver?.showConnectionField('server', $values)} {#if driver?.showConnectionField('server', $values)}
<div class="row"> <div class="row">
<div class="col-9 mr-1"> <div class="col-9 mr-1">

View File

@@ -36,8 +36,5 @@
"lodash": "^4.17.21", "lodash": "^4.17.21",
"webpack": "^5.91.0", "webpack": "^5.91.0",
"webpack-cli": "^5.1.4" "webpack-cli": "^5.1.4"
},
"dependencies": {
"oracledb": "^6.5.1"
} }
} }

View File

@@ -1,13 +1,22 @@
const _ = require('lodash'); const _ = require('lodash');
const stream = require('stream'); const stream = require('stream');
const driverBases = require('../frontend/drivers'); const driverBase = require('../frontend/driver');
const Analyser = require('./Analyser'); const Analyser = require('./Analyser');
//--const pg = require('pg');
const oracledb = require('oracledb');
const { createBulkInsertStreamBase, makeUniqueColumnNames } = require('dbgate-tools'); const { createBulkInsertStreamBase, makeUniqueColumnNames } = require('dbgate-tools');
const createOracleBulkInsertStream = require('./createOracleBulkInsertStream'); const createOracleBulkInsertStream = require('./createOracleBulkInsertStream');
let requireOracledb;
let oracledbValue;
function getOracledb() {
if (!oracledbValue) {
oracledbValue = requireOracledb();
}
return oracledbValue;
}
/* /*
pg.types.setTypeParser(1082, 'text', val => val); // date pg.types.setTypeParser(1082, 'text', val => val); // date
pg.types.setTypeParser(1114, 'text', val => val); // timestamp without timezone pg.types.setTypeParser(1114, 'text', val => val); // timestamp without timezone
@@ -33,8 +42,10 @@ function zipDataRow(rowArray, columns) {
return obj; return obj;
} }
let oracleClientInitialized = false;
/** @type {import('dbgate-types').EngineDriver} */ /** @type {import('dbgate-types').EngineDriver} */
const drivers = driverBases.map(driverBase => ({ const driver = {
...driverBase, ...driverBase,
analyserClass: Analyser, analyserClass: Analyser,
@@ -51,8 +62,14 @@ const drivers = driverBases.map(driverBase => ({
ssl, ssl,
isReadOnly, isReadOnly,
authType, authType,
clientLibraryPath,
socketPath, socketPath,
}) { }) {
const oracledb = getOracledb();
if (authType == 'thick' && !oracleClientInitialized) {
oracledb.initOracleClient({ libDir: clientLibraryPath });
oracleClientInitialized = true;
}
client = await oracledb.getConnection({ client = await oracledb.getConnection({
user, user,
password, password,
@@ -312,15 +329,21 @@ const drivers = driverBases.map(driverBase => ({
getAuthTypes() { getAuthTypes() {
return [ return [
{ {
title: 'Host and port', title: 'Thin mode (default) - direct connection to Oracle database',
name: 'hostPort', name: 'thin',
}, },
{ {
title: 'Socket', title: 'Thick mode - connection via Oracle instant client',
name: 'socket', name: 'thick',
}, },
]; ];
}, },
})); };
module.exports = drivers; driver.initialize = (dbgateEnv) => {
if (dbgateEnv.nativeModules && dbgateEnv.nativeModules['oracledb']) {
requireOracledb = dbgateEnv.nativeModules['oracledb'];
}
};
module.exports = driver;

View File

@@ -1,6 +1,9 @@
const drivers = require('./drivers'); const driver = require('./driver');
module.exports = { module.exports = {
packageName: 'dbgate-plugin-oracle', packageName: 'dbgate-plugin-oracle',
drivers, drivers: [driver],
initialize(dbgateEnv) {
driver.initialize(dbgateEnv);
},
}; };

View File

@@ -82,10 +82,15 @@ const dialect = {
}, },
}; };
const oracleDriverBase = { /** @type {import('dbgate-types').EngineDriver} */
...driverBase, const oracleDriver = {
dumperClass: Dumper, engine: 'oracle@dbgate-plugin-oracle',
title: 'OracleDB',
defaultPort: 1521,
authTypeLabel: 'Driver mode',
defaultAuthTypeName: 'thin',
dialect, dialect,
dumperClass: Dumper,
// showConnectionField: (field, values) => // showConnectionField: (field, values) =>
// ['server', 'port', 'user', 'password', 'defaultDatabase', 'singleDatabase'].includes(field), // ['server', 'port', 'user', 'password', 'defaultDatabase', 'singleDatabase'].includes(field),
getQuerySplitterOptions: () => oracleSplitterOptions, getQuerySplitterOptions: () => oracleSplitterOptions,
@@ -93,8 +98,12 @@ const oracleDriverBase = {
databaseUrlPlaceholder: 'e.g. localhost:1521/orcl', databaseUrlPlaceholder: 'e.g. localhost:1521/orcl',
showConnectionField: (field, values) => { showConnectionField: (field, values) => {
if (field == 'useDatabaseUrl') return true; if (field == 'useDatabaseUrl') return true;
if (field == 'authType') return true;
if (field == 'clientLibraryPath') return values.authType == 'thick';
if (values.useDatabaseUrl) { if (values.useDatabaseUrl) {
return ['databaseUrl', 'user', 'password'].includes(field); return ['databaseUrl', 'user', 'password'].includes(field);
} }
@@ -126,18 +135,6 @@ $$ LANGUAGE plpgsql;`,
}, },
]; ];
}, },
};
/** @type {import('dbgate-types').EngineDriver} */
const oracleDriver = {
...oracleDriverBase,
engine: 'oracle@dbgate-plugin-oracle',
title: 'OracleDB',
defaultPort: 1521,
dialect: {
...dialect,
materializedViews: true,
},
dialectByVersion(version) { dialectByVersion(version) {
if (version) { if (version) {
@@ -156,4 +153,4 @@ const oracleDriver = {
showConnectionTab: field => field == 'sshTunnel', showConnectionTab: field => field == 'sshTunnel',
}; };
module.exports = [oracleDriver]; module.exports = oracleDriver;

View File

@@ -1,6 +1,6 @@
import drivers from './drivers'; import driver from './driver';
export default { export default {
packageName: 'dbgate-plugin-oracle', packageName: 'dbgate-plugin-oracle',
drivers, drivers: [driver],
}; };

View File

@@ -7978,10 +7978,10 @@ optionator@^0.8.1, optionator@^0.8.3:
resolved "https://registry.yarnpkg.com/opts/-/opts-2.0.2.tgz#a17e189fbbfee171da559edd8a42423bc5993ce1" resolved "https://registry.yarnpkg.com/opts/-/opts-2.0.2.tgz#a17e189fbbfee171da559edd8a42423bc5993ce1"
integrity sha512-k41FwbcLnlgnFh69f4qdUfvDQ+5vaSDnVPFI/y5XuhKRq97EnVVneO9F1ESVCdiVu4fCS2L8usX3mU331hB7pg== integrity sha512-k41FwbcLnlgnFh69f4qdUfvDQ+5vaSDnVPFI/y5XuhKRq97EnVVneO9F1ESVCdiVu4fCS2L8usX3mU331hB7pg==
oracledb@^6.5.1: oracledb@^6.6.0:
version "6.5.1" version "6.6.0"
resolved "https://registry.yarnpkg.com/oracledb/-/oracledb-6.5.1.tgz#814d985035acdb1a6470b1152af0ca3767569ede" resolved "https://registry.yarnpkg.com/oracledb/-/oracledb-6.6.0.tgz#bb40adbe81a84a1e544c48af9f120c61f030e936"
integrity sha512-JzoSGei1wnvmqgKnAZK1W650mzHTZXx+7hClV4mwsbY/ZjUtrpnojNJMYJ2jkOhj7XG5oJPfXc4GqDKaNzkxqg== integrity sha512-T3dx+o3j+tVN53wQyr4yGTmoPHLy+a2V8yb1T2PmWrsj3ZlSt2Yu1BgV2yTDqnmBZYpRi/I3yJXRCOHHD7PiyA==
os-tmpdir@~1.0.2: os-tmpdir@~1.0.2:
version "1.0.2" version "1.0.2"