diff --git a/packages/api/src/controllers/sqlgen.js b/packages/api/src/controllers/sqlgen.js new file mode 100644 index 000000000..a7756a8d4 --- /dev/null +++ b/packages/api/src/controllers/sqlgen.js @@ -0,0 +1,19 @@ +const databaseConnections = require('./databaseConnections'); +const connections = require('./connections'); +const requireEngineDriver = require('../utility/requireEngineDriver'); +const { SqlGenerator } = require('dbgate-tools') + +module.exports = { + preview_meta: { + method: 'post', + }, + async preview({ conid, database, objects, options }) { + const structure = await databaseConnections.structure({ conid, database }) + const connection = await connections.get({ conid }) + const driver = requireEngineDriver(connection); + const dmp = driver.createDumper() + const generator = new SqlGenerator(structure, options, objects, dmp); + generator.dump(); + return dmp.s; + }, +}; diff --git a/packages/api/src/main.js b/packages/api/src/main.js index b96dbc809..63080f666 100644 --- a/packages/api/src/main.js +++ b/packages/api/src/main.js @@ -26,6 +26,7 @@ const uploads = require('./controllers/uploads'); const plugins = require('./controllers/plugins'); const files = require('./controllers/files'); const scheduler = require('./controllers/scheduler'); +const sqlgen = require('./controllers/sqlgen'); const { rundir } = require('./utility/directories'); @@ -72,6 +73,7 @@ function start(argument = null) { useController(app, '/plugins', plugins); useController(app, '/files', files); useController(app, '/scheduler', scheduler); + useController(app, '/sqlgen', sqlgen); // if (process.env.PAGES_DIRECTORY) { // app.use('/pages', express.static(process.env.PAGES_DIRECTORY)); diff --git a/packages/tools/src/SqlGenerator.ts b/packages/tools/src/SqlGenerator.ts new file mode 100644 index 000000000..ab5a0791a --- /dev/null +++ b/packages/tools/src/SqlGenerator.ts @@ -0,0 +1,62 @@ +import { DatabaseInfo, FunctionInfo, ProcedureInfo, TableInfo, ViewInfo } from 'dbgate-types'; +import { SqlDumper } from './SqlDumper'; + +interface SqlGeneratorOptions { + dropTables: boolean; + checkIfTableExists: boolean; + dropReferences: boolean; + createTables: boolean; + createReferences: boolean; + createForeignKeys: boolean; + createIndexes: boolean; + insert: boolean; + skipAutoincrementColumn: boolean; + disableConstraints: boolean; + omitNulls: boolean; + truncate: boolean; +} + +interface SqlGeneratorObject { + schemaName: string; + pureName: string; + objectTypeField: 'tables' | 'views' | 'procedures' | 'functions'; +} + +export class SqlGenerator { + private tables: TableInfo[]; + private views: ViewInfo[]; + private procedures: ProcedureInfo[]; + private functions: FunctionInfo[]; + constructor( + public dbinfo: DatabaseInfo, + public options: SqlGeneratorOptions, + public objects: SqlGeneratorObject[], + public dmp: SqlDumper + ) { + this.tables = this.extract('tables'); + this.views = this.extract('views'); + this.procedures = this.extract('procedures'); + this.functions = this.extract('functions'); + } + + checkDumper() { + return false; + } + + dump() { + if (this.options.createTables) { + for (const table of this.tables) { + this.dmp.createTable(table); + if (this.checkDumper()) return; + } + } + } + + extract(objectTypeField) { + return this.dbinfo[objectTypeField].filter(x => + this.objects.find( + y => x.pureName == y.pureName && x.schemaName == y.schemaName && y.objectTypeField == objectTypeField + ) + ); + } +} diff --git a/packages/tools/src/index.ts b/packages/tools/src/index.ts index 772f9e183..a5204138f 100644 --- a/packages/tools/src/index.ts +++ b/packages/tools/src/index.ts @@ -8,3 +8,4 @@ export * from './driverBase'; export * from './SqlDumper'; export * from './testPermission'; export * from './splitPostgresQuery'; +export * from './SqlGenerator'; diff --git a/packages/web/src/appobj/AppObjectCore.svelte b/packages/web/src/appobj/AppObjectCore.svelte index 00ff3aab2..fba5022cb 100644 --- a/packages/web/src/appobj/AppObjectCore.svelte +++ b/packages/web/src/appobj/AppObjectCore.svelte @@ -2,12 +2,14 @@ import FontIcon from '../icons/FontIcon.svelte'; import contextMenu from '../utility/contextMenu'; import { createEventDispatcher } from 'svelte'; + import CheckboxField from '../forms/CheckboxField.svelte'; const dispatch = createEventDispatcher(); export let icon; export let title; export let data; + export let module; export let isBold = false; export let isBusy = false; @@ -16,22 +18,54 @@ export let extInfo = undefined; export let menu = undefined; export let expandIcon = undefined; + export let checkedObjectsStore = null; + + $: isChecked = checkedObjectsStore && $checkedObjectsStore.find(x => module.extractKey(data) == module.extractKey(x)); function handleExpand() { dispatch('expand'); } + function handleClick() { + if (checkedObjectsStore) { + if (isChecked) { + checkedObjectsStore.update(x => x.filter(y => module.extractKey(data) != module.extractKey(y))); + } else { + checkedObjectsStore.update(x => [...x, data]); + } + } else { + dispatch('click'); + } + } + + function setChecked(value) { + if (!value && isChecked) { + checkedObjectsStore.update(x => x.filter(y => module.extractKey(data) != module.extractKey(y))); + } + if (value && !isChecked) { + checkedObjectsStore.update(x => [...x, data]); + } + }