diff --git a/packages/tools/src/SqlDumper.ts b/packages/tools/src/SqlDumper.ts index 7f2b29cc3..9c1a07325 100644 --- a/packages/tools/src/SqlDumper.ts +++ b/packages/tools/src/SqlDumper.ts @@ -294,12 +294,25 @@ export class SqlDumper implements AlterProcessor { }); this.put('&<&n)'); + + this.tableOptions(table); + this.endCommand(); (table.indexes || []).forEach(ix => { this.createIndex(ix); }); } + tableOptions(table: TableInfo) { + const options = this.driver.getTableFormOptions('sqlCreateTable'); + for (const option of options) { + if (table[option.name]) { + this.put('&n'); + this.put(option.sqlFormatString, table[option.name]); + } + } + } + createTablePrimaryKeyCore(table: TableInfo) { if (table.primaryKey) { this.put(',&n'); diff --git a/packages/types/engines.d.ts b/packages/types/engines.d.ts index 477bb784e..e3166bd0d 100644 --- a/packages/types/engines.d.ts +++ b/packages/types/engines.d.ts @@ -155,6 +155,11 @@ export interface EngineDriver extends FilterBehaviourProvider { collectionNameLabel?: string; newCollectionFormParams?: any[]; + getTableFormOptions(intent: 'newTableForm' | 'editTableForm' | 'sqlCreateTable' | 'sqlAlterTable'): { + name: string; + sqlFormatString: string; + }[]; + supportedCreateDatabase?: boolean; showConnectionField?: ( field: string, diff --git a/packages/web/src/elements/ObjectFieldsEditor.svelte b/packages/web/src/elements/ObjectFieldsEditor.svelte new file mode 100644 index 000000000..cc5dcf8ab --- /dev/null +++ b/packages/web/src/elements/ObjectFieldsEditor.svelte @@ -0,0 +1,67 @@ + + +
+
+ { + collapsed = !collapsed; + }} + > + + + {title} +
+ {#if !collapsed} + + + + {/if} +
+ + diff --git a/packages/web/src/forms/FormArgument.svelte b/packages/web/src/forms/FormArgument.svelte index ea1bd923d..a40fcfced 100644 --- a/packages/web/src/forms/FormArgument.svelte +++ b/packages/web/src/forms/FormArgument.svelte @@ -5,11 +5,15 @@ import FormSelectField from './FormSelectField.svelte'; import FormTextField from './FormTextField.svelte'; import FormStringList from './FormStringList.svelte'; + import FormDropDownTextField from './FormDropDownTextField.svelte'; + import { getFormContext } from './FormProviderCore.svelte'; export let arg; export let namePrefix; $: name = `${namePrefix}${arg.name}`; + + const { setFieldValue } = getFormContext(); {#if arg.type == 'text'} @@ -19,14 +23,10 @@ defaultValue={arg.default} focused={arg.focused} placeholder={arg.placeholder} + disabled={arg.disabled} /> {:else if arg.type == 'stringlist'} - + {:else if arg.type == 'number'} +{:else if arg.type == 'dropdowntext'} + { + return arg.options.map(opt => ({ + text: _.isString(opt) ? opt : opt.name, + onClick: () => setFieldValue(name, _.isString(opt) ? opt : opt.value), + })); + }} + /> {/if} diff --git a/packages/web/src/tableeditor/TableEditor.svelte b/packages/web/src/tableeditor/TableEditor.svelte index 7863e0709..27d24d5a2 100644 --- a/packages/web/src/tableeditor/TableEditor.svelte +++ b/packages/web/src/tableeditor/TableEditor.svelte @@ -81,6 +81,7 @@ import IndexEditorModal from './IndexEditorModal.svelte'; import PrimaryKeyEditorModal from './PrimaryKeyEditorModal.svelte'; import UniqueEditorModal from './UniqueEditorModal.svelte'; + import ObjectFieldsEditor from '../elements/ObjectFieldsEditor.svelte'; export const activator = createActivator('TableEditor', true); @@ -154,9 +155,24 @@ tableInfo; invalidateCommands(); } + + $: tableFormOptions = driver?.getTableFormOptions(tableInfo?.objectId ? 'editTableForm' : 'newTableForm');
+ {#if tableFormOptions} + { + if (!_.isEmpty(vals)) { + setTableInfo(tbl => ({ ...tbl, ...vals })); + } + }} + /> + {/if} + ({ ...x, ordinal: index + 1 }))} title={`Columns (${columns?.length || 0})`} diff --git a/plugins/dbgate-plugin-clickhouse/src/frontend/driver.js b/plugins/dbgate-plugin-clickhouse/src/frontend/driver.js index 242c858df..2d24f47aa 100644 --- a/plugins/dbgate-plugin-clickhouse/src/frontend/driver.js +++ b/plugins/dbgate-plugin-clickhouse/src/frontend/driver.js @@ -3,6 +3,53 @@ const Dumper = require('./Dumper'); const { mysqlSplitterOptions } = require('dbgate-query-splitter/lib/options'); const _cloneDeepWith = require('lodash/cloneDeepWith'); +const clickhouseEngines = [ + 'MergeTree', + 'ReplacingMergeTree', + 'SummingMergeTree', + 'AggregatingMergeTree', + 'CollapsingMergeTree', + 'VersionedCollapsingMergeTree', + 'GraphiteMergeTree', + 'Distributed', + 'Log', + 'TinyLog', + 'StripeLog', + 'Memory', + 'File', + 'URL', + 'JDBC', + 'ODBC', + 'Buffer', + 'Null', + 'Kafka', + 'HDFS', + 'S3', + 'Merge', + 'Join', + 'MaterializedView', + 'Dictionary', + 'MySQL', + 'PostgreSQL', + 'MongoDB', + 'EmbeddedRocksDB', + 'View', + 'MaterializeMySQL', + 'MaterializePostgreSQL', + 'ReplicatedMergeTree', + 'ReplicatedReplacingMergeTree', + 'ReplicatedSummingMergeTree', + 'ReplicatedAggregatingMergeTree', + 'ReplicatedCollapsingMergeTree', + 'ReplicatedVersionedCollapsingMergeTree', + 'ReplicatedGraphiteMergeTree', + 'ExternalDistributed', + 'Iceberg', + 'Parquet', + 'ORC', + 'DeltaLake', +]; + /** @type {import('dbgate-types').SqlDialect} */ const dialect = { limitSelect: true, @@ -70,6 +117,26 @@ const driver = { } return res; }, + + getTableFormOptions: (intent) => { + const isNewTable = intent == 'newTableForm'; + return [ + { + type: isNewTable ? 'dropdowntext' : text, + options: clickhouseEngines, + label: 'Engine', + name: 'tableEngine', + sqlFormatString: '^engine = %s', + disabled: !isNewTable, + }, + { + type: 'text', + label: 'Comment', + name: 'objectComment', + sqlFormatString: '^comment %v', + }, + ]; + }, }; module.exports = driver;