mirror of
https://github.com/DeNNiiInc/dbgate.git
synced 2026-04-18 00:56:02 +00:00
create script callable from react
This commit is contained in:
@@ -1,14 +1,19 @@
|
||||
const mssql = require('mssql');
|
||||
const mysql = require('mysql');
|
||||
const pg = require('pg');
|
||||
const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
|
||||
const nativeModules = {
|
||||
mssql,
|
||||
mysql,
|
||||
pg,
|
||||
fs,
|
||||
path,
|
||||
};
|
||||
|
||||
function driverConnect(driver, connection) {
|
||||
const driverModules = {
|
||||
mssql,
|
||||
mysql,
|
||||
pg,
|
||||
};
|
||||
return driver.connect(driverModules, connection);
|
||||
return driver.connect(nativeModules, connection);
|
||||
}
|
||||
|
||||
module.exports = driverConnect;
|
||||
|
||||
@@ -8,8 +8,8 @@ class SqlDumper {
|
||||
putRaw(text) {
|
||||
this.s += text;
|
||||
}
|
||||
putCmd(text) {
|
||||
this.putRaw(text);
|
||||
putCmd(format, ...args) {
|
||||
this.put(format, ...args);
|
||||
this.putRaw(';\n');
|
||||
}
|
||||
putFormattedValue(c, value) {
|
||||
|
||||
@@ -1,7 +1,25 @@
|
||||
const _ = require("lodash");
|
||||
const mssql = require('./mssql');
|
||||
const mysql = require('./mysql');
|
||||
const postgres = require('./postgres');
|
||||
|
||||
const drivers = {
|
||||
mssql,
|
||||
mysql,
|
||||
postgres,
|
||||
}
|
||||
|
||||
/** @return {import('@dbgate/types').EngineDriver} */
|
||||
function getDriver(connection) {
|
||||
const { engine } = connection;
|
||||
return require(`./${engine}`);
|
||||
if (_.isString(connection)) {
|
||||
return drivers[connection];
|
||||
}
|
||||
if (_.isPlainObject(connection)) {
|
||||
const { engine } = connection;
|
||||
if (engine) {
|
||||
return drivers[engine];
|
||||
}
|
||||
}
|
||||
throw new Error(`Cannot extract engine from ${connection}`)
|
||||
}
|
||||
module.exports = getDriver;
|
||||
|
||||
@@ -1,42 +1,49 @@
|
||||
const fs = require('fs-extra');
|
||||
const fp = require('lodash/fp');
|
||||
const path = require('path');
|
||||
const _ = require('lodash');
|
||||
const fp = require("lodash/fp");
|
||||
const _ = require("lodash");
|
||||
|
||||
const DatabaseAnalayser = require('../default/DatabaseAnalyser');
|
||||
const DatabaseAnalayser = require("../default/DatabaseAnalyser");
|
||||
|
||||
/** @returns {Promise<string>} */
|
||||
async function loadQuery(name) {
|
||||
return await fs.readFile(path.join(__dirname, name), 'utf-8');
|
||||
async function loadQuery(pool, name) {
|
||||
return await pool._nativeModules.fs.readFile(
|
||||
pool._nativeModules.path.join(__dirname, name),
|
||||
"utf-8"
|
||||
);
|
||||
}
|
||||
|
||||
const byTableFilter = table => x => x.pureName == table.pureName && x.schemaName == x.schemaName;
|
||||
const byTableFilter = table => x =>
|
||||
x.pureName == table.pureName && x.schemaName == x.schemaName;
|
||||
|
||||
function extractPrimaryKeys(table, pkColumns) {
|
||||
const filtered = pkColumns.filter(byTableFilter(table));
|
||||
if (filtered.length == 0) return undefined;
|
||||
return {
|
||||
..._.pick(filtered[0], ['constraintName', 'schemaName', 'pureName']),
|
||||
constraintType: 'primaryKey',
|
||||
columns: filtered.map(fp.pick('columnName')),
|
||||
..._.pick(filtered[0], ["constraintName", "schemaName", "pureName"]),
|
||||
constraintType: "primaryKey",
|
||||
columns: filtered.map(fp.pick("columnName"))
|
||||
};
|
||||
}
|
||||
|
||||
function extractForeignKeys(table, fkColumns) {
|
||||
const grouped = _.groupBy(fkColumns.filter(byTableFilter(table)), 'constraintName');
|
||||
const grouped = _.groupBy(
|
||||
fkColumns.filter(byTableFilter(table)),
|
||||
"constraintName"
|
||||
);
|
||||
return _.keys(grouped).map(constraintName => ({
|
||||
constraintName,
|
||||
constraintType: 'foreignKey',
|
||||
constraintType: "foreignKey",
|
||||
..._.pick(grouped[constraintName][0], [
|
||||
'constraintName',
|
||||
'schemaName',
|
||||
'pureName',
|
||||
'refSchemaName',
|
||||
'refTableName',
|
||||
'updateAction',
|
||||
'deleteAction',
|
||||
"constraintName",
|
||||
"schemaName",
|
||||
"pureName",
|
||||
"refSchemaName",
|
||||
"refTableName",
|
||||
"updateAction",
|
||||
"deleteAction"
|
||||
]),
|
||||
columns: grouped[constraintName].map(fp.pick(['columnName', 'refColumnName'])),
|
||||
columns: grouped[constraintName].map(
|
||||
fp.pick(["columnName", "refColumnName"])
|
||||
)
|
||||
}));
|
||||
}
|
||||
|
||||
@@ -53,15 +60,27 @@ class MsSqlAnalyser extends DatabaseAnalayser {
|
||||
functions = false,
|
||||
triggers = false
|
||||
) {
|
||||
let res = await loadQuery(resFileName);
|
||||
res = res.replace('=[OBJECT_ID_CONDITION]', ' is not null');
|
||||
let res = await loadQuery(this.pool, resFileName);
|
||||
res = res.replace("=[OBJECT_ID_CONDITION]", " is not null");
|
||||
return res;
|
||||
}
|
||||
async runAnalysis() {
|
||||
const tables = await this.driver.query(this.pool, await this.createQuery('tables.sql'));
|
||||
const columns = await this.driver.query(this.pool, await this.createQuery('columns.sql'));
|
||||
const pkColumns = await this.driver.query(this.pool, await this.createQuery('primary_keys.sql'));
|
||||
const fkColumns = await this.driver.query(this.pool, await this.createQuery('foreign_keys.sql'));
|
||||
const tables = await this.driver.query(
|
||||
this.pool,
|
||||
await this.createQuery("tables.sql")
|
||||
);
|
||||
const columns = await this.driver.query(
|
||||
this.pool,
|
||||
await this.createQuery("columns.sql")
|
||||
);
|
||||
const pkColumns = await this.driver.query(
|
||||
this.pool,
|
||||
await this.createQuery("primary_keys.sql")
|
||||
);
|
||||
const fkColumns = await this.driver.query(
|
||||
this.pool,
|
||||
await this.createQuery("foreign_keys.sql")
|
||||
);
|
||||
|
||||
this.result.tables = tables.rows.map(table => ({
|
||||
...table,
|
||||
@@ -70,10 +89,10 @@ class MsSqlAnalyser extends DatabaseAnalayser {
|
||||
.map(({ isNullable, isIdentity, ...col }) => ({
|
||||
...col,
|
||||
notNull: !isNullable,
|
||||
autoIncrement: !!isIdentity,
|
||||
autoIncrement: !!isIdentity
|
||||
})),
|
||||
primaryKey: extractPrimaryKeys(table, pkColumns.rows),
|
||||
foreignKeys: extractForeignKeys(table, fkColumns.rows),
|
||||
foreignKeys: extractForeignKeys(table, fkColumns.rows)
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,14 +12,15 @@ const dialect = {
|
||||
|
||||
/** @type {import('@dbgate/types').EngineDriver} */
|
||||
const driver = {
|
||||
async connect({ mssql }, { server, port, user, password, database }) {
|
||||
const pool = await mssql.connect({
|
||||
async connect(nativeModules, { server, port, user, password, database }) {
|
||||
const pool = await nativeModules.mssql.connect({
|
||||
server,
|
||||
port,
|
||||
user,
|
||||
password,
|
||||
database
|
||||
});
|
||||
pool._nativeModules = nativeModules;
|
||||
return pool;
|
||||
},
|
||||
async query(pool, sql) {
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
const fs = require('fs-extra');
|
||||
const fp = require('lodash/fp');
|
||||
const path = require('path');
|
||||
const _ = require('lodash');
|
||||
const fp = require("lodash/fp");
|
||||
const _ = require("lodash");
|
||||
|
||||
const DatabaseAnalayser = require('../default/DatabaseAnalyser');
|
||||
const DatabaseAnalayser = require("../default/DatabaseAnalyser");
|
||||
|
||||
/** @returns {Promise<string>} */
|
||||
async function loadQuery(name) {
|
||||
return await fs.readFile(path.join(__dirname, name), 'utf-8');
|
||||
async function loadQuery(pool, name) {
|
||||
return await pool._nativeModules.fs.readFile(
|
||||
pool._nativeModules.path.join(__dirname, name),
|
||||
"utf-8"
|
||||
);
|
||||
}
|
||||
|
||||
class MySqlAnalyser extends DatabaseAnalayser {
|
||||
@@ -23,14 +24,20 @@ class MySqlAnalyser extends DatabaseAnalayser {
|
||||
functions = false,
|
||||
triggers = false
|
||||
) {
|
||||
let res = await loadQuery(resFileName);
|
||||
res = res.replace('=[OBJECT_NAME_CONDITION]', ' is not null');
|
||||
res = res.replace('#DATABASE#', this.pool._database_name);
|
||||
let res = await loadQuery(this.pool, resFileName);
|
||||
res = res.replace("=[OBJECT_NAME_CONDITION]", " is not null");
|
||||
res = res.replace("#DATABASE#", this.pool._database_name);
|
||||
return res;
|
||||
}
|
||||
async runAnalysis() {
|
||||
const tables = await this.driver.query(this.pool, await this.createQuery('tables.sql'));
|
||||
const columns = await this.driver.query(this.pool, await this.createQuery('columns.sql'));
|
||||
const tables = await this.driver.query(
|
||||
this.pool,
|
||||
await this.createQuery("tables.sql")
|
||||
);
|
||||
const columns = await this.driver.query(
|
||||
this.pool,
|
||||
await this.createQuery("columns.sql")
|
||||
);
|
||||
// const pkColumns = await this.driver.query(this.pool, await this.createQuery('primary_keys.sql'));
|
||||
// const fkColumns = await this.driver.query(this.pool, await this.createQuery('foreign_keys.sql'));
|
||||
|
||||
@@ -41,9 +48,9 @@ class MySqlAnalyser extends DatabaseAnalayser {
|
||||
.map(({ isNullable, extra, ...col }) => ({
|
||||
...col,
|
||||
notNull: !isNullable,
|
||||
autoIncrement: extra && extra.toLowerCase().includes('auto_increment'),
|
||||
autoIncrement: extra && extra.toLowerCase().includes("auto_increment")
|
||||
})),
|
||||
foreignKeys: [],
|
||||
foreignKeys: []
|
||||
// primaryKey: extractPrimaryKeys(table, pkColumns.rows),
|
||||
// foreignKeys: extractForeignKeys(table, fkColumns.rows),
|
||||
}));
|
||||
|
||||
@@ -11,8 +11,8 @@ const dialect = {
|
||||
|
||||
/** @type {import('@dbgate/types').EngineDriver} */
|
||||
const driver = {
|
||||
async connect({ mysql }, { server, port, user, password, database }) {
|
||||
const connection = mysql.createConnection({
|
||||
async connect(nativeModules, { server, port, user, password, database }) {
|
||||
const connection = nativeModules.mysql.createConnection({
|
||||
host: server,
|
||||
port,
|
||||
user,
|
||||
@@ -20,6 +20,7 @@ const driver = {
|
||||
database
|
||||
});
|
||||
connection._database_name = database;
|
||||
connection._nativeModules = nativeModules;
|
||||
return connection;
|
||||
},
|
||||
async query(connection, sql) {
|
||||
|
||||
@@ -10,8 +10,6 @@
|
||||
"typescript": "^3.7.5"
|
||||
},
|
||||
"dependencies": {
|
||||
"fs-extra": "^8.1.0",
|
||||
"lodash": "^4.17.15",
|
||||
"path": "^0.12.7"
|
||||
"lodash": "^4.17.15"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
const fs = require('fs-extra');
|
||||
const fp = require('lodash/fp');
|
||||
const path = require('path');
|
||||
const _ = require('lodash');
|
||||
const fp = require("lodash/fp");
|
||||
const _ = require("lodash");
|
||||
|
||||
const DatabaseAnalayser = require('../default/DatabaseAnalyser');
|
||||
const DatabaseAnalayser = require("../default/DatabaseAnalyser");
|
||||
|
||||
/** @returns {Promise<string>} */
|
||||
async function loadQuery(name) {
|
||||
return await fs.readFile(path.join(__dirname, name), 'utf-8');
|
||||
async function loadQuery(pool, name) {
|
||||
return await pool._nativeModules.fs.readFile(
|
||||
pool._nativeModules.path.join(__dirname, name),
|
||||
"utf-8"
|
||||
);
|
||||
}
|
||||
|
||||
class MySqlAnalyser extends DatabaseAnalayser {
|
||||
@@ -23,25 +24,34 @@ class MySqlAnalyser extends DatabaseAnalayser {
|
||||
functions = false,
|
||||
triggers = false
|
||||
) {
|
||||
let res = await loadQuery(resFileName);
|
||||
res = res.replace('=[OBJECT_ID_CONDITION]', ' is not null');
|
||||
let res = await loadQuery(this.pool, resFileName);
|
||||
res = res.replace("=[OBJECT_ID_CONDITION]", " is not null");
|
||||
return res;
|
||||
}
|
||||
async runAnalysis() {
|
||||
const tables = await this.driver.query(this.pool, await this.createQuery('table_modifications.psql'));
|
||||
const columns = await this.driver.query(this.pool, await this.createQuery('columns.psql'));
|
||||
const tables = await this.driver.query(
|
||||
this.pool,
|
||||
await this.createQuery("table_modifications.psql")
|
||||
);
|
||||
const columns = await this.driver.query(
|
||||
this.pool,
|
||||
await this.createQuery("columns.psql")
|
||||
);
|
||||
// const pkColumns = await this.driver.query(this.pool, await this.createQuery('primary_keys.sql'));
|
||||
// const fkColumns = await this.driver.query(this.pool, await this.createQuery('foreign_keys.sql'));
|
||||
|
||||
this.result.tables = tables.rows.map(table => ({
|
||||
...table,
|
||||
columns: columns.rows
|
||||
.filter(col => col.pureName == table.pureName && col.schemaName == table.schemaName)
|
||||
.filter(
|
||||
col =>
|
||||
col.pureName == table.pureName && col.schemaName == table.schemaName
|
||||
)
|
||||
.map(({ isNullable, ...col }) => ({
|
||||
...col,
|
||||
notNull: !isNullable,
|
||||
notNull: !isNullable
|
||||
})),
|
||||
foreignKeys: [],
|
||||
foreignKeys: []
|
||||
// primaryKey: extractPrimaryKeys(table, pkColumns.rows),
|
||||
// foreignKeys: extractForeignKeys(table, fkColumns.rows),
|
||||
}));
|
||||
|
||||
@@ -11,9 +11,10 @@ const dialect = {
|
||||
|
||||
/** @type {import('@dbgate/types').EngineDriver} */
|
||||
const driver = {
|
||||
async connect({pg}, { server, port, user, password, database }) {
|
||||
const client = new pg.Client({ host: server, port, user, password, database: database || 'postgres' });
|
||||
async connect(nativeModules, { server, port, user, password, database }) {
|
||||
const client = new nativeModules.pg.Client({ host: server, port, user, password, database: database || 'postgres' });
|
||||
await client.connect();
|
||||
client._nativeModules = nativeModules;
|
||||
return client;
|
||||
},
|
||||
async query(client, sql) {
|
||||
|
||||
2
packages/types/engines.d.ts
vendored
2
packages/types/engines.d.ts
vendored
@@ -4,7 +4,7 @@ import { SqlDumper } from "./dumper";
|
||||
import { DatabaseInfo } from "./dbinfo";
|
||||
|
||||
export interface EngineDriver {
|
||||
connect(driverModules, { server, port, user, password, database }): any;
|
||||
connect(nativeModules, { server, port, user, password, database }): any;
|
||||
query(pool: any, sql: string): Promise<QueryResult>;
|
||||
getVersion(pool: any): Promise<{ version: string }>;
|
||||
listDatabases(
|
||||
|
||||
@@ -21,7 +21,8 @@
|
||||
"resize-observer-polyfill": "^1.5.1",
|
||||
"socket.io-client": "^2.3.0",
|
||||
"styled-components": "^4.4.1",
|
||||
"uuid": "^3.4.0"
|
||||
"uuid": "^3.4.0",
|
||||
"@dbgate/engines": "^0.1.0"
|
||||
},
|
||||
"scripts": {
|
||||
"start": "cross-env PORT=5000 react-scripts start",
|
||||
|
||||
@@ -4,6 +4,7 @@ import styled from 'styled-components';
|
||||
import theme from '../theme';
|
||||
import AceEditor from 'react-ace';
|
||||
import useDimensions from '../utility/useDimensions';
|
||||
import engines from '@dbgate/engines';
|
||||
|
||||
const Wrapper = styled.div`
|
||||
position: absolute;
|
||||
@@ -23,6 +24,11 @@ export default function TableCreateScriptTab({ conid, database, schemaName, pure
|
||||
params: { conid, database, schemaName, pureName },
|
||||
});
|
||||
|
||||
/** @type {import('@dbgate/types').EngineDriver} */
|
||||
const driver = engines('mssql');
|
||||
const dumper = driver.createDumper();
|
||||
dumper.putCmd('^select * ^from %f', { schemaName, pureName });
|
||||
|
||||
return (
|
||||
<Wrapper ref={containerRef}>
|
||||
<AceEditor
|
||||
@@ -31,7 +37,7 @@ export default function TableCreateScriptTab({ conid, database, schemaName, pure
|
||||
// onChange={onChange}
|
||||
name="UNIQUE_ID_OF_DIV"
|
||||
editorProps={{ $blockScrolling: true }}
|
||||
value={sql}
|
||||
value={dumper.s}
|
||||
readOnly
|
||||
fontSize="11pt"
|
||||
width={`${width}px`}
|
||||
|
||||
Reference in New Issue
Block a user