mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-27 02:05:59 +00:00
Merge branch 'develop'
This commit is contained in:
@@ -33,7 +33,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"lodash": "^4.17.21",
|
||||
"xlsx": "^0.16.8",
|
||||
"xlsx": "^0.18.5",
|
||||
"dbgate-plugin-tools": "^1.0.7",
|
||||
"webpack": "^4.42.0",
|
||||
"webpack-cli": "^3.3.11"
|
||||
|
||||
@@ -1,9 +1,3 @@
|
||||
let dbgateEnv;
|
||||
|
||||
function initialize(dbgateEnv) {
|
||||
dbgateEnv = dbgateEnv;
|
||||
}
|
||||
|
||||
const fileFormat = {
|
||||
packageName: 'dbgate-plugin-excel',
|
||||
// file format identifier
|
||||
@@ -17,8 +11,8 @@ const fileFormat = {
|
||||
// function name from backend, which contains writer factory, postfixed by package name
|
||||
writerFunc: 'writer@dbgate-plugin-excel',
|
||||
|
||||
addFileToSourceList: async ({ fileName }, newSources, newValues) => {
|
||||
const resp = await dbgateEnv.apiCall('plugins/command', {
|
||||
addFileToSourceList: async ({ fileName }, newSources, newValues, apiCall) => {
|
||||
const resp = await apiCall('plugins/command', {
|
||||
command: 'analyse',
|
||||
packageName: 'dbgate-plugin-excel',
|
||||
args: {
|
||||
@@ -85,5 +79,4 @@ export default {
|
||||
}),
|
||||
},
|
||||
],
|
||||
initialize,
|
||||
};
|
||||
|
||||
@@ -42,6 +42,7 @@ const dialect = {
|
||||
dropCheck: true,
|
||||
|
||||
dropReferencesWhenDropTable: false,
|
||||
requireStandaloneSelectForScopeIdentity: true,
|
||||
|
||||
columnProperties: {
|
||||
columnComment: true,
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
"devDependencies": {
|
||||
"dbgate-plugin-tools": "^1.0.8",
|
||||
"dbgate-query-splitter": "^4.9.0",
|
||||
"dbgate-tools": "^5.1.6",
|
||||
"dbgate-tools": "^5.0.0-alpha.1",
|
||||
"lodash": "^4.17.21",
|
||||
"webpack": "^4.42.0",
|
||||
"webpack-cli": "^3.3.11"
|
||||
|
||||
@@ -104,7 +104,7 @@ class Analyser extends DatabaseAnalyser {
|
||||
const uniqueNames = await this.analyserQuery('uniqueNames', ['tables']);
|
||||
this.feedback({ analysingMessage: 'Finalizing DB structure' });
|
||||
|
||||
const columnColumnsMapped = fkColumns.rows.map(x => ({
|
||||
const fkColumnsMapped = fkColumns.rows.map(x => ({
|
||||
pureName: x.pure_name,
|
||||
schemaName: x.schema_name,
|
||||
constraintSchema: x.constraint_schema,
|
||||
@@ -124,6 +124,9 @@ class Analyser extends DatabaseAnalyser {
|
||||
columnName: x.column_name,
|
||||
}));
|
||||
|
||||
const columnGroup = col => `${col.schema_name}||${col.pure_name}`;
|
||||
const columnsGrouped = _.groupBy(columns.rows, columnGroup);
|
||||
|
||||
const res = {
|
||||
tables: tables.rows.map(table => {
|
||||
const newTable = {
|
||||
@@ -134,11 +137,11 @@ class Analyser extends DatabaseAnalyser {
|
||||
};
|
||||
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)),
|
||||
columns: (columnsGrouped[columnGroup(table)] || []).map(col =>
|
||||
getColumnInfo(col, newTable, geometryColumns, geographyColumns)
|
||||
),
|
||||
primaryKey: DatabaseAnalyser.extractPrimaryKeys(newTable, pkColumnsMapped),
|
||||
foreignKeys: DatabaseAnalyser.extractForeignKeys(newTable, columnColumnsMapped),
|
||||
foreignKeys: DatabaseAnalyser.extractForeignKeys(newTable, fkColumnsMapped),
|
||||
indexes: _.uniqBy(
|
||||
indexes.rows.filter(
|
||||
idx =>
|
||||
@@ -176,9 +179,7 @@ class Analyser extends DatabaseAnalyser {
|
||||
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)),
|
||||
columns: (columnsGrouped[columnGroup(view)] || []).map(col => getColumnInfo(col)),
|
||||
})),
|
||||
matviews: matviews
|
||||
? matviews.rows.map(matview => ({
|
||||
@@ -212,6 +213,9 @@ class Analyser extends DatabaseAnalyser {
|
||||
})),
|
||||
};
|
||||
|
||||
// this.feedback({ analysingMessage: 'Debug sleep' });
|
||||
// await new Promise(resolve => setTimeout(resolve, 90 * 1000));
|
||||
|
||||
this.feedback({ analysingMessage: null });
|
||||
|
||||
return res;
|
||||
|
||||
@@ -52,52 +52,10 @@ const drivers = driverBases.map(driverBase => ({
|
||||
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
|
||||
client = await oracledb.getConnection({
|
||||
user,
|
||||
password,
|
||||
connectString: useDatabaseUrl ? databaseUrl : port ? `${server}:${port}` : server,
|
||||
});
|
||||
return client;
|
||||
},
|
||||
@@ -105,28 +63,25 @@ const drivers = driverBases.map(driverBase => ({
|
||||
return pool.end();
|
||||
},
|
||||
async query(client, sql) {
|
||||
//console.log('query sql', sql);
|
||||
//console.log('query sql', sql);
|
||||
if (sql == null) {
|
||||
return {
|
||||
rows: [],
|
||||
columns: [],
|
||||
};
|
||||
}
|
||||
try {
|
||||
try {
|
||||
//console.log('sql3', 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 };
|
||||
}
|
||||
catch(err) {
|
||||
console.log('Error query', err, sql);
|
||||
}
|
||||
finally {
|
||||
//console.log('finally', 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 };
|
||||
} catch (err) {
|
||||
console.log('Error query', err, sql);
|
||||
} finally {
|
||||
//console.log('finally', sql);
|
||||
}
|
||||
},
|
||||
stream(client, sql, options) {
|
||||
/*
|
||||
@@ -137,8 +92,8 @@ finally {
|
||||
*/
|
||||
// console.log('queryStream', sql);
|
||||
const query = client.queryStream(sql);
|
||||
// const consumeStream = new Promise((resolve, reject) => {
|
||||
let rowcount = 0;
|
||||
// const consumeStream = new Promise((resolve, reject) => {
|
||||
let rowcount = 0;
|
||||
let wasHeader = false;
|
||||
|
||||
query.on('metadata', row => {
|
||||
@@ -200,13 +155,12 @@ finally {
|
||||
});
|
||||
options.done();
|
||||
});
|
||||
query.on('close', function() {
|
||||
//console.log("stream 'close' event");
|
||||
// The underlying ResultSet has been closed, so the connection can now
|
||||
// be closed, if desired. Note: do not close connections on 'end'.
|
||||
//resolve(rowcount);
|
||||
;
|
||||
});
|
||||
query.on('close', function () {
|
||||
//console.log("stream 'close' event");
|
||||
// The underlying ResultSet has been closed, so the connection can now
|
||||
// be closed, if desired. Note: do not close connections on 'end'.
|
||||
//resolve(rowcount);
|
||||
});
|
||||
//});
|
||||
|
||||
//const numrows = await consumeStream;
|
||||
@@ -215,7 +169,7 @@ finally {
|
||||
},
|
||||
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 as \"version\" FROM v$instance");
|
||||
const { rows } = await this.query(client, 'SELECT version as "version" FROM v$instance');
|
||||
const { version } = rows[0];
|
||||
|
||||
const isCockroach = false; //version.toLowerCase().includes('cockroachdb');
|
||||
@@ -245,7 +199,7 @@ finally {
|
||||
};
|
||||
},
|
||||
async readQuery(client, sql, structure) {
|
||||
/*
|
||||
/*
|
||||
const query = new pg.Query({
|
||||
text: sql,
|
||||
rowMode: 'array',
|
||||
@@ -267,10 +221,10 @@ finally {
|
||||
if (!wasHeader) {
|
||||
columns = extractOracleColumns(row);
|
||||
if (columns && columns.length > 0) {
|
||||
pass.write({
|
||||
__isStreamHeader: true,
|
||||
...(structure || { columns }),
|
||||
});
|
||||
pass.write({
|
||||
__isStreamHeader: true,
|
||||
...(structure || { columns }),
|
||||
});
|
||||
}
|
||||
wasHeader = true;
|
||||
}
|
||||
@@ -301,7 +255,7 @@ finally {
|
||||
return createBulkInsertStreamBase(this, stream, pool, name, options);
|
||||
},
|
||||
async listDatabases(client) {
|
||||
const { rows } = await this.query(client, 'SELECT instance_name AS \"name\" FROM v$instance');
|
||||
const { rows } = await this.query(client, 'SELECT instance_name AS "name" FROM v$instance');
|
||||
return rows;
|
||||
},
|
||||
|
||||
@@ -319,7 +273,7 @@ finally {
|
||||
},
|
||||
}));
|
||||
|
||||
drivers.initialize = (dbgateEnv) => {
|
||||
drivers.initialize = dbgateEnv => {
|
||||
if (dbgateEnv.nativeModules && dbgateEnv.nativeModules.oracledb) {
|
||||
oracledb = dbgateEnv.nativeModules.oracledb();
|
||||
}
|
||||
|
||||
@@ -118,11 +118,7 @@ const oracleDriverBase = {
|
||||
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))
|
||||
);
|
||||
return ['user', 'password', 'defaultDatabase', 'singleDatabase', 'isReadOnly', 'server', 'port'].includes(field);
|
||||
},
|
||||
|
||||
beforeConnectionSave: connection => {
|
||||
@@ -166,17 +162,13 @@ $$ 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',
|
||||
title: 'OracleDB (Experimental)',
|
||||
defaultPort: 1521,
|
||||
dialect: {
|
||||
...dialect,
|
||||
@@ -196,7 +188,8 @@ const oracleDriver = {
|
||||
}
|
||||
return dialect;
|
||||
},
|
||||
|
||||
showConnectionTab: (field) => field == 'sshTunnel',
|
||||
};
|
||||
|
||||
|
||||
module.exports = [oracleDriver];
|
||||
|
||||
@@ -35,6 +35,7 @@ const dialect = {
|
||||
dropCheck: true,
|
||||
|
||||
dropReferencesWhenDropTable: true,
|
||||
requireStandaloneSelectForScopeIdentity: true,
|
||||
|
||||
predefinedDataTypes: [
|
||||
'bigint',
|
||||
|
||||
@@ -18,7 +18,23 @@ class Dumper extends SqlDumper {
|
||||
}
|
||||
|
||||
selectScopeIdentity() {
|
||||
this.put('^select last_insert_rowid()')
|
||||
this.put('^select last_insert_rowid()');
|
||||
}
|
||||
|
||||
columnDefinition(column, flags) {
|
||||
if (column.dataType && column.dataType.toLowerCase().includes('int') && column.notNull && column.autoIncrement) {
|
||||
this.put('^integer ^primary ^key ^autoincrement');
|
||||
return;
|
||||
}
|
||||
super.columnDefinition(column, flags);
|
||||
}
|
||||
|
||||
createTablePrimaryKeyCore(table) {
|
||||
const column = table.columns.find((x) => x.autoIncrement);
|
||||
if (column && column.dataType && column.dataType.toLowerCase().includes('int') && column.notNull) {
|
||||
return;
|
||||
}
|
||||
super.createTablePrimaryKeyCore(table);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ const dialect = {
|
||||
return `[${s}]`;
|
||||
},
|
||||
anonymousPrimaryKey: true,
|
||||
requireStandaloneSelectForScopeIdentity: true,
|
||||
|
||||
createColumn: true,
|
||||
dropColumn: true,
|
||||
|
||||
Reference in New Issue
Block a user