get version result and login from oracle

This commit is contained in:
Rinie Kervel 2022-09-26 17:54:24 +02:00
parent 1535dfd407
commit 4939b74179
36 changed files with 1508 additions and 0 deletions

View File

@ -0,0 +1,21 @@
MIT License
Copyright (c) 2021 Jan Prochazka
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -0,0 +1,10 @@
[![styled with prettier](https://img.shields.io/badge/styled_with-prettier-ff69b4.svg)](https://github.com/prettier/prettier)
[![NPM version](https://img.shields.io/npm/v/dbgate-plugin-oracle.svg)](https://www.npmjs.com/package/dbgate-plugin-oracle)
# dbgate-plugin-oracle
Use DbGate for install of this plugin
set NODE_OPTIONS=--openssl-legacy-provider
Map pg.client and pg.query to oracledb

View File

@ -0,0 +1,22 @@
<?xml version="1.0"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN"
"http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg width="432.071pt" height="445.383pt" viewBox="0 0 432.071 445.383" xml:space="preserve" xmlns="http://www.w3.org/2000/svg">
<g id="orginal" style="fill-rule:nonzero;clip-rule:nonzero;stroke:#000000;stroke-miterlimit:4;">
</g>
<g id="Layer_x0020_3" style="fill-rule:nonzero;clip-rule:nonzero;fill:none;stroke:#FFFFFF;stroke-width:12.4651;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;">
<path style="fill:#000000;stroke:#000000;stroke-width:37.3953;stroke-linecap:butt;stroke-linejoin:miter;" d="M323.205,324.227c2.833-23.601,1.984-27.062,19.563-23.239l4.463,0.392c13.517,0.615,31.199-2.174,41.587-7c22.362-10.376,35.622-27.7,13.572-23.148c-50.297,10.376-53.755-6.655-53.755-6.655c53.111-78.803,75.313-178.836,56.149-203.322 C352.514-5.534,262.036,26.049,260.522,26.869l-0.482,0.089c-9.938-2.062-21.06-3.294-33.554-3.496c-22.761-0.374-40.032,5.967-53.133,15.904c0,0-161.408-66.498-153.899,83.628c1.597,31.936,45.777,241.655,98.47,178.31 c19.259-23.163,37.871-42.748,37.871-42.748c9.242,6.14,20.307,9.272,31.912,8.147l0.897-0.765c-0.281,2.876-0.157,5.689,0.359,9.019c-13.572,15.167-9.584,17.83-36.723,23.416c-27.457,5.659-11.326,15.734-0.797,18.367c12.768,3.193,42.305,7.716,62.268-20.224 l-0.795,3.188c5.325,4.26,4.965,30.619,5.72,49.452c0.756,18.834,2.017,36.409,5.856,46.771c3.839,10.36,8.369,37.05,44.036,29.406c29.809-6.388,52.6-15.582,54.677-101.107"/>
<path style="fill:#336791;stroke:none;" d="M402.395,271.23c-50.302,10.376-53.76-6.655-53.76-6.655c53.111-78.808,75.313-178.843,56.153-203.326c-52.27-66.785-142.752-35.2-144.262-34.38l-0.486,0.087c-9.938-2.063-21.06-3.292-33.56-3.496c-22.761-0.373-40.026,5.967-53.127,15.902 c0,0-161.411-66.495-153.904,83.63c1.597,31.938,45.776,241.657,98.471,178.312c19.26-23.163,37.869-42.748,37.869-42.748c9.243,6.14,20.308,9.272,31.908,8.147l0.901-0.765c-0.28,2.876-0.152,5.689,0.361,9.019c-13.575,15.167-9.586,17.83-36.723,23.416 c-27.459,5.659-11.328,15.734-0.796,18.367c12.768,3.193,42.307,7.716,62.266-20.224l-0.796,3.188c5.319,4.26,9.054,27.711,8.428,48.969c-0.626,21.259-1.044,35.854,3.147,47.254c4.191,11.4,8.368,37.05,44.042,29.406c29.809-6.388,45.256-22.942,47.405-50.555 c1.525-19.631,4.976-16.729,5.194-34.28l2.768-8.309c3.192-26.611,0.507-35.196,18.872-31.203l4.463,0.392c13.517,0.615,31.208-2.174,41.591-7c22.358-10.376,35.618-27.7,13.573-23.148z"/>
<path d="M215.866,286.484c-1.385,49.516,0.348,99.377,5.193,111.495c4.848,12.118,15.223,35.688,50.9,28.045c29.806-6.39,40.651-18.756,45.357-46.051c3.466-20.082,10.148-75.854,11.005-87.281"/>
<path d="M173.104,38.256c0,0-161.521-66.016-154.012,84.109c1.597,31.938,45.779,241.664,98.473,178.316c19.256-23.166,36.671-41.335,36.671-41.335"/>
<path d="M260.349,26.207c-5.591,1.753,89.848-34.889,144.087,34.417c19.159,24.484-3.043,124.519-56.153,203.329"/>
<path style="stroke-linejoin:bevel;" d="M348.282,263.953c0,0,3.461,17.036,53.764,6.653c22.04-4.552,8.776,12.774-13.577,23.155c-18.345,8.514-59.474,10.696-60.146-1.069c-1.729-30.355,21.647-21.133,19.96-28.739c-1.525-6.85-11.979-13.573-18.894-30.338 c-6.037-14.633-82.796-126.849,21.287-110.183c3.813-0.789-27.146-99.002-124.553-100.599c-97.385-1.597-94.19,119.762-94.19,119.762"/>
<path d="M188.604,274.334c-13.577,15.166-9.584,17.829-36.723,23.417c-27.459,5.66-11.326,15.733-0.797,18.365c12.768,3.195,42.307,7.718,62.266-20.229c6.078-8.509-0.036-22.086-8.385-25.547c-4.034-1.671-9.428-3.765-16.361,3.994z"/>
<path d="M187.715,274.069c-1.368-8.917,2.93-19.528,7.536-31.942c6.922-18.626,22.893-37.255,10.117-96.339c-9.523-44.029-73.396-9.163-73.436-3.193c-0.039,5.968,2.889,30.26-1.067,58.548c-5.162,36.913,23.488,68.132,56.479,64.938"/>
<path style="fill:#FFFFFF;stroke-width:4.155;stroke-linecap:butt;stroke-linejoin:miter;" d="M172.517,141.7c-0.288,2.039,3.733,7.48,8.976,8.207c5.234,0.73,9.714-3.522,9.998-5.559c0.284-2.039-3.732-4.285-8.977-5.015c-5.237-0.731-9.719,0.333-9.996,2.367z"/>
<path style="fill:#FFFFFF;stroke-width:2.0775;stroke-linecap:butt;stroke-linejoin:miter;" d="M331.941,137.543c0.284,2.039-3.732,7.48-8.976,8.207c-5.238,0.73-9.718-3.522-10.005-5.559c-0.277-2.039,3.74-4.285,8.979-5.015c5.239-0.73,9.718,0.333,10.002,2.368z"/>
<path d="M350.676,123.432c0.863,15.994-3.445,26.888-3.988,43.914c-0.804,24.748,11.799,53.074-7.191,81.435"/>
<path style="stroke-width:3;" d="M0,60.232"/>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.3 KiB

View File

@ -0,0 +1,41 @@
{
"name": "dbgate-plugin-oracle",
"main": "dist/backend.js",
"version": "5.0.0-alpha.1",
"license": "MIT",
"description": "Oracle connector plugin for DbGate",
"homepage": "https://dbgate.org",
"repository": {
"type": "git",
"url": "https://github.com/dbgate/dbgate"
},
"author": "Rinie Kervel",
"keywords": [
"dbgate",
"dbgateplugin",
"oracle"
],
"files": [
"dist",
"icon.svg"
],
"scripts": {
"build:frontend": "webpack --config webpack-frontend.config",
"build:frontend:watch": "webpack --watch --config webpack-frontend.config",
"build:backend": "webpack --config webpack-backend.config.js",
"build": "yarn build:frontend && yarn build:backend",
"plugin": "yarn build && yarn pack && dbgate-plugin dbgate-plugin-oracle",
"copydist": "yarn build && yarn pack && dbgate-copydist ../dist/dbgate-plugin-oracle",
"plugout": "dbgate-plugout dbgate-plugin-oracle",
"prepublishOnly": "yarn build"
},
"devDependencies": {
"dbgate-plugin-tools": "^1.0.7",
"dbgate-query-splitter": "^4.9.0",
"dbgate-tools": "^5.0.0-alpha.1",
"lodash": "^4.17.21",
"oracledb": "^5.0.0",
"webpack": "^4.42.0",
"webpack-cli": "^3.3.11"
}
}

View File

@ -0,0 +1,9 @@
module.exports = {
trailingComma: 'es5',
tabWidth: 2,
semi: true,
singleQuote: true,
arrowParen: 'avoid',
arrowParens: 'avoid',
printWidth: 120,
};

View File

@ -0,0 +1,353 @@
const fp = require('lodash/fp');
const _ = require('lodash');
const sql = require('./sql');
const { DatabaseAnalyser } = require('dbgate-tools');
const { isTypeString, isTypeNumeric } = require('dbgate-tools');
function normalizeTypeName(dataType) {
if (dataType == 'character varying') return 'varchar';
if (dataType == 'timestamp without time zone') return 'timestamp';
return dataType;
}
function getColumnInfo(
{ is_nullable, column_name, data_type, char_max_length, numeric_precision, numeric_ccale, default_value },
table = undefined,
geometryColumns = undefined,
geographyColumns = undefined
) {
const normDataType = normalizeTypeName(data_type);
let fullDataType = normDataType;
if (char_max_length && isTypeString(normDataType)) fullDataType = `${normDataType}(${char_max_length})`;
if (numeric_precision && numeric_ccale && isTypeNumeric(normDataType))
fullDataType = `${normDataType}(${numeric_precision},${numeric_ccale})`;
const autoIncrement = !!(default_value && default_value.startsWith('nextval('));
if (
table &&
geometryColumns &&
geometryColumns.rows.find(
x => x.schema_name == table.schemaName && x.pure_name == table.pureName && x.column_name == column_name
)
) {
fullDataType = 'geometry';
}
if (
table &&
geographyColumns &&
geographyColumns.rows.find(
x => x.schema_name == table.schemaName && x.pure_name == table.pureName && x.column_name == column_name
)
) {
fullDataType = 'geography';
}
return {
columnName: column_name,
dataType: fullDataType,
notNull: !is_nullable || is_nullable == 'NO' || is_nullable == 'no',
defaultValue: autoIncrement ? undefined : default_value,
autoIncrement,
};
}
class Analyser extends DatabaseAnalyser {
constructor(pool, driver, version) {
super(pool, driver, version);
}
createQuery(resFileName, typeFields) {
const query = super.createQuery(sql[resFileName], typeFields);
if (query) return query.replace('#REFTABLECOND#', this.driver.__analyserInternals.refTableCond);
return null;
}
async _computeSingleObjectId() {
const { typeField, schemaName, pureName } = this.singleObjectFilter;
this.singleObjectId = `${typeField}:${schemaName || 'public'}.${pureName}`;
}
async _runAnalysis() {
this.feedback({ analysingMessage: 'Loading tables' });
const tables = await this.driver.query(
this.pool,
this.createQuery(this.driver.dialect.stringAgg ? 'tableModifications' : 'tableList', ['tables'])
);
this.feedback({ analysingMessage: 'Loading columns' });
const columns = await this.driver.query(this.pool, this.createQuery('columns', ['tables', 'views']));
this.feedback({ analysingMessage: 'Loading primary keys' });
const pkColumns = await this.driver.query(this.pool, this.createQuery('primaryKeys', ['tables']));
let fkColumns = null;
// if (true) {
if (this.containsObjectIdCondition(['tables']) || this.driver.__analyserInternals.refTableCond) {
this.feedback({ analysingMessage: 'Loading foreign keys' });
fkColumns = await this.driver.query(this.pool, this.createQuery('foreignKeys', ['tables']));
} else {
this.feedback({ analysingMessage: 'Loading foreign key constraints' });
const fk_tableConstraints = await this.driver.query(
this.pool,
this.createQuery('fk_tableConstraints', ['tables'])
);
this.feedback({ analysingMessage: 'Loading foreign key refs' });
const fk_referentialConstraints = await this.driver.query(
this.pool,
this.createQuery('fk_referentialConstraints', ['tables'])
);
this.feedback({ analysingMessage: 'Loading foreign key columns' });
const fk_keyColumnUsage = await this.driver.query(this.pool, this.createQuery('fk_keyColumnUsage', ['tables']));
const cntKey = x => `${x.constraint_name}|${x.constraint_schema}`;
const rows = [];
const constraintDct = _.keyBy(fk_tableConstraints.rows, cntKey);
for (const fkRef of fk_referentialConstraints.rows) {
const cntBase = constraintDct[cntKey(fkRef)];
const cntRef = constraintDct[`${fkRef.unique_constraint_name}|${fkRef.unique_constraint_schema}`];
if (!cntBase || !cntRef) continue;
const baseCols = _.sortBy(
fk_keyColumnUsage.rows.filter(
x => x.table_name == cntBase.table_name && x.constraint_name == cntBase.constraint_name
),
'ordinal_position'
);
const refCols = _.sortBy(
fk_keyColumnUsage.rows.filter(
x => x.table_name == cntRef.table_name && x.constraint_name == cntRef.constraint_name
),
'ordinal_position'
);
if (baseCols.length != refCols.length) continue;
for (let i = 0; i < baseCols.length; i++) {
const baseCol = baseCols[i];
const refCol = refCols[i];
rows.push({
...fkRef,
pure_name: cntBase.table_name,
schema_name: cntBase.table_schema,
ref_table_name: cntRef.table_name,
ref_schema_name: cntRef.table_schema,
column_name: baseCol.column_name,
ref_column_name: refCol.column_name,
});
}
}
fkColumns = { rows };
}
this.feedback({ analysingMessage: 'Loading views' });
const views = await this.driver.query(this.pool, this.createQuery('views', ['views']));
this.feedback({ analysingMessage: 'Loading materialized views' });
const matviews = this.driver.dialect.materializedViews
? await this.driver.query(this.pool, this.createQuery('matviews', ['matviews']))
: null;
this.feedback({ analysingMessage: 'Loading materialized view columns' });
const matviewColumns = this.driver.dialect.materializedViews
? await this.driver.query(this.pool, this.createQuery('matviewColumns', ['matviews']))
: null;
this.feedback({ analysingMessage: 'Loading routines' });
const routines = await this.driver.query(this.pool, this.createQuery('routines', ['procedures', 'functions']));
this.feedback({ analysingMessage: 'Loading indexes' });
const indexes = this.driver.__analyserInternals.skipIndexes
? { rows: [] }
: await this.driver.query(this.pool, this.createQuery('indexes', ['tables']));
this.feedback({ analysingMessage: 'Loading index columns' });
const indexcols = this.driver.__analyserInternals.skipIndexes
? { rows: [] }
: await this.driver.query(this.pool, this.createQuery('indexcols', ['tables']));
this.feedback({ analysingMessage: 'Loading unique names' });
const uniqueNames = await this.driver.query(this.pool, this.createQuery('uniqueNames', ['tables']));
let geometryColumns = { rows: [] };
if (views.rows.find(x => x.pure_name == 'geometry_columns' && x.schema_name == 'public')) {
this.feedback({ analysingMessage: 'Loading geometry columns' });
geometryColumns = await this.safeQuery(this.createQuery('geometryColumns', ['tables']));
}
let geographyColumns = { rows: [] };
if (views.rows.find(x => x.pure_name == 'geography_columns' && x.schema_name == 'public')) {
this.feedback({ analysingMessage: 'Loading geography columns' });
geographyColumns = await this.safeQuery(this.createQuery('geographyColumns', ['tables']));
}
this.feedback({ analysingMessage: 'Finalizing DB structure' });
const columnColumnsMapped = fkColumns.rows.map(x => ({
pureName: x.pure_name,
schemaName: x.schema_name,
constraintSchema: x.constraint_schema,
constraintName: x.constraint_name,
columnName: x.column_name,
refColumnName: x.ref_column_name,
updateAction: x.update_action,
deleteAction: x.delete_action,
refTableName: x.ref_table_name,
refSchemaName: x.ref_schema_name,
}));
const pkColumnsMapped = pkColumns.rows.map(x => ({
pureName: x.pure_name,
schemaName: x.schema_name,
constraintSchema: x.constraint_schema,
constraintName: x.constraint_name,
columnName: x.column_name,
}));
const res = {
tables: tables.rows.map(table => {
const newTable = {
pureName: table.pure_name,
schemaName: table.schema_name,
objectId: `tables:${table.schema_name}.${table.pure_name}`,
contentHash: table.hash_code_columns ? `${table.hash_code_columns}-${table.hash_code_constraints}` : null,
};
return {
...newTable,
columns: columns.rows
.filter(col => col.pure_name == table.pure_name && col.schema_name == table.schema_name)
.map(col => getColumnInfo(col, newTable, geometryColumns, geographyColumns)),
primaryKey: DatabaseAnalyser.extractPrimaryKeys(newTable, pkColumnsMapped),
foreignKeys: DatabaseAnalyser.extractForeignKeys(newTable, columnColumnsMapped),
indexes: indexes.rows
.filter(
x =>
x.table_name == table.pure_name &&
x.schema_name == table.schema_name &&
!uniqueNames.rows.find(y => y.constraint_name == x.index_name)
)
.map(idx => ({
constraintName: idx.index_name,
isUnique: idx.is_unique,
columns: _.compact(
idx.indkey
.split(' ')
.map(colid => indexcols.rows.find(col => col.oid == idx.oid && col.attnum == colid))
.filter(col => col != null)
.map(col => ({
columnName: col.column_name,
}))
),
})),
uniques: indexes.rows
.filter(
x =>
x.table_name == table.pure_name &&
x.schema_name == table.schema_name &&
uniqueNames.rows.find(y => y.constraint_name == x.index_name)
)
.map(idx => ({
constraintName: idx.index_name,
columns: _.compact(
idx.indkey
.split(' ')
.map(colid => indexcols.rows.find(col => col.oid == idx.oid && col.attnum == colid))
.filter(col => col != null)
.map(col => ({
columnName: col.column_name,
}))
),
})),
};
}),
views: views.rows.map(view => ({
objectId: `views:${view.schema_name}.${view.pure_name}`,
pureName: view.pure_name,
schemaName: view.schema_name,
contentHash: view.hash_code,
createSql: `CREATE VIEW "${view.schema_name}"."${view.pure_name}"\nAS\n${view.create_sql}`,
columns: columns.rows
.filter(col => col.pure_name == view.pure_name && col.schema_name == view.schema_name)
.map(col => getColumnInfo(col)),
})),
matviews: matviews
? matviews.rows.map(matview => ({
objectId: `matviews:${matview.schema_name}.${matview.pure_name}`,
pureName: matview.pure_name,
schemaName: matview.schema_name,
contentHash: matview.hash_code,
createSql: `CREATE MATERIALIZED VIEW "${matview.schema_name}"."${matview.pure_name}"\nAS\n${matview.definition}`,
columns: matviewColumns.rows
.filter(col => col.pure_name == matview.pure_name && col.schema_name == matview.schema_name)
.map(col => getColumnInfo(col)),
}))
: undefined,
procedures: routines.rows
.filter(x => x.object_type == 'PROCEDURE')
.map(proc => ({
objectId: `procedures:${proc.schema_name}.${proc.pure_name}`,
pureName: proc.pure_name,
schemaName: proc.schema_name,
createSql: `CREATE PROCEDURE "${proc.schema_name}"."${proc.pure_name}"() LANGUAGE ${proc.language}\nAS\n$$\n${proc.definition}\n$$`,
contentHash: proc.hash_code,
})),
functions: routines.rows
.filter(x => x.object_type == 'FUNCTION')
.map(func => ({
objectId: `functions:${func.schema_name}.${func.pure_name}`,
createSql: `CREATE FUNCTION "${func.schema_name}"."${func.pure_name}"() RETURNS ${func.data_type} LANGUAGE ${func.language}\nAS\n$$\n${func.definition}\n$$`,
pureName: func.pure_name,
schemaName: func.schema_name,
contentHash: func.hash_code,
})),
};
this.feedback({ analysingMessage: null });
return res;
}
async _getFastSnapshot() {
const tableModificationsQueryData = this.driver.dialect.stringAgg
? await this.driver.query(this.pool, this.createQuery('tableModifications'))
: null;
const viewModificationsQueryData = await this.driver.query(this.pool, this.createQuery('viewModifications'));
const matviewModificationsQueryData = this.driver.dialect.materializedViews
? await this.driver.query(this.pool, this.createQuery('matviewModifications'))
: null;
const routineModificationsQueryData = await this.driver.query(this.pool, this.createQuery('routineModifications'));
return {
tables: tableModificationsQueryData
? tableModificationsQueryData.rows.map(x => ({
objectId: `tables:${x.schema_name}.${x.pure_name}`,
pureName: x.pure_name,
schemaName: x.schema_name,
contentHash: `${x.hash_code_columns}-${x.hash_code_constraints}`,
}))
: null,
views: viewModificationsQueryData.rows.map(x => ({
objectId: `views:${x.schema_name}.${x.pure_name}`,
pureName: x.pure_name,
schemaName: x.schema_name,
contentHash: x.hash_code,
})),
matviews: matviewModificationsQueryData
? matviewModificationsQueryData.rows.map(x => ({
objectId: `matviews:${x.schema_name}.${x.pure_name}`,
pureName: x.pure_name,
schemaName: x.schema_name,
contentHash: x.hash_code,
}))
: undefined,
procedures: routineModificationsQueryData.rows
.filter(x => x.object_type == 'PROCEDURE')
.map(x => ({
objectId: `procedures:${x.schema_name}.${x.pure_name}`,
pureName: x.pure_name,
schemaName: x.schema_name,
contentHash: x.hash_code,
})),
functions: routineModificationsQueryData.rows
.filter(x => x.object_type == 'FUNCTION')
.map(x => ({
objectId: `functions:${x.schema_name}.${x.pure_name}`,
pureName: x.pure_name,
schemaName: x.schema_name,
contentHash: x.hash_code,
})),
};
}
}
module.exports = Analyser;

View File

@ -0,0 +1,303 @@
const _ = require('lodash');
const stream = require('stream');
const driverBases = require('../frontend/drivers');
const Analyser = require('./Analyser');
//--const pg = require('pg');
const oracledb = require('oracledb');
const { createBulkInsertStreamBase, makeUniqueColumnNames } = require('dbgate-tools');
/*
pg.types.setTypeParser(1082, 'text', val => val); // date
pg.types.setTypeParser(1114, 'text', val => val); // timestamp without timezone
pg.types.setTypeParser(1184, 'text', val => val); // timestamp
*/
function extractOracleColumns(result) {
console.log('result', result);
console.log('result.name', result[0].name);
console.log('result.map', result.map(fld => ({
columnName: fld.name.toLowerCase(),
})));
if (!result /*|| !result.fields */) return [];
const res = result.map(fld => ({
columnName: fld.name.toLowerCase(),
}));
makeUniqueColumnNames(res);
return res;
}
function zipDataRow(rowArray, columns) {
return _.zipObject(
columns.map(x => x.columnName),
rowArray
);
}
/** @type {import('dbgate-types').EngineDriver} */
const drivers = driverBases.map(driverBase => ({
...driverBase,
analyserClass: Analyser,
async connect({
engine,
server,
port,
user,
password,
database,
databaseUrl,
useDatabaseUrl,
ssl,
isReadOnly,
authType,
socketPath,
}) {
let options = null;
if (engine == 'redshift@dbgate-plugin-oracle') {
let url = databaseUrl;
if (url && url.startsWith('jdbc:redshift://')) {
url = url.substring('jdbc:redshift://'.length);
}
if (user && password) {
url = `oracle://${user}:${password}@${url}`;
} else if (user) {
url = `oracle://${user}@${url}`;
} else {
url = `oracle://${url}`;
}
options = {
connectionString: url,
};
} else {
options = useDatabaseUrl
? {
connectionString: databaseUrl,
}
: {
host: authType == 'socket' ? socketPath || driverBase.defaultSocketPath : server,
port: authType == 'socket' ? null : port,
user,
password,
database: database || 'oracle',
ssl,
};
}
console.log('OPTIONS', options);
/*
const client = new pg.Client(options);
await client.connect();
if (isReadOnly) {
await this.query(client, 'SET SESSION CHARACTERISTICS AS TRANSACTION READ ONLY');
}
*/
client = await oracledb.getConnection( {
user : options.user,
password : options.password,
connectString : options.host
});
return client;
},
async close(pool) {
return pool.end();
},
async query(client, sql) {
if (sql == null) {
return {
rows: [],
columns: [],
};
}
console.log('sql', sql);
const res = await client.execute(sql);
console.log('res', res);
const columns = extractOracleColumns(res.metaData);
console.log('columns', columns);
return { rows: (res.rows || []).map(row => zipDataRow(row, columns)), columns };
},
stream(client, sql, options) {
/*
const query = new pg.Query({
text: sql,
rowMode: 'array',
});
*/
console.log('queryStream', sql);
const query = client.queryStream(sql);
let wasHeader = false;
query.on('metaData', row => {
console.log('metaData', row);
if (!wasHeader) {
columns = extractOracleColumns(query.metaData);
if (columns && columns.length > 0) {
options.recordset(columns);
}
wasHeader = true;
}
options.row(zipDataRow(row, columns));
});
query.on('data', row => {
console.log('DATA', row);
if (!wasHeader) {
columns = extractOracleColumns(query._result);
if (columns && columns.length > 0) {
options.recordset(columns);
}
wasHeader = true;
}
options.row(zipDataRow(row, columns));
});
query.on('end', () => {
const { command, rowCount } = query._result || {};
if (command != 'SELECT' && _.isNumber(rowCount)) {
options.info({
message: `${rowCount} rows affected`,
time: new Date(),
severity: 'info',
});
}
if (!wasHeader) {
columns = extractOracleColumns(query._result);
if (columns && columns.length > 0) {
options.recordset(columns);
}
wasHeader = true;
}
options.done();
});
query.on('error', error => {
console.log('ERROR', error);
const { message, lineNumber, procName } = error;
options.info({
message,
line: lineNumber,
procedure: procName,
time: new Date(),
severity: 'error',
});
options.done();
});
client.query(query);
},
async getVersion(client) {
//const { rows } = await this.query(client, "SELECT banner as version FROM v$version WHERE banner LIKE 'Oracle%'");
const { rows } = await this.query(client, "SELECT version FROM v$instance");
const { version } = rows[0];
const isCockroach = false; //version.toLowerCase().includes('cockroachdb');
const isRedshift = false; // version.toLowerCase().includes('redshift');
const isOracle = true;
const m = version.match(/([\d\.]+)/);
//console.log('M', m);
let versionText = null;
let versionMajor = null;
let versionMinor = null;
if (m) {
if (isOracle) versionText = `Oracle ${m[1]}`;
const numbers = m[1].split('.');
if (numbers[0]) versionMajor = parseInt(numbers[0]);
if (numbers[1]) versionMinor = parseInt(numbers[1]);
}
return {
version,
versionText,
isOracle,
isCockroach,
isRedshift,
versionMajor,
versionMinor,
};
},
async readQuery(client, sql, structure) {
/*
const query = new pg.Query({
text: sql,
rowMode: 'array',
});
*/
console.log('readQuery', sql, structure);
const query = await client.queryStream(sql);
let wasHeader = false;
let columns = null;
const pass = new stream.PassThrough({
objectMode: true,
highWaterMark: 100,
});
query.on('data', row => {
if (!wasHeader) {
columns = extractOracleColumns(query._result);
pass.write({
__isStreamHeader: true,
...(structure || { columns }),
});
wasHeader = true;
}
pass.write(zipDataRow(row, columns));
});
query.on('end', () => {
if (!wasHeader) {
columns = extractOracleColumns(query._result);
pass.write({
__isStreamHeader: true,
...(structure || { columns }),
});
wasHeader = true;
}
pass.end();
});
query.on('error', error => {
console.error(error);
pass.end();
});
client.query(query);
return pass;
},
async writeTable(pool, name, options) {
// @ts-ignore
return createBulkInsertStreamBase(this, stream, pool, name, options);
},
async listDatabases(client) {
const { rows } = await this.query(client, 'SELECT instance_name AS name FROM v$instance');
return rows;
},
getAuthTypes() {
return [
{
title: 'Host and port',
name: 'hostPort',
},
{
title: 'Socket',
name: 'socket',
},
];
},
}));
module.exports = drivers;

View File

@ -0,0 +1,6 @@
const drivers = require('./drivers');
module.exports = {
packageName: 'dbgate-plugin-oracle',
drivers,
};

View File

@ -0,0 +1,23 @@
module.exports = `
select
table_schema as "schema_name",
table_name as "pure_name",
column_name as "column_name",
is_nullable as "is_nullable",
data_type as "data_type",
character_maximum_length as "char_max_length",
numeric_precision as "numeric_precision",
numeric_scale as "numeric_scale",
column_default as "default_value"
from information_schema.columns
where
table_schema <> 'information_schema'
and table_schema <> 'pg_catalog'
and table_schema !~ '^pg_toast'
and (
('tables:' || table_schema || '.' || table_name) =OBJECT_ID_CONDITION
or
('views:' || table_schema || '.' || table_name) =OBJECT_ID_CONDITION
)
order by ordinal_position
`;

View File

@ -0,0 +1,10 @@
module.exports = `
select
basecol.constraint_name,
basecol.constraint_schema,
basecol.column_name as "column_name",
basecol.table_schema,
basecol.table_name,
basecol.ordinal_position
from information_schema.key_column_usage basecol
`;

View File

@ -0,0 +1,10 @@
module.exports = `
select
fk.constraint_name as "constraint_name",
fk.constraint_schema as "constraint_schema",
fk.update_rule as "update_action",
fk.delete_rule as "delete_action",
fk.unique_constraint_name as "unique_constraint_name",
fk.unique_constraint_schema as "unique_constraint_schema"
from information_schema.referential_constraints fk
`;

View File

@ -0,0 +1,8 @@
module.exports = `
select
base.table_name as "table_name",
base.table_schema as "table_schema",
base.constraint_name as "constraint_name",
base.constraint_schema as "constraint_schema"
from information_schema.table_constraints base
`;

View File

@ -0,0 +1,24 @@
module.exports = `
select
fk.constraint_name as "constraint_name",
fk.constraint_schema as "constraint_schema",
base.table_name as "pure_name",
base.table_schema as "schema_name",
fk.update_rule as "update_action",
fk.delete_rule as "delete_action",
ref.table_name as "ref_table_name",
ref.table_schema as "ref_schema_name",
basecol.column_name as "column_name",
refcol.column_name as "ref_column_name"
from information_schema.referential_constraints fk
inner join information_schema.table_constraints base on fk.constraint_name = base.constraint_name and fk.constraint_schema = base.constraint_schema
inner join information_schema.table_constraints ref on fk.unique_constraint_name = ref.constraint_name and fk.unique_constraint_schema = ref.constraint_schema #REFTABLECOND#
inner join information_schema.key_column_usage basecol on base.table_name = basecol.table_name and base.constraint_name = basecol.constraint_name
inner join information_schema.key_column_usage refcol on ref.table_name = refcol.table_name and ref.constraint_name = refcol.constraint_name and basecol.ordinal_position = refcol.ordinal_position
where
base.table_schema <> 'information_schema'
and base.table_schema <> 'pg_catalog'
and base.table_schema !~ '^pg_toast'
and ('tables:' || base.table_schema || '.' || base.table_name) =OBJECT_ID_CONDITION
order by basecol.ordinal_position
`;

View File

@ -0,0 +1,8 @@
module.exports = `
select
f_table_schema as "schema_name",
f_table_name as "pure_name",
f_geography_column as "column_name"
from public.geography_columns
where ('tables:' || f_table_schema || '.' || f_table_name) =OBJECT_ID_CONDITION
`;

View File

@ -0,0 +1,8 @@
module.exports = `
select
f_table_schema as "schema_name",
f_table_name as "pure_name",
f_geometry_column as "column_name"
from public.geometry_columns
where ('tables:' || f_table_schema || '.' || f_table_name) =OBJECT_ID_CONDITION
`;

View File

@ -0,0 +1,44 @@
const columns = require('./columns');
const tableModifications = require('./tableList');
const tableList = require('./tableList');
const viewModifications = require('./views');
const matviewModifications = require('./matviewModifications');
const primaryKeys = require('./primaryKeys');
const foreignKeys = require('./foreignKeys');
const views = require('./views');
const matviews = require('./matviews');
const routines = require('./routines');
const routineModifications = require('./routineModifications');
const matviewColumns = require('./matviewColumns');
const indexes = require('./indexes');
const indexcols = require('./indexcols');
const uniqueNames = require('./uniqueNames');
const geometryColumns = require('./geometryColumns');
const geographyColumns = require('./geographyColumns');
const fk_keyColumnUsage = require('./fk_key_column_usage');
const fk_referentialConstraints = require('./fk_referential_constraints');
const fk_tableConstraints = require('./fk_table_constraints');
module.exports = {
columns,
tableModifications,
tableList,
viewModifications,
primaryKeys,
foreignKeys,
fk_keyColumnUsage,
fk_referentialConstraints,
fk_tableConstraints,
views,
routines,
routineModifications,
matviews,
matviewModifications,
matviewColumns,
indexes,
indexcols,
uniqueNames,
geometryColumns,
geographyColumns,
};

View File

@ -0,0 +1,24 @@
module.exports = `
select
a.attname as "column_name",
a.attnum as "attnum",
a.attrelid as "oid"
from
pg_class t,
pg_class i,
pg_attribute a,
pg_index ix,
pg_namespace c
where
t.oid = ix.indrelid
and a.attnum = ANY(ix.indkey)
and a.attrelid = t.oid
and i.oid = ix.indexrelid
and t.relkind = 'r'
and ix.indisprimary = false
and t.relnamespace = c.oid
and c.nspname != 'pg_catalog'
and ('tables:' || c.nspname || '.' || t.relname) =OBJECT_ID_CONDITION
order by
t.relname
`;

View File

@ -0,0 +1,25 @@
module.exports = `
select
t.relname as "table_name",
c.nspname as "schema_name",
i.relname as "index_name",
ix.indisprimary as "is_primary",
ix.indisunique as "is_unique",
ix.indkey as "indkey",
t.oid as "oid"
from
pg_class t,
pg_class i,
pg_index ix,
pg_namespace c
where
t.oid = ix.indrelid
and i.oid = ix.indexrelid
and t.relkind = 'r'
and ix.indisprimary = false
and t.relnamespace = c.oid
and c.nspname != 'pg_catalog'
and ('tables:' || c.nspname || '.' || t.relname) =OBJECT_ID_CONDITION
order by
t.relname
`;

View File

@ -0,0 +1,17 @@
module.exports = `
SELECT pg_namespace.nspname AS "schema_name"
, pg_class.relname AS "pure_name"
, pg_attribute.attname AS "column_name"
, pg_catalog.format_type(pg_attribute.atttypid, pg_attribute.atttypmod) AS "data_type"
FROM pg_catalog.pg_class
INNER JOIN pg_catalog.pg_namespace
ON pg_class.relnamespace = pg_namespace.oid
INNER JOIN pg_catalog.pg_attribute
ON pg_class.oid = pg_attribute.attrelid
-- Keeps only materialized views, and non-db/catalog/index columns
WHERE pg_class.relkind = 'm'
AND pg_attribute.attnum >= 1
AND ('matviews:' || pg_namespace.nspname || '.' || pg_class.relname) =OBJECT_ID_CONDITION
ORDER BY pg_attribute.attnum
`;

View File

@ -0,0 +1,8 @@
module.exports = `
select
matviewname as "pure_name",
schemaname as "schema_name",
md5(definition) as "hash_code"
from
pg_catalog.pg_matviews WHERE schemaname NOT LIKE 'pg_%'
`;

View File

@ -0,0 +1,10 @@
module.exports = `
select
matviewname as "pure_name",
schemaname as "schema_name",
definition as "definition",
md5(definition) as "hash_code"
from
pg_catalog.pg_matviews WHERE schemaname NOT LIKE 'pg_%'
and ('matviews:' || schemaname || '.' || matviewname) =OBJECT_ID_CONDITION
`;

View File

@ -0,0 +1,17 @@
module.exports = `
select
table_constraints.constraint_schema as "constraint_schema",
table_constraints.constraint_name as "constraint_name",
table_constraints.table_schema as "schema_name",
table_constraints.table_name as "pure_name",
key_column_usage.column_name as "column_name"
from information_schema.table_constraints
inner join information_schema.key_column_usage on table_constraints.table_name = key_column_usage.table_name and table_constraints.constraint_name = key_column_usage.constraint_name
where
table_constraints.table_schema <> 'information_schema'
and table_constraints.table_schema <> 'pg_catalog'
and table_constraints.table_schema !~ '^pg_toast'
and table_constraints.constraint_type = 'PRIMARY KEY'
and ('tables:' || table_constraints.table_schema || '.' || table_constraints.table_name) =OBJECT_ID_CONDITION
order by key_column_usage.ordinal_position
`;

View File

@ -0,0 +1,10 @@
module.exports = `
select
routine_name as "pure_name",
routine_schema as "schema_name",
md5(routine_definition) as "hash_code",
routine_type as "object_type"
from
information_schema.routines where routine_schema != 'information_schema' and routine_schema != 'pg_catalog'
and routine_type in ('PROCEDURE', 'FUNCTION')
`;

View File

@ -0,0 +1,17 @@
module.exports = `
select
routine_name as "pure_name",
routine_schema as "schema_name",
routine_definition as "definition",
md5(routine_definition) as "hash_code",
routine_type as "object_type",
data_type as "data_type",
external_language as "language"
from
information_schema.routines where routine_schema != 'information_schema' and routine_schema != 'pg_catalog'
and (
(routine_type = 'PROCEDURE' and ('procedures:' || routine_schema || '.' || routine_name) =OBJECT_ID_CONDITION)
or
(routine_type = 'FUNCTION' and ('functions:' || routine_schema || '.' || routine_name) =OBJECT_ID_CONDITION)
)
`;

View File

@ -0,0 +1,18 @@
module.exports = `
select ao.owner as "schema_name", ao.object_name as "pure_name"
from all_objects ao
where exists(select null from user_objects uo where uo.object_id = ao.object_id)
and object_type = 'TABLE'
`;
/*
module.exports = `
select infoTables.table_schema as "schema_name", infoTables.table_name as "pure_name"
from information_schema.tables infoTables
where infoTables.table_type not like '%VIEW%'
and ('tables:' || infoTables.table_schema || '.' || infoTables.table_name) =OBJECT_ID_CONDITION
and infoTables.table_schema <> 'pg_catalog'
and infoTables.table_schema <> 'information_schema'
and infoTables.table_schema <> 'pg_internal'
and infoTables.table_schema !~ '^pg_toast'
`;
*/

View File

@ -0,0 +1,28 @@
module.exports = `
select infoTables.table_schema as "schema_name", infoTables.table_name as "pure_name",
(
select md5(string_agg(
infoColumns.column_name || '|' || infoColumns.data_type || '|' || infoColumns.is_nullable::varchar(255) || '|' || coalesce(infoColumns.character_maximum_length, -1)::varchar(255)
|| '|' || coalesce(infoColumns.numeric_precision, -1)::varchar(255) ,
',' order by infoColumns.ordinal_position
)) as "hash_code_columns"
from information_schema.columns infoColumns
where infoColumns.table_schema = infoTables.table_schema and infoColumns.table_name = infoTables.table_name
),
(
select md5(string_agg(
infoConstraints.constraint_name || '|' || infoConstraints.constraint_type ,
',' order by infoConstraints.constraint_name
)) as "hash_code_constraints"
from information_schema.table_constraints infoConstraints
where infoConstraints.table_schema = infoTables.table_schema and infoConstraints.table_name = infoTables.table_name
)
from information_schema.tables infoTables
where infoTables.table_type not like '%VIEW%'
and ('tables:' || infoTables.table_schema || '.' || infoTables.table_name) =OBJECT_ID_CONDITION
and infoTables.table_schema <> 'pg_catalog'
and infoTables.table_schema <> 'information_schema'
and infoTables.table_schema <> 'pg_internal'
and infoTables.table_schema !~ '^pg_toast'
`;

View File

@ -0,0 +1,3 @@
module.exports = `
select conname as "constraint_name" from pg_constraint where contype = 'u'
`;

View File

@ -0,0 +1,8 @@
module.exports = `
select
table_name as "pure_name",
table_schema as "schema_name",
md5(view_definition) as "hash_code"
from
information_schema.views where table_schema != 'information_schema' and table_schema != 'pg_catalog'
`;

View File

@ -0,0 +1,9 @@
module.exports = `
select
ao.owner as "schema_name", ao.object_name as "pure_name",
'later' as "create_sql",
object_id as "hash_code"
from all_objects ao
where exists(select null from user_objects uo where uo.object_id = ao.object_id)
and object_type = 'VIEW'
`;

View File

@ -0,0 +1,100 @@
const { SqlDumper, arrayToHexString, testEqualTypes } = global.DBGATE_TOOLS;
class Dumper extends SqlDumper {
/** @param type {import('dbgate-types').TransformType} */
transform(type, dumpExpr) {
switch (type) {
case 'GROUP:YEAR':
case 'YEAR':
this.put('^extract(^year ^from %c)', dumpExpr);
break;
case 'MONTH':
this.put('^extract(^month ^from %c)', dumpExpr);
break;
case 'DAY':
this.put('^extract(^day ^from %c)', dumpExpr);
break;
case 'GROUP:MONTH':
this.put("^to_char(%c, '%s')", dumpExpr, 'YYYY-MM');
break;
case 'GROUP:DAY':
this.put("^to_char(%c, '%s')", dumpExpr, 'YYYY-MM-DD');
break;
default:
dumpExpr();
break;
}
}
dropRecreatedTempTable(tmptable) {
this.putCmd('^drop ^table %i ^cascade', tmptable);
}
renameTable(obj, newname) {
this.putCmd('^alter ^table %f ^rename ^to %i', obj, newname);
}
renameColumn(column, newcol) {
this.putCmd('^alter ^table %f ^rename ^column %i ^to %i', column, column.columnName, newcol);
}
dropTable(obj, options = {}) {
this.put('^drop ^table');
if (options.testIfExists) this.put(' ^if ^exists');
this.put(' %f', obj);
this.endCommand();
}
//public override void CreateIndex(IndexInfo ix)
//{
//}
enableConstraints(table, enabled) {
this.putCmd('^alter ^table %f %k ^trigger ^all', table, enabled ? 'enable' : 'disable');
}
columnDefinition(col, options) {
if (col.autoIncrement) {
this.put('^serial');
return;
}
super.columnDefinition(col, options);
}
changeColumn(oldcol, newcol, constraints) {
if (oldcol.columnName != newcol.columnName) {
this.putCmd('^alter ^table %f ^rename ^column %i ^to %i', oldcol, oldcol.columnName, newcol.columnName);
}
if (!testEqualTypes(oldcol, newcol)) {
this.putCmd('^alter ^table %f ^alter ^column %i ^type %s', oldcol, newcol.columnName, newcol.dataType);
}
if (oldcol.notNull != newcol.notNull) {
if (newcol.notNull) this.putCmd('^alter ^table %f ^alter ^column %i ^set ^not ^null', newcol, newcol.columnName);
else this.putCmd('^alter ^table %f ^alter ^column %i ^drop ^not ^null', newcol, newcol.columnName);
}
if (oldcol.defaultValue != newcol.defaultValue) {
if (newcol.defaultValue == null) {
this.putCmd('^alter ^table %f ^alter ^column %i ^drop ^default', newcol, newcol.columnName);
} else {
this.putCmd(
'^alter ^table %f ^alter ^column %i ^set ^default %s',
newcol,
newcol.columnName,
newcol.defaultValue
);
}
}
}
putValue(value) {
if (value === true) this.putRaw('true');
else if (value === false) this.putRaw('false');
else super.putValue(value);
}
putByteArrayValue(value) {
this.putRaw(`e'\\\\x${arrayToHexString(value)}'`);
}
}
module.exports = Dumper;

View File

@ -0,0 +1,200 @@
const { driverBase } = global.DBGATE_TOOLS;
const Dumper = require('./Dumper');
const { oracleSplitterOptions } = require('dbgate-query-splitter/lib/options');
const spatialTypes = ['GEOGRAPHY'];
/** @type {import('dbgate-types').SqlDialect} */
const dialect = {
rangeSelect: true,
ilike: true,
// stringEscapeChar: '\\',
stringEscapeChar: "'",
fallbackDataType: 'varchar',
anonymousPrimaryKey: true,
enableConstraintsPerTable: true,
dropColumnDependencies: ['dependencies'],
quoteIdentifier(s) {
return '"' + s + '"';
},
stringAgg: true,
createColumn: true,
dropColumn: true,
changeColumn: true,
createIndex: true,
dropIndex: true,
createForeignKey: true,
dropForeignKey: true,
createPrimaryKey: true,
dropPrimaryKey: true,
createUnique: true,
dropUnique: true,
createCheck: true,
dropCheck: true,
dropReferencesWhenDropTable: true,
predefinedDataTypes: [
'bigint',
'bigserial',
'bit',
'varbit',
'boolean',
'box',
'bytea',
'char(20)',
'varchar(250)',
'cidr',
'circle',
'date',
'double precision',
'inet',
'int',
'interval',
'json',
'jsonb',
'line',
'lseg',
'macaddr',
'macaddr8',
'money',
'numeric(10,2)',
'path',
'pg_lsn',
'pg_snapshot',
'point',
'polygon',
'real',
'smallint',
'smallserial',
'serial',
'text',
'time',
'timetz',
'timestamp',
'timestamptz',
'tsquery',
'tsvector',
'txid_snapshot',
'uuid',
'xml',
],
createColumnViewExpression(columnName, dataType, source, alias) {
if (dataType && spatialTypes.includes(dataType.toUpperCase())) {
return {
exprType: 'call',
func: 'ST_AsText',
alias: alias || columnName,
args: [
{
exprType: 'column',
columnName,
source,
},
],
};
}
},
};
const oracleDriverBase = {
...driverBase,
dumperClass: Dumper,
dialect,
// showConnectionField: (field, values) =>
// ['server', 'port', 'user', 'password', 'defaultDatabase', 'singleDatabase'].includes(field),
getQuerySplitterOptions: () => oracleSplitterOptions,
readOnlySessions: true,
databaseUrlPlaceholder: 'e.g. oracledb://user:password@localhost:1521',
showConnectionField: (field, values) => {
if (field == 'useDatabaseUrl') return true;
if (values.useDatabaseUrl) {
return ['databaseUrl', 'isReadOnly'].includes(field);
}
return (
['authType', 'user', 'password', 'defaultDatabase', 'singleDatabase', 'isReadOnly'].includes(field) ||
(values.authType == 'socket' && ['socketPath'].includes(field)) ||
(values.authType != 'socket' && ['server', 'port'].includes(field))
);
},
beforeConnectionSave: connection => {
const { databaseUrl } = connection;
if (databaseUrl) {
const m = databaseUrl.match(/\/([^/]+)($|\?)/);
return {
...connection,
singleDatabase: !!m,
defaultDatabase: m ? m[1] : null,
};
}
return connection;
},
__analyserInternals: {
refTableCond: '',
},
getNewObjectTemplates() {
return [
{ label: 'New view', sql: 'CREATE VIEW myview\nAS\nSELECT * FROM table1' },
{ label: 'New materialized view', sql: 'CREATE MATERIALIZED VIEW myview\nAS\nSELECT * FROM table1' },
{
label: 'New procedure',
sql: `CREATE PROCEDURE myproc (arg1 INT)
LANGUAGE SQL
AS $$
SELECT * FROM table1;
$$`,
},
{
label: 'New function (plpgsql)',
sql: `CREATE FUNCTION myfunc (arg1 INT)
RETURNS INT
AS $$
BEGIN
RETURN 1;
END
$$ LANGUAGE plpgsql;`,
},
];
},
authTypeLabel: 'Connection mode',
defaultAuthTypeName: 'hostPort',
defaultSocketPath: '/var/run/oracledb',
};
/** @type {import('dbgate-types').EngineDriver} */
const oracleDriver = {
...oracleDriverBase,
engine: 'oracle@dbgate-plugin-oracle',
title: 'OracleDB',
defaultPort: 1521,
dialect: {
...dialect,
materializedViews: true,
},
dialectByVersion(version) {
if (version) {
return {
...dialect,
materializedViews:
version &&
version.versionMajor != null &&
version.versionMinor != null &&
(version.versionMajor > 9 || version.versionMajor == 9 || version.versionMinor >= 3),
};
}
return dialect;
},
};
module.exports = [oracleDriver];

View File

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

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,40 @@
var webpack = require('webpack');
var path = require('path');
var config = {
context: __dirname + '/src/backend',
entry: {
app: './index.js',
},
target: 'node',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'backend.js',
libraryTarget: 'commonjs2',
},
// uncomment for disable minimalization
// optimization: {
// minimize: false,
// },
plugins: [
new webpack.IgnorePlugin({
checkResource(resource) {
const lazyImports = ['oracledb', 'uws'];
if (!lazyImports.includes(resource)) {
return false;
}
try {
require.resolve(resource);
} catch (err) {
return true;
}
return false;
},
}),
],
};
module.exports = config;

View File

@ -0,0 +1,30 @@
var webpack = require('webpack');
var path = require('path');
var config = {
context: __dirname + '/src/frontend',
entry: {
app: './index.js',
},
target: 'web',
output: {
path: path.resolve(__dirname, 'dist'),
filename: 'frontend.js',
libraryTarget: 'var',
library: 'plugin',
},
plugins: [
new webpack.DefinePlugin({
'global.DBGATE_TOOLS': 'window.DBGATE_TOOLS',
}),
],
// uncomment for disable minimalization
// optimization: {
// minimize: false,
// },
};
module.exports = config;

View File

@ -8195,6 +8195,11 @@ optionator@^0.8.1, optionator@^0.8.3:
resolved "https://registry.yarnpkg.com/opts/-/opts-2.0.2.tgz#a17e189fbbfee171da559edd8a42423bc5993ce1"
integrity sha512-k41FwbcLnlgnFh69f4qdUfvDQ+5vaSDnVPFI/y5XuhKRq97EnVVneO9F1ESVCdiVu4fCS2L8usX3mU331hB7pg==
oracledb@^5.0.0:
version "5.5.0"
resolved "https://registry.yarnpkg.com/oracledb/-/oracledb-5.5.0.tgz#0cf9af5d0c0815f74849ae9ed56aee823514d71b"
integrity sha512-i5cPvMENpZP8nnqptB6l0pjiOyySj1IISkbM4Hr3yZEDdANo2eezarwZb9NQ8fTh5pRjmgpZdSyIbnn9N3AENw==
os-browserify@^0.3.0:
version "0.3.0"
resolved "https://registry.yarnpkg.com/os-browserify/-/os-browserify-0.3.0.tgz#854373c7f5c2315914fc9bfc6bd8238fdda1ec27"