From 9ec0faa0f410d764b6ece47a8b38686d3737c82d Mon Sep 17 00:00:00 2001 From: qianmoQ Date: Mon, 27 Jun 2022 16:27:38 +0800 Subject: [PATCH 01/20] Supports quick query of PostgreSQL --- electron-builder.yml | 62 ++++--------------- package.json | 2 +- .../query/quick/quick.query.component.ts | 5 ++ .../config/plugin/postgresql.config.ts | 14 ++++- 4 files changed, 31 insertions(+), 52 deletions(-) diff --git a/electron-builder.yml b/electron-builder.yml index dbd6f9b6..7273066d 100644 --- a/electron-builder.yml +++ b/electron-builder.yml @@ -1,64 +1,26 @@ appId: 'io.edurt.dbm' + artifactName: ${name}-${version}-${os}-${arch}.${ext} + productName: 'dbm' -publish: { provider: github, releaseType: draft, vPrefixedTagName: true } + +publish: { + provider: github, + releaseType: draft, + vPrefixedTagName: true +} + forceCodeSigning: false releaseInfo: releaseNotes: | - #### General - - --- - - - Add multiple editor theme - - Redesign data source deletion prompt - - Support metadata management to jump to the query page - - Delete the domain name incubator tag - - Add some trend charts and project badges - - Fix that the editor cannot boot when it automatically prompts for multiple options, and the option is highlighted - - Compressed and packaged binary software package - - #### Security - - --- - - - Upgrade angular to `14.0.1` - - Upgrade electron to `16.2.0` - - #### ClickHouse - - --- - - - Support the currently stopped running process - #### Trino & Presto - - --- - - - Supports query result time and total number of data [issues-158](https://github.com/EdurtIO/dbm/issues/158) - - #### MySQL - - --- - - - Support quick query operation [issues-180](https://github.com/EdurtIO/dbm/issues/180) - - Supports query result time and total number of data [issues-180](https://github.com/EdurtIO/dbm/issues/180) - - Supports monitor → processors [issues-180](https://github.com/EdurtIO/dbm/issues/180) - - Supports monitor → connection [issues-180](https://github.com/EdurtIO/dbm/issues/180) - - Supports metadata management of disk usage [issues-180](https://github.com/EdurtIO/dbm/issues/180) - - Support metadata management menu server related operations [issues-180](https://github.com/EdurtIO/dbm/issues/180) - - #### PostgreSQL - - --- - - - Support PostgreSQL (custom query and data source management) - - Add PostgreSQL docs directories: output: ./release + files: -# - '**/*' + # - '**/*' - '!**/*.ts' - '!scripts' - '!src' @@ -68,7 +30,9 @@ files: - '!.github' - '!.vscode' - 'dist' + compression: normal + asar: false mac: diff --git a/package.json b/package.json index 284db4a6..abc62489 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dbm", - "version": "1.19.0", + "version": "1.20.0-SNAPSHOT", "author": "qianmoQ ", "description": "DataBase GUI", "github": "https://github.com/EdurtIO/dbm.git", diff --git a/src/renderer/components/query/quick/quick.query.component.ts b/src/renderer/components/query/quick/quick.query.component.ts index 97cbdd3d..639488a0 100644 --- a/src/renderer/components/query/quick/quick.query.component.ts +++ b/src/renderer/components/query/quick/quick.query.component.ts @@ -67,6 +67,11 @@ export class QuickQueryComponent extends BaseComponent { } else { this.spanSize = 8; } + + if (request.config.type === DatabaseEnum.postgresql) { + request.config.database = this.database; + } + switch (quick) { case QuickEnum.database: this.disabled.dialog = true; diff --git a/src/renderer/config/plugin/postgresql.config.ts b/src/renderer/config/plugin/postgresql.config.ts index e974e5cc..2efc6085 100644 --- a/src/renderer/config/plugin/postgresql.config.ts +++ b/src/renderer/config/plugin/postgresql.config.ts @@ -6,7 +6,12 @@ export class PostgresqlConfig implements BaseConfig { connectionFetchAll: string; databaseCreate: string; databaseDiskUsedRatio: string; - databaseFetchAll: string; + databaseFetchAll = ` + SELECT datname AS name + FROM pg_database + WHERE datistemplate = false + GROUP BY datname + `; databaseItems: string; databaseItemsFilterFuzzy: string; databaseItemsFilterPrecise: string; @@ -16,7 +21,12 @@ export class PostgresqlConfig implements BaseConfig { serverInfo: string; slowQueryFetchAll: string; tableDiskUsedRatio: string; - tableFetchAll: string; + tableFetchAll = ` + SELECT table_name AS name + FROM information_schema.tables + WHERE table_type = 'BASE TABLE' + AND table_schema = 'public' + `; tableItems: string; tableItemsFilterFuzzy: string; tableItemsFilterPrecise: string; From 2220785e85797b0da4595e52a74545c6ec59e73b Mon Sep 17 00:00:00 2001 From: qianmoQ Date: Tue, 28 Jun 2022 00:50:48 +0800 Subject: [PATCH 02/20] Support metadata management to build data tables for MySQL #180 --- src/renderer/assets/i18n/en.json | 3 +- src/renderer/assets/i18n/zh.json | 3 +- .../table/create/table.create.component.ts | 21 +- src/renderer/config/operation.config.ts | 6 +- src/renderer/config/table.config.json | 320 ------------------ src/renderer/config/table.config.ts | 136 ++++++-- src/renderer/enum/database.enum.ts | 1 + src/renderer/services/builder/base.builder.ts | 6 + .../services/builder/clickhouse.builder.ts | 124 +++++++ .../services/builder/default.builder.ts | 52 +++ src/renderer/services/factory.service.ts | 11 + .../services/management/table.service.ts | 225 ++++-------- 12 files changed, 393 insertions(+), 515 deletions(-) delete mode 100644 src/renderer/config/table.config.json create mode 100644 src/renderer/services/builder/base.builder.ts create mode 100644 src/renderer/services/builder/clickhouse.builder.ts create mode 100644 src/renderer/services/builder/default.builder.ts diff --git a/src/renderer/assets/i18n/en.json b/src/renderer/assets/i18n/en.json index b3943f92..90b8be44 100644 --- a/src/renderer/assets/i18n/en.json +++ b/src/renderer/assets/i18n/en.json @@ -233,7 +233,8 @@ "jdbc": "Allows ClickHouse to connect to external databases via JDBC", "sqlite": "The engine allows to import and export data to SQLite and supports queries to SQLite tables directly from ClickHouse.", "odbc": "Allows ClickHouse to connect to external databases via ODBC", - "mongodb": "MongoDB engine is read-only table engine which allows to read data (SELECT queries) from remote MongoDB collection. Engine supports only non-nested data types. INSERT queries are not supported." + "mongodb": "MongoDB engine is read-only table engine which allows to read data (SELECT queries) from remote MongoDB collection. Engine supports only non-nested data types. INSERT queries are not supported.", + "default": "Default table engine" }, "property": { "timeSeconds": "Retention time in RAM (unit per second)", diff --git a/src/renderer/assets/i18n/zh.json b/src/renderer/assets/i18n/zh.json index 6f0c8520..74e7ffc4 100644 --- a/src/renderer/assets/i18n/zh.json +++ b/src/renderer/assets/i18n/zh.json @@ -234,7 +234,8 @@ "jdbc": "允许ClickHouse通过JDBC连接到外部数据库", "sqlite": "The engine allows to import and export data to SQLite and supports queries to SQLite tables directly from ClickHouse.", "odbc": "Allows ClickHouse to connect to external databases via ODBC", - "mongodb": "MongoDB engine is read-only table engine which allows to read data (SELECT queries) from remote MongoDB collection. Engine supports only non-nested data types. INSERT queries are not supported." + "mongodb": "MongoDB engine is read-only table engine which allows to read data (SELECT queries) from remote MongoDB collection. Engine supports only non-nested data types. INSERT queries are not supported.", + "default": "默认表引擎" }, "property": { "timeSeconds": "Retention time in RAM (unit per second)", diff --git a/src/renderer/components/table/create/table.create.component.ts b/src/renderer/components/table/create/table.create.component.ts index e13d05a6..39360acb 100644 --- a/src/renderer/components/table/create/table.create.component.ts +++ b/src/renderer/components/table/create/table.create.component.ts @@ -1,4 +1,4 @@ -import { Component, EventEmitter, Input, Output } from '@angular/core'; +import { AfterViewInit, Component, EventEmitter, Input, Output } from '@angular/core'; import { BaseComponent } from '@renderer/app/base.component'; import { TableConfig } from '@renderer/config/table.config'; import { ColumnModel } from '@renderer/model/column.model'; @@ -15,7 +15,7 @@ import { NzMessageService } from 'ng-zorro-antd/message'; selector: 'app-component-create-table', templateUrl: './table.create.component.html' }) -export class CreateTableComponent extends BaseComponent { +export class CreateTableComponent extends BaseComponent implements AfterViewInit { @Input() config: ConfigModel; @Input() @@ -23,7 +23,7 @@ export class CreateTableComponent extends BaseComponent { @Output() emitter = new EventEmitter(); current = 0; - tableEngines: DatabaseModel[]; + tableEngines: DatabaseModel[] = new Array(); configure: DatabaseModel; selectValue: string; columns: ColumnModel[] = new Array(); @@ -33,7 +33,6 @@ export class CreateTableComponent extends BaseComponent { private dataSourceService: DatasourceService, private messageService: NzMessageService) { super(); - this.tableEngines = new TableConfig().getConfigFromJson(); this.columnTypes.push('Int8', 'Int16', 'Int32', @@ -54,6 +53,20 @@ export class CreateTableComponent extends BaseComponent { 'BIGINT'); } + ngAfterViewInit(): void { + setTimeout(() => { + this.dataSourceService.getByAliasAsync(this.config.value).then(response => { + new TableConfig().getConfig() + .forEach(item => { + item.engines = item.engines.filter(engine => engine.supportedSource.find(value => value === response.type) !== undefined) + if (item.engines.length > 0) { + this.tableEngines.push(item); + } + }); + }); + }, 0); + } + handlerChange(value: DatabaseModel) { this.configure = cloneDeep(value); } diff --git a/src/renderer/config/operation.config.ts b/src/renderer/config/operation.config.ts index 1f25faae..4c8fef32 100644 --- a/src/renderer/config/operation.config.ts +++ b/src/renderer/config/operation.config.ts @@ -31,7 +31,11 @@ export class OperationConfig { database.name = TypeEnum.database.toString(); database.type = TypeEnum.database; database.operations = [ - {type: TypeEnum.table, actions: [OperationEnum.create], supportedSource: [DatabaseEnum.clickhosue]}, + { + type: TypeEnum.table, + actions: [OperationEnum.create], + supportedSource: [DatabaseEnum.clickhosue, DatabaseEnum.mysql] + }, {type: TypeEnum.table, actions: [OperationEnum.filter], supportedSource: [DatabaseEnum.clickhosue]}, {type: TypeEnum.database, actions: [OperationEnum.delete], supportedSource: [DatabaseEnum.clickhosue]}, {type: TypeEnum.database, actions: [OperationEnum.structure], supportedSource: [DatabaseEnum.clickhosue]}, diff --git a/src/renderer/config/table.config.json b/src/renderer/config/table.config.json deleted file mode 100644 index 38ef0a0c..00000000 --- a/src/renderer/config/table.config.json +++ /dev/null @@ -1,320 +0,0 @@ -[ - { - "name": "common.log", - "description": "tooltip.table.log", - "engines": [ - { - "name": "common.log", - "description": "tooltip.table.log", - "type": "Log", - "properties": null - }, - { - "name": "common.tinylog", - "description": "tooltip.table.log", - "type": "TinyLog", - "properties": null - }, - { - "name": "common.stripelog", - "description": "tooltip.table.log", - "type": "StripeLog", - "properties": null - } - ] - }, - { - "name": "common.integration", - "description": "tooltip.table.integration", - "engines": [ - { - "name": "Kafka", - "description": "tooltip.table.kafka", - "type": "Kafka", - "properties": [ - { - "name": "broker", - "label": "common.broker", - "placeholder": "placeholder.broker", - "tooltip": "tooltip.property.broker", - "origin": "kafka_broker_list", - "required": true - }, - { - "name": "kafka", - "label": "common.topic", - "placeholder": "placeholder.topic", - "tooltip": "tooltip.property.topic", - "origin": "kafka_topic_list", - "required": true - }, - { - "name": "group", - "label": "common.group", - "placeholder": "placeholder.group", - "tooltip": "tooltip.property.group", - "origin": "kafka_group_name", - "required": true - }, - { - "name": "format", - "label": "common.format", - "placeholder": "placeholder.format", - "tooltip": "tooltip.property.format", - "origin": "kafka_format", - "required": true - } - ], - "optionalProperties": [ - { - "name": "rowDelimiter", - "label": "common.rowDelimiter", - "placeholder": "placeholder.rowDelimiter", - "tooltip": "tooltip.property.rowDelimiter", - "origin": "kafka_row_delimiter", - "required": false - }, - { - "name": "schema", - "label": "common.schema", - "placeholder": "placeholder.schema", - "tooltip": "tooltip.property.schema", - "origin": "kafka_schema", - "required": false - }, - { - "name": "numOfConsumer", - "label": "common.numOfConsumer", - "placeholder": "placeholder.numOfConsumer", - "tooltip": "tooltip.property.numOfConsumer", - "origin": "kafka_num_consumers", - "required": false - }, - { - "name": "maxBlockSize", - "label": "common.maxBlockSize", - "placeholder": "placeholder.maxBlockSize", - "tooltip": "tooltip.property.maxBlockSize", - "origin": "kafka_max_block_size", - "required": false - }, - { - "name": "skipBrokenMessages", - "label": "common.skipBrokenMessages", - "placeholder": "placeholder.skipBrokenMessages", - "tooltip": "tooltip.property.skipBrokenMessages", - "origin": "kafka_skip_broken_messages", - "required": false - }, - { - "name": "commitEveryBatch", - "label": "common.commitEveryBatch", - "placeholder": "placeholder.commitEveryBatch", - "tooltip": "tooltip.property.commitEveryBatch", - "origin": "kafka_commit_every_batch", - "required": false - }, - { - "name": "threadPerConsumer", - "label": "common.threadPerConsumer", - "placeholder": "placeholder.threadPerConsumer", - "tooltip": "tooltip.property.threadPerConsumer", - "origin": "kafka_thread_per_consumer", - "required": false - } - ], - "experimental": false, - "propertyType": "key" - }, - { - "name": "HDFS", - "description": "tooltip.table.hdfs", - "type": "HDFS", - "properties": [ - { - "name": "uri", - "label": "common.uri", - "placeholder": "placeholder.uri", - "tooltip": "tooltip.property.uri", - "origin": null, - "isSetting": false, - "required": true - }, - { - "name": "format", - "label": "common.format", - "placeholder": "placeholder.format", - "tooltip": "tooltip.property.format", - "origin": null, - "isSetting": false, - "required": true - } - ], - "experimental": false, - "propertyType": "name" - }, - { - "name": "JDBC", - "description": "tooltip.table.jdbc", - "type": "JDBC", - "properties": [ - { - "name": "uri", - "label": "common.uri", - "placeholder": "placeholder.uri", - "tooltip": "tooltip.property.uri", - "origin": null, - "isSetting": false, - "required": true - }, - { - "name": "database", - "label": "common.database", - "placeholder": "placeholder.database", - "tooltip": "tooltip.property.database", - "origin": null, - "isSetting": false, - "required": true - }, - { - "name": "table", - "label": "common.table", - "placeholder": "placeholder.table", - "tooltip": "tooltip.property.table", - "origin": null, - "isSetting": false, - "required": true - } - ], - "experimental": false, - "propertyType": "name" - }, - { - "name": "SQLite", - "description": "tooltip.table.sqlite", - "type": "SQLite", - "properties": [ - { - "name": "path", - "label": "common.path", - "placeholder": "placeholder.path", - "tooltip": "tooltip.property.path", - "origin": null, - "isSetting": false, - "required": true - }, - { - "name": "table", - "label": "common.table", - "placeholder": "placeholder.table", - "tooltip": "tooltip.property.table", - "origin": null, - "isSetting": false, - "required": true - } - ], - "experimental": false, - "propertyType": "name" - }, - { - "name": "ODBC", - "description": "tooltip.table.odbc", - "type": "ODBC", - "properties": [ - { - "name": "path", - "label": "common.path", - "placeholder": "placeholder.setting", - "tooltip": "tooltip.property.setting.odbc", - "origin": null, - "isSetting": false, - "required": true - }, - { - "name": "database", - "label": "common.database", - "placeholder": "placeholder.database", - "tooltip": "tooltip.property.database", - "origin": null, - "isSetting": false, - "required": true - }, - { - "name": "table", - "label": "common.table", - "placeholder": "placeholder.table", - "tooltip": "tooltip.property.table", - "origin": null, - "isSetting": false, - "required": true - } - ], - "experimental": false, - "propertyType": "name" - }, - { - "name": "MongoDB", - "description": "tooltip.table.mongodb", - "type": "MongoDB", - "properties": [ - { - "name": "uri", - "label": "common.uri", - "placeholder": "placeholder.uri", - "tooltip": "tooltip.property.mongodb.uri", - "origin": null, - "isSetting": false, - "required": true - }, - { - "name": "database", - "label": "common.database", - "placeholder": "tooltip.property.mongodb.database", - "tooltip": "tooltip.property.mongodb.database", - "origin": null, - "isSetting": false, - "required": true - }, - { - "name": "collection", - "label": "common.collection", - "placeholder": "placeholder.collection", - "tooltip": "tooltip.property.mongodb.collection", - "origin": null, - "isSetting": false, - "required": true - }, - { - "name": "username", - "label": "common.username", - "placeholder": "tooltip.property.mongodb.username", - "tooltip": "tooltip.property.mongodb.username", - "origin": null, - "isSetting": false, - "required": true - }, - { - "name": "password", - "label": "common.password", - "placeholder": "tooltip.property.mongodb.password", - "tooltip": "tooltip.property.mongodb.password", - "origin": null, - "isSetting": false, - "required": true - }, - { - "name": "options", - "label": "common.options", - "placeholder": "tooltip.property.mongodb.options", - "tooltip": "tooltip.property.mongodb.options", - "origin": null, - "isSetting": false, - "required": false - } - ], - "experimental": false, - "propertyType": "name" - } - ] - } -] diff --git a/src/renderer/config/table.config.ts b/src/renderer/config/table.config.ts index 9625f17b..bbdf2cb9 100644 --- a/src/renderer/config/table.config.ts +++ b/src/renderer/config/table.config.ts @@ -6,12 +6,27 @@ import { TranslateUtils } from '@renderer/utils/translate.utils'; import { PropertyModel } from '@renderer/model/property.model'; import { PropertyEnum } from '@renderer/enum/property.enum'; -const tableConfigJson = require('./table.config.json'); - @Injectable() export class TableConfig { getConfig(): DatabaseModel[] { const tableEngines = new Array(); + /** + * Default Engine + */ + const defaultTable = new DatabaseModel(); + defaultTable.name = TranslateUtils.getValue('common.default'); + defaultTable.description = TranslateUtils.getValue('tooltip.table.default'); + defaultTable.supportedSource = [DatabaseEnum.mysql]; + const defaultEngines = new Array(); + const i_default = DatabaseModel.builder(TranslateUtils.getValue('common.default'), + TranslateUtils.getValue('tooltip.table.default'), + DatabaseEnum.none, + null) + i_default.supportedSource = [DatabaseEnum.mysql]; + defaultEngines.push(i_default); + defaultTable.engines = defaultEngines; + tableEngines.push(defaultTable); + /** * Log Engine */ @@ -19,29 +34,42 @@ export class TableConfig { logTable.name = StringUtils.format('{0}', [TranslateUtils.getValue('common.log')]); logTable.description = TranslateUtils.getValue('tooltip.table.log'); + logTable.supportedSource = [DatabaseEnum.clickhosue]; const logEngines = new Array(); + // Log - logEngines.push(DatabaseModel.builder(TranslateUtils.getValue('common.log'), + const log = DatabaseModel.builder(TranslateUtils.getValue('common.log'), TranslateUtils.getValue('tooltip.table.log'), DatabaseEnum.log, - null)); + null) + log.supportedSource = [DatabaseEnum.clickhosue]; + logEngines.push(log); + // TinyLog - logEngines.push(DatabaseModel.builder(TranslateUtils.getValue('common.tinylog'), + const tinylog = DatabaseModel.builder(TranslateUtils.getValue('common.tinylog'), TranslateUtils.getValue('tooltip.table.log'), DatabaseEnum.tinylog, - null)); + null) + tinylog.supportedSource = [DatabaseEnum.clickhosue]; + logEngines.push(tinylog); + // StripeLog - logEngines.push(DatabaseModel.builder(TranslateUtils.getValue('common.stripelog'), + const stripelog = DatabaseModel.builder(TranslateUtils.getValue('common.stripelog'), TranslateUtils.getValue('tooltip.table.log'), DatabaseEnum.stripelog, - null)); + null); + stripelog.supportedSource = [DatabaseEnum.clickhosue]; + logEngines.push(stripelog); logTable.engines = logEngines; tableEngines.push(logTable); + const integrationTable = new DatabaseModel(); integrationTable.name = StringUtils.format('{0}', [TranslateUtils.getValue('common.integration')]); integrationTable.description = TranslateUtils.getValue('tooltip.table.integration'); + integrationTable.supportedSource = [DatabaseEnum.clickhosue]; const integrationEngines = new Array(); + // Kafka const kafkaProperties = new Array(); kafkaProperties.push(PropertyModel.builder('broker', @@ -64,12 +92,15 @@ export class TableConfig { TranslateUtils.getValue('placeholder.format'), TranslateUtils.getValue('tooltip.property.format'), 'kafka_format')); - integrationEngines.push(DatabaseModel.builder(DatabaseEnum.kafka.toString(), + const kafka = DatabaseModel.builder(DatabaseEnum.kafka.toString(), TranslateUtils.getValue('tooltip.table.kafka'), DatabaseEnum.kafka, kafkaProperties, false, - PropertyEnum.key)); + PropertyEnum.key); + kafka.supportedSource = [DatabaseEnum.clickhosue]; + integrationEngines.push(kafka); + // HDFS const hdfsProperties = new Array(); hdfsProperties.push(PropertyModel.builder('uri', @@ -84,12 +115,15 @@ export class TableConfig { TranslateUtils.getValue('tooltip.property.format'), null, false)); - integrationEngines.push(DatabaseModel.builder(DatabaseEnum.hdfs.toString(), + const hdfs = DatabaseModel.builder(DatabaseEnum.hdfs.toString(), TranslateUtils.getValue('tooltip.table.hdfs'), DatabaseEnum.hdfs, hdfsProperties, false, - PropertyEnum.name)); + PropertyEnum.name); + hdfs.supportedSource = [DatabaseEnum.clickhosue]; + integrationEngines.push(hdfs); + // JDBC const jdbcProperties = new Array(); jdbcProperties.push(PropertyModel.builder('uri', @@ -110,12 +144,15 @@ export class TableConfig { TranslateUtils.getValue('tooltip.property.table'), null, false)); - integrationEngines.push(DatabaseModel.builder(DatabaseEnum.jdbc.toString(), + const jdbc = DatabaseModel.builder(DatabaseEnum.jdbc.toString(), TranslateUtils.getValue('tooltip.table.jdbc'), DatabaseEnum.jdbc, jdbcProperties, false, - PropertyEnum.name)); + PropertyEnum.name); + jdbc.supportedSource = [DatabaseEnum.clickhosue]; + integrationEngines.push(jdbc); + // SQLite const sqliteProperties = new Array(); sqliteProperties.push(PropertyModel.builder('path', @@ -130,12 +167,15 @@ export class TableConfig { TranslateUtils.getValue('tooltip.property.table'), null, false)); - integrationEngines.push(DatabaseModel.builder(DatabaseEnum.sqlite.toString(), + const sqlite = DatabaseModel.builder(DatabaseEnum.sqlite.toString(), TranslateUtils.getValue('tooltip.table.sqlite'), DatabaseEnum.sqlite, sqliteProperties, false, - PropertyEnum.name)); + PropertyEnum.name); + sqlite.supportedSource = [DatabaseEnum.clickhosue]; + integrationEngines.push(sqlite); + // ODBC const odbcProperties = new Array(); odbcProperties.push(PropertyModel.builder('path', @@ -156,18 +196,70 @@ export class TableConfig { TranslateUtils.getValue('tooltip.property.table'), null, false)); - integrationEngines.push(DatabaseModel.builder(DatabaseEnum.odbc.toString(), + const odbc = DatabaseModel.builder(DatabaseEnum.odbc.toString(), TranslateUtils.getValue('tooltip.table.odbc'), DatabaseEnum.odbc, odbcProperties, false, - PropertyEnum.name)); + PropertyEnum.name); + odbc.supportedSource = [DatabaseEnum.clickhosue]; + integrationEngines.push(odbc); + + // MongoDB + const mongodbProperties = new Array(); + mongodbProperties.push(PropertyModel.builder('uri', + TranslateUtils.getValue('common.uri'), + TranslateUtils.getValue('placeholder.uri'), + TranslateUtils.getValue('tooltip.property.mongodb.uri'), + null, + false, + true)); + mongodbProperties.push(PropertyModel.builder('database', + TranslateUtils.getValue('common.database'), + TranslateUtils.getValue('tooltip.property.mongodb.database'), + TranslateUtils.getValue('tooltip.property.mongodb.database'), + null, + false, + true)); + mongodbProperties.push(PropertyModel.builder('collection', + TranslateUtils.getValue('common.collection'), + TranslateUtils.getValue('placeholder.collection'), + TranslateUtils.getValue('tooltip.property.mongodb.collection'), + null, + false, + true)); + mongodbProperties.push(PropertyModel.builder('username', + TranslateUtils.getValue('common.username'), + TranslateUtils.getValue('tooltip.property.mongodb.username'), + TranslateUtils.getValue('tooltip.property.mongodb.username'), + null, + false, + true)); + mongodbProperties.push(PropertyModel.builder('password', + TranslateUtils.getValue('common.password'), + TranslateUtils.getValue('tooltip.property.mongodb.password'), + TranslateUtils.getValue('tooltip.property.mongodb.password'), + null, + false, + true)); + mongodbProperties.push(PropertyModel.builder('options', + TranslateUtils.getValue('common.options'), + TranslateUtils.getValue('tooltip.property.mongodb.options'), + TranslateUtils.getValue('tooltip.property.mongodb.options'), + null, + false, + false)); + const mongodb = DatabaseModel.builder(DatabaseEnum.mongodb.toString(), + TranslateUtils.getValue('tooltip.table.mongodb'), + DatabaseEnum.mongodb, + mongodbProperties, + false, + PropertyEnum.name); + mongodb.supportedSource = [DatabaseEnum.clickhosue]; + integrationEngines.push(mongodb); + integrationTable.engines = integrationEngines; tableEngines.push(integrationTable); return tableEngines; } - - getConfigFromJson(): DatabaseModel[] { - return tableConfigJson; - } } diff --git a/src/renderer/enum/database.enum.ts b/src/renderer/enum/database.enum.ts index 3ec733d2..a9d45b6a 100644 --- a/src/renderer/enum/database.enum.ts +++ b/src/renderer/enum/database.enum.ts @@ -14,6 +14,7 @@ export enum DatabaseEnum { jdbc = 'JDBC', sqlite = 'SQLite', odbc = 'ODBC', + mongodb = 'MongoDB', // DataSource Type clickhosue = 'ClickHouse', diff --git a/src/renderer/services/builder/base.builder.ts b/src/renderer/services/builder/base.builder.ts new file mode 100644 index 00000000..b7d6f70f --- /dev/null +++ b/src/renderer/services/builder/base.builder.ts @@ -0,0 +1,6 @@ +import { DatabaseModel } from "@renderer/model/database.model"; +import { ColumnModel } from "@renderer/model/column.model"; + +export interface BaseBuilder { + builder(configure: DatabaseModel, columns: ColumnModel[]): string; +} diff --git a/src/renderer/services/builder/clickhouse.builder.ts b/src/renderer/services/builder/clickhouse.builder.ts new file mode 100644 index 00000000..061fb673 --- /dev/null +++ b/src/renderer/services/builder/clickhouse.builder.ts @@ -0,0 +1,124 @@ +import { BaseBuilder } from "@renderer/services/builder/base.builder"; +import { StringUtils } from "@renderer/utils/string.utils"; +import { SqlUtils } from "@renderer/utils/sql.utils"; +import { ColumnModel } from "@renderer/model/column.model"; +import { PropertyModel } from "@renderer/model/property.model"; +import { DatabaseModel } from "@renderer/model/database.model"; +import { PropertyEnum } from "@renderer/enum/property.enum"; + +export class ClickhouseBuilder implements BaseBuilder { + public builder(configure: DatabaseModel, columns: ColumnModel[]): string { + let sql = StringUtils.format('CREATE TABLE {0} (\n', [SqlUtils.getTableName(configure.database, configure.targetName)]); + sql += StringUtils.format('{0}\n', [this.builderColumnsToString(columns)]); + sql += StringUtils.format(') {0}\n', [this.builderEngine(configure)]); + const mergeProperties = this.mergeProperties(configure); + sql += this.builderProperties(mergeProperties); + return sql; + } + + builderColumnsToString(columns: ColumnModel[]): string { + let columnStr = ''; + columns.forEach((value, index) => { + if (index !== columns.length - 1) { + columnStr += this.builderColumnToString(value, true); + } else { + columnStr += this.builderColumnToString(value, false); + } + }); + return columnStr; + } + + builderColumnToString(value: ColumnModel, end: boolean): string { + let column: string; + let dStr: string; + if (value.empty) { + dStr = StringUtils.format(' {0} Nullable({1})', [value.name, value.type]); + } else { + dStr = StringUtils.format(' {0} {1}', [value.name, value.type]); + } + const endStr = end ? ',\n' : ''; + if (StringUtils.isNotEmpty(value.description)) { + column = StringUtils.format(` {0} COMMENT '{1}' {2}`, [dStr, value.description, endStr]); + } else { + column = StringUtils.format(' {0} {1}', [dStr, endStr]); + } + return column; + } + + /** + * Build key-value pairs based on configured table engine parameters + * @param properties Configuration parameters + * @returns sql string + */ + private builderProperties(properties: PropertyModel[]): string { + let substr: string = ''; + // const map = this.flatProperties(properties); + // map.forEach((v, k) => { + // if (k !== 'type') { + // substr += StringUtils.format('\n {0} = \'{1}\',', [k, v]); + // } + // }); + properties + .filter(p => p.origin !== undefined && StringUtils.isNotEmpty(p.origin)) + .filter(p => p.value !== undefined) + .forEach(p => { + substr += StringUtils.format('\n {0} = \'{1}\',', [p.origin, p.value]); + }); + if (StringUtils.isNotEmpty(substr)) { + substr = StringUtils.format('SETTINGS {0}', [substr.substring(0, substr.length - 1)]); + } + return substr; + } + + private builderEngine(configure: DatabaseModel): string { + let sql: string = ''; + const prefix = '\nENGINE = '; + switch (configure.propertyType) { + case PropertyEnum.key: + default: + sql = StringUtils.format('{0} {1}()', [prefix, configure.type]); + break; + case PropertyEnum.name: + const substr = configure.properties + .filter(element => StringUtils.isNotEmpty(element.value)) + .flatMap(element => StringUtils.format('\'{0}\'', [element.value])) + .join(', '); + sql = StringUtils.format('{0} {1}({2})', [prefix, configure.type, substr]); + break; + } + return sql; + } + + private flatProperties(properties: PropertyModel[]): Map { + const map = new Map(); + properties + .filter(p => p.isSetting === undefined || p.isSetting) + .forEach(p => { + if (StringUtils.isNotEmpty(p.origin)) { + map.set('type', PropertyEnum.key); + map.set(p.origin, p.value); + } else { + map.set('type', PropertyEnum.name); + map.set(p.name, p.value); + } + }); + return map; + } + + /** + * Merges required and optional configurations + * @param configure Data model configuration + * @private merges array + */ + private mergeProperties(configure: DatabaseModel): PropertyModel[] { + let applyArray = new Array(); + if (configure?.properties) { + applyArray = applyArray.concat(configure.properties); + } + const filterOptionalProperties = configure.optionalProperties?.filter(element => StringUtils.isNotEmpty(element.value)); + if (filterOptionalProperties) { + applyArray = applyArray.concat(filterOptionalProperties); + } + return applyArray; + } +} diff --git a/src/renderer/services/builder/default.builder.ts b/src/renderer/services/builder/default.builder.ts new file mode 100644 index 00000000..d2975118 --- /dev/null +++ b/src/renderer/services/builder/default.builder.ts @@ -0,0 +1,52 @@ +import { BaseBuilder } from "@renderer/services/builder/base.builder"; +import { DatabaseModel } from "@renderer/model/database.model"; +import { ColumnModel } from "@renderer/model/column.model"; +import { StringUtils } from "@renderer/utils/string.utils"; +import { SqlUtils } from "@renderer/utils/sql.utils"; + +export class DefaultBuilder implements BaseBuilder { + builder(configure: DatabaseModel, columns: ColumnModel[]): string { + let sql = this.builderPrefix(configure); + sql += this.builderColumns(columns); + sql += this.builderSuffix(); + return sql; + } + + builderPrefix(configure: DatabaseModel): string { + return StringUtils.format('CREATE TABLE {0} (\n', + [SqlUtils.getTableName(configure.database, configure.targetName)]); + } + + builderColumns(columns: ColumnModel[]): string { + let columnStr = ''; + columns.forEach((value, index) => { + if (index !== columns.length - 1) { + columnStr += this.builderColumnToString(value, true); + } else { + columnStr += this.builderColumnToString(value, false); + } + }); + return columnStr; + } + + builderColumnToString(value: ColumnModel, end: boolean): string { + let column: string; + let dStr: string; + if (value.empty) { + dStr = StringUtils.format(' {0} {1} NOT NULL', [value.name, value.type]); + } else { + dStr = StringUtils.format(' {0} {1}', [value.name, value.type]); + } + const endStr = end ? ',\n' : ''; + if (StringUtils.isNotEmpty(value.description)) { + column = StringUtils.format(` {0} COMMENT '{1}' {2}`, [dStr, value.description, endStr]); + } else { + column = StringUtils.format(' {0} {1}', [dStr, endStr]); + } + return column; + } + + builderSuffix(): string { + return ')'; + } +} diff --git a/src/renderer/services/factory.service.ts b/src/renderer/services/factory.service.ts index 728f58ab..593ac614 100644 --- a/src/renderer/services/factory.service.ts +++ b/src/renderer/services/factory.service.ts @@ -4,6 +4,8 @@ import { ClickhouseConfig } from "@renderer/config/clickhouse.config"; import { PrestoConfig } from "@renderer/config/presto.config"; import { MySQLConfig } from "@renderer/config/plugin/mysql.config"; import { PostgresqlConfig } from "@renderer/config/plugin/postgresql.config"; +import { DefaultBuilder } from "@renderer/services/builder/default.builder"; +import { ClickhouseBuilder } from "@renderer/services/builder/clickhouse.builder"; export class FactoryService { public forward(type: string) { @@ -22,4 +24,13 @@ export class FactoryService { return null; } } + + public forwardBuilder(type: string) { + switch (type) { + case DatabaseEnum.clickhosue: + return Factory.create(ClickhouseBuilder); + default: + return Factory.create(DefaultBuilder); + } + } } diff --git a/src/renderer/services/management/table.service.ts b/src/renderer/services/management/table.service.ts index 77d0d64f..8e4384c2 100644 --- a/src/renderer/services/management/table.service.ts +++ b/src/renderer/services/management/table.service.ts @@ -1,28 +1,28 @@ -import {Injectable} from '@angular/core'; -import {LogicEnum} from '@renderer/enum/logic.enum'; -import {PropertyEnum} from '@renderer/enum/property.enum'; -import {ColumnModel} from '@renderer/model/column.model'; -import {DatabaseModel} from '@renderer/model/database.model'; -import {PropertyModel} from '@renderer/model/property.model'; -import {RequestModel} from '@renderer/model/request.model'; -import {ResponseModel} from '@renderer/model/response.model'; -import {BaseService} from '@renderer/services/base.service'; -import {HttpService} from '@renderer/services/http.service'; -import {SqlUtils} from '@renderer/utils/sql.utils'; -import {StringUtils} from '@renderer/utils/string.utils'; -import {TableTtlModel} from '@renderer/model/table/table.ttl.model'; -import {SshService} from '@renderer/services/ssh.service'; -import {BasicService} from '@renderer/services/system/basic.service'; -import {ForwardService} from '@renderer/services/forward.service'; -import {FactoryService} from "@renderer/services/factory.service"; +import { Injectable } from '@angular/core'; +import { LogicEnum } from '@renderer/enum/logic.enum'; +import { ColumnModel } from '@renderer/model/column.model'; +import { DatabaseModel } from '@renderer/model/database.model'; +import { RequestModel } from '@renderer/model/request.model'; +import { ResponseModel } from '@renderer/model/response.model'; +import { BaseService } from '@renderer/services/base.service'; +import { HttpService } from '@renderer/services/http.service'; +import { SqlUtils } from '@renderer/utils/sql.utils'; +import { StringUtils } from '@renderer/utils/string.utils'; +import { TableTtlModel } from '@renderer/model/table/table.ttl.model'; +import { SshService } from '@renderer/services/ssh.service'; +import { BasicService } from '@renderer/services/system/basic.service'; +import { ForwardService } from '@renderer/services/forward.service'; +import { FactoryService } from "@renderer/services/factory.service"; +import { MySQLService } from "@renderer/services/plugin/mysql.service"; @Injectable() export class TableService extends ForwardService implements BaseService { constructor(httpService: HttpService, factoryService: FactoryService, sshService: SshService, - basicService: BasicService) { - super(basicService, factoryService, httpService, sshService); + basicService: BasicService, + mysqlService: MySQLService) { + super(basicService, factoryService, httpService, sshService, null, mysqlService); } getResponse(request: RequestModel, sql?: string): Promise { @@ -36,35 +36,28 @@ export class TableService extends ForwardService implements BaseService { check(request: RequestModel, database: string, table: string): Promise { const sql = StringUtils.format(` - SELECT - name - FROM - system.tables - WHERE - database = '{0}' AND name = '{1}' - `, [database, table]); + SELECT name + FROM system.tables + WHERE database = '{0}' + AND name = '{1}' + `, [database, table]); return this.getResponse(request, sql); } getSize(request: RequestModel, database: string, table: string): Promise { const sql = StringUtils.format(` - SELECT - database AS db, table AS name, SUM(bytes_on_disk) AS tableUsedBytes, - formatReadableSize(sum(bytes_on_disk)) AS value, - if(SUM(bytes_on_disk) > (1024*1024*1024*50), 1, 0) AS flag - FROM system.parts + SELECT database AS db, table AS name, SUM (bytes_on_disk) AS tableUsedBytes, + formatReadableSize(sum (bytes_on_disk)) AS value, + if(SUM (bytes_on_disk) > (1024*1024*1024*50), 1, 0) AS flag + FROM system.parts WHERE database = '{0}' AND name = '{1}' GROUP BY db, name - `, [database, table]); + `, [database, table]); return this.getResponse(request, sql); } createTable(request: RequestModel, configure: DatabaseModel, columns: ColumnModel[]): Promise { - let sql = StringUtils.format('CREATE TABLE {0} (\n', [SqlUtils.getTableName(configure.database, configure.targetName)]); - sql += StringUtils.format('{0}\n', [this.builderColumnsToString(columns)]); - sql += StringUtils.format(') {0}\n', [this.builderEngine(configure)]); - const mergeProperties = this.mergeProperties(configure); - sql += this.builderProperties(mergeProperties); + const sql = this.factoryService.forwardBuilder(request.config.type).builder(configure, columns); return this.getResponse(request, sql); } @@ -74,7 +67,8 @@ export class TableService extends ForwardService implements BaseService { } rename(request: RequestModel, value: DatabaseModel, newName: string): Promise { - const sql = StringUtils.format('RENAME TABLE {0} TO {1}', [SqlUtils.getTableName(value.database, value.name), SqlUtils.getTableName(value.database, newName)]); + const sql = StringUtils.format('RENAME TABLE {0} TO {1}', + [SqlUtils.getTableName(value.database, value.name), SqlUtils.getTableName(value.database, newName)]); return this.getResponse(request, sql); } @@ -104,9 +98,10 @@ export class TableService extends ForwardService implements BaseService { getPartitions(request: RequestModel, value: DatabaseModel, partition?: string, logic?: LogicEnum): Promise { let sql = StringUtils.format(` - SELECT - DISTINCT "partition" AS "partition", partition_id AS id, - engine, SUM(rows) AS rows, formatReadableSize(SUM(bytes_on_disk)) AS size + SELECT DISTINCT "partition" AS "partition", + partition_id AS id, + engine, + SUM(rows) AS rows, formatReadableSize(SUM(bytes_on_disk)) AS size FROM "system".parts WHERE @@ -116,30 +111,35 @@ export class TableService extends ForwardService implements BaseService { ORDER BY "partition" ASC`, [value.database, value.name]); if (StringUtils.isNotEmpty(partition) && StringUtils.isNotEmpty(logic)) { sql = StringUtils.format(` - SELECT - DISTINCT "partition" AS "partition", partition_id AS id, - engine, SUM(rows) AS rows, formatReadableSize(SUM(bytes_on_disk)) AS size - FROM - "system".parts - WHERE - "database" = '{0}' - AND "table" = '{1}' - AND "partition" {2} '{3}' - GROUP BY "partition", partition_id, engine - ORDER BY "partition" ASC`, [value.database, value.name, logic, partition]); + SELECT DISTINCT "partition" AS "partition", + partition_id AS id, + engine, + SUM(rows) AS rows, formatReadableSize(SUM(bytes_on_disk)) AS size + FROM + "system".parts + WHERE + "database" = '{0}' + AND "table" = '{1}' + AND "partition" {2} '{3}' + GROUP BY "partition", partition_id, engine + ORDER BY "partition" ASC`, [value.database, value.name, logic, partition]); } return this.getResponse(request, sql); } getPreview(request: RequestModel, value: DatabaseModel): Promise { - const sql = StringUtils.format(`SELECT * FROM {0} LIMIT 10`, [SqlUtils.getTableName(value.database, value.name)]); + const sql = StringUtils.format(`SELECT * + FROM {0} LIMIT 10`, [SqlUtils.getTableName(value.database, value.name)]); return this.getResponse(request, sql); } getTimeColumns(request: RequestModel, value: DatabaseModel): Promise { const sql = StringUtils.format(` - SELECT name FROM "system"."columns" - WHERE "database" = '{0}' AND "table" = '{1}' AND type like 'Date%'`, + SELECT name + FROM "system"."columns" + WHERE "database" = '{0}' + AND "table" = '{1}' + AND type like 'Date%'`, [value.database, value.name]); return this.getResponse(request, sql); } @@ -158,17 +158,16 @@ export class TableService extends ForwardService implements BaseService { getTTL(request: RequestModel, value: TableTtlModel): Promise { const sql = StringUtils.format(` - SELECT - extract(engine_full, 'TTL [\\s\\S]*ETTINGS') AS full, + SELECT extract(engine_full, 'TTL [\\s\\S]*ETTINGS') AS full, REPLACE(REPLACE(full, 'TTL', ''), ' SETTINGS', '') AS ttl, splitByString('+', ttl) AS ttlArray, trimBoth(arrayElement(ttlArray, 1)) AS "column", extract(arrayElement(ttlArray, 2), '\\d+') AS value, splitByString('(', replace(arrayElement(ttlArray, 2), 'toInterval', '')) AS rangerArray, upperUTF8(arrayElement(rangerArray, 1)) AS ranger - FROM "system"."tables" - WHERE "database" = '{0}' AND "name" = '{1}' - `, + FROM "system"."tables" + WHERE "database" = '{0}' AND "name" = '{1}' + `, [value.database, value.table]); return this.getResponse(request, sql); } @@ -178,110 +177,4 @@ export class TableService extends ForwardService implements BaseService { [SqlUtils.getAlterTablePrefix(value.database, value.table)]); return this.getResponse(request, sql); } - - builderColumnsToString(columns: ColumnModel[]): string { - let columnStr = ''; - columns.forEach((value, index) => { - if (index !== columns.length - 1) { - columnStr += this.builderColumnToString(value, true); - } else { - columnStr += this.builderColumnToString(value, false); - } - }); - return columnStr; - } - - builderColumnToString(value: ColumnModel, end: boolean): string { - let column: string; - let dStr: string; - if (value.empty) { - dStr = StringUtils.format(' {0} Nullable({1})', [value.name, value.type]); - } else { - dStr = StringUtils.format(' {0} {1}', [value.name, value.type]); - } - const endStr = end ? ',\n' : ''; - if (StringUtils.isNotEmpty(value.description)) { - column = StringUtils.format(` {0} COMMENT '{1}' {2}`, [dStr, value.description, endStr]); - } else { - column = StringUtils.format(' {0} {1}', [dStr, endStr]); - } - return column; - } - - /** - * Build key-value pairs based on configured table engine parameters - * @param properties Configuration parameters - * @returns sql string - */ - private builderProperties(properties: PropertyModel[]): string { - let substr: string = ''; - // const map = this.flatProperties(properties); - // map.forEach((v, k) => { - // if (k !== 'type') { - // substr += StringUtils.format('\n {0} = \'{1}\',', [k, v]); - // } - // }); - properties - .filter(p => p.origin !== undefined && StringUtils.isNotEmpty(p.origin)) - .filter(p => p.value !== undefined) - .forEach(p => { - substr += StringUtils.format('\n {0} = \'{1}\',', [p.origin, p.value]); - }); - if (StringUtils.isNotEmpty(substr)) { - substr = StringUtils.format('SETTINGS {0}', [substr.substring(0, substr.length - 1)]); - } - return substr; - } - - private builderEngine(configure: DatabaseModel): string { - let sql: string = ''; - const prefix = '\nENGINE = '; - switch (configure.propertyType) { - case PropertyEnum.key: - default: - sql = StringUtils.format('{0} {1}()', [prefix, configure.type]); - break; - case PropertyEnum.name: - const substr = configure.properties - .filter(element => StringUtils.isNotEmpty(element.value)) - .flatMap(element => StringUtils.format('\'{0}\'', [element.value])) - .join(', '); - sql = StringUtils.format('{0} {1}({2})', [prefix, configure.type, substr]); - break; - } - return sql; - } - - private flatProperties(properties: PropertyModel[]): Map { - const map = new Map(); - properties - .filter(p => p.isSetting === undefined || p.isSetting) - .forEach(p => { - if (StringUtils.isNotEmpty(p.origin)) { - map.set('type', PropertyEnum.key); - map.set(p.origin, p.value); - } else { - map.set('type', PropertyEnum.name); - map.set(p.name, p.value); - } - }); - return map; - } - - /** - * Merges required and optional configurations - * @param configure Data model configuration - * @private merges array - */ - private mergeProperties(configure: DatabaseModel): PropertyModel[] { - let applyArray = new Array(); - if (configure?.properties) { - applyArray = applyArray.concat(configure.properties); - } - const filterOptionalProperties = configure.optionalProperties?.filter(element => StringUtils.isNotEmpty(element.value)); - if (filterOptionalProperties) { - applyArray = applyArray.concat(filterOptionalProperties); - } - return applyArray; - } } From 4b395b82a23b694a4ace7acebf5856972b4892ae Mon Sep 17 00:00:00 2001 From: qianmoQ Date: Tue, 28 Jun 2022 10:41:05 +0800 Subject: [PATCH 03/20] Support metadata management to filter tables for MySQL #180 --- src/renderer/config/operation.config.ts | 6 +++++- src/renderer/config/plugin/mysql.config.ts | 12 ++++++++++-- 2 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/renderer/config/operation.config.ts b/src/renderer/config/operation.config.ts index 4c8fef32..1bb56cb5 100644 --- a/src/renderer/config/operation.config.ts +++ b/src/renderer/config/operation.config.ts @@ -36,7 +36,11 @@ export class OperationConfig { actions: [OperationEnum.create], supportedSource: [DatabaseEnum.clickhosue, DatabaseEnum.mysql] }, - {type: TypeEnum.table, actions: [OperationEnum.filter], supportedSource: [DatabaseEnum.clickhosue]}, + { + type: TypeEnum.table, + actions: [OperationEnum.filter], + supportedSource: [DatabaseEnum.clickhosue, DatabaseEnum.mysql] + }, {type: TypeEnum.database, actions: [OperationEnum.delete], supportedSource: [DatabaseEnum.clickhosue]}, {type: TypeEnum.database, actions: [OperationEnum.structure], supportedSource: [DatabaseEnum.clickhosue]}, {type: TypeEnum.database, actions: [OperationEnum.rename], supportedSource: [DatabaseEnum.clickhosue]} diff --git a/src/renderer/config/plugin/mysql.config.ts b/src/renderer/config/plugin/mysql.config.ts index e7cf5ad5..131c31a9 100644 --- a/src/renderer/config/plugin/mysql.config.ts +++ b/src/renderer/config/plugin/mysql.config.ts @@ -93,8 +93,16 @@ FROM information_schema.tables WHERE table_schema = '{0}' GROUP BY TABLE_NAME `; - tableItemsFilterFuzzy: string; - tableItemsFilterPrecise: string; + tableItemsFilterFuzzy = ` +SELECT table_name AS name +FROM information_schema.tables +WHERE table_schema = '{0}' AND table_name LIKE '%{1}%' + `; + tableItemsFilterPrecise = ` +SELECT table_name AS name +FROM information_schema.tables +WHERE table_schema = '{0}' AND table_name = '{1}' + `; tableSchemaFetchAll: string; version = `SELECT version() AS version`; stopProcessor: string; From 9156fdfcef9f916332f7b8e1a208288ae2968848 Mon Sep 17 00:00:00 2001 From: qianmoQ Date: Tue, 28 Jun 2022 11:02:29 +0800 Subject: [PATCH 04/20] Support metadata management to show database ddl for MySQL #180 --- .../database/structure/database.structure.component.ts | 7 ++++++- src/renderer/config/base.config.ts | 1 + src/renderer/config/operation.config.ts | 6 +++++- src/renderer/config/{ => plugin}/clickhouse.config.ts | 1 + src/renderer/config/plugin/mysql.config.ts | 1 + src/renderer/config/plugin/postgresql.config.ts | 1 + src/renderer/config/{ => plugin}/presto.config.ts | 1 + src/renderer/services/factory.service.ts | 4 ++-- src/renderer/services/management/metadata.service.ts | 4 +--- 9 files changed, 19 insertions(+), 7 deletions(-) rename src/renderer/config/{ => plugin}/clickhouse.config.ts (98%) rename src/renderer/config/{ => plugin}/presto.config.ts (98%) diff --git a/src/renderer/components/database/structure/database.structure.component.ts b/src/renderer/components/database/structure/database.structure.component.ts index 0c9ff8a8..8655fef3 100644 --- a/src/renderer/components/database/structure/database.structure.component.ts +++ b/src/renderer/components/database/structure/database.structure.component.ts @@ -9,6 +9,7 @@ import { ClipboardComService } from '@renderer/services/other/clipboard.service' import { EditorService } from '@renderer/services/editor/editor.service'; import { SystemEditorModel } from '@renderer/model/system.model'; import { SqlUtils } from '@renderer/utils/sql.utils'; +import { DatabaseEnum } from "@renderer/enum/database.enum"; @Component({ selector: 'app-component-database-structure', @@ -54,7 +55,11 @@ export class DatabaseStructureComponent extends BaseComponent implements AfterVi request.config = await this.dataSourceService.getByAliasAsync(this.config.value); this.metadataService.getDatabaseDDL(request, this.value).then(response => { if (response.status) { - this.structure = response?.data?.columns[0]?.statement; + if (request.config.type === DatabaseEnum.mysql) { + this.structure = response?.data?.columns[0]?.['Create Database']; + } else { + this.structure = response?.data?.columns[0]?.statement; + } } else { this.messageService.error(response.message); } diff --git a/src/renderer/config/base.config.ts b/src/renderer/config/base.config.ts index 0a528c48..10c23d93 100644 --- a/src/renderer/config/base.config.ts +++ b/src/renderer/config/base.config.ts @@ -21,4 +21,5 @@ export interface BaseConfig { columnItems: string; serverInfo: string; stopProcessor: string; + showCreateDatabase: string; } diff --git a/src/renderer/config/operation.config.ts b/src/renderer/config/operation.config.ts index 1bb56cb5..f0db6787 100644 --- a/src/renderer/config/operation.config.ts +++ b/src/renderer/config/operation.config.ts @@ -42,7 +42,11 @@ export class OperationConfig { supportedSource: [DatabaseEnum.clickhosue, DatabaseEnum.mysql] }, {type: TypeEnum.database, actions: [OperationEnum.delete], supportedSource: [DatabaseEnum.clickhosue]}, - {type: TypeEnum.database, actions: [OperationEnum.structure], supportedSource: [DatabaseEnum.clickhosue]}, + { + type: TypeEnum.database, + actions: [OperationEnum.structure], + supportedSource: [DatabaseEnum.clickhosue, DatabaseEnum.mysql] + }, {type: TypeEnum.database, actions: [OperationEnum.rename], supportedSource: [DatabaseEnum.clickhosue]} ]; opertions.push(database); diff --git a/src/renderer/config/clickhouse.config.ts b/src/renderer/config/plugin/clickhouse.config.ts similarity index 98% rename from src/renderer/config/clickhouse.config.ts rename to src/renderer/config/plugin/clickhouse.config.ts index 63fbb374..99cc3da0 100644 --- a/src/renderer/config/clickhouse.config.ts +++ b/src/renderer/config/plugin/clickhouse.config.ts @@ -158,4 +158,5 @@ DESC {0}.{1} SELECT * FROM system.build_options `; stopProcessor = `KILL QUERY WHERE query_id = '{0}'`; + showCreateDatabase = 'SHOW CREATE DATABASE `{0}`'; } diff --git a/src/renderer/config/plugin/mysql.config.ts b/src/renderer/config/plugin/mysql.config.ts index 131c31a9..354d6f27 100644 --- a/src/renderer/config/plugin/mysql.config.ts +++ b/src/renderer/config/plugin/mysql.config.ts @@ -106,4 +106,5 @@ WHERE table_schema = '{0}' AND table_name = '{1}' tableSchemaFetchAll: string; version = `SELECT version() AS version`; stopProcessor: string; + showCreateDatabase = 'SHOW CREATE DATABASE `{0}`'; } diff --git a/src/renderer/config/plugin/postgresql.config.ts b/src/renderer/config/plugin/postgresql.config.ts index 2efc6085..dbcdd02a 100644 --- a/src/renderer/config/plugin/postgresql.config.ts +++ b/src/renderer/config/plugin/postgresql.config.ts @@ -33,4 +33,5 @@ export class PostgresqlConfig implements BaseConfig { tableSchemaFetchAll: string; version = `SELECT current_setting('server_version') AS version`; stopProcessor: string; + showCreateDatabase: string; } diff --git a/src/renderer/config/presto.config.ts b/src/renderer/config/plugin/presto.config.ts similarity index 98% rename from src/renderer/config/presto.config.ts rename to src/renderer/config/plugin/presto.config.ts index f385bfda..56cbf3d1 100644 --- a/src/renderer/config/presto.config.ts +++ b/src/renderer/config/plugin/presto.config.ts @@ -63,4 +63,5 @@ LIMIT 100 tableItemsFilterPrecise: string; serverInfo = this.version; stopProcessor: string; + showCreateDatabase: string; } diff --git a/src/renderer/services/factory.service.ts b/src/renderer/services/factory.service.ts index 593ac614..c3afb135 100644 --- a/src/renderer/services/factory.service.ts +++ b/src/renderer/services/factory.service.ts @@ -1,11 +1,11 @@ import { DatabaseEnum } from "@renderer/enum/database.enum"; import { Factory } from "@renderer/factory"; -import { ClickhouseConfig } from "@renderer/config/clickhouse.config"; -import { PrestoConfig } from "@renderer/config/presto.config"; import { MySQLConfig } from "@renderer/config/plugin/mysql.config"; import { PostgresqlConfig } from "@renderer/config/plugin/postgresql.config"; import { DefaultBuilder } from "@renderer/services/builder/default.builder"; import { ClickhouseBuilder } from "@renderer/services/builder/clickhouse.builder"; +import { PrestoConfig } from "@renderer/config/plugin/presto.config"; +import { ClickhouseConfig } from "@renderer/config/plugin/clickhouse.config"; export class FactoryService { public forward(type: string) { diff --git a/src/renderer/services/management/metadata.service.ts b/src/renderer/services/management/metadata.service.ts index 62944cf3..08e99c94 100644 --- a/src/renderer/services/management/metadata.service.ts +++ b/src/renderer/services/management/metadata.service.ts @@ -5,8 +5,6 @@ import { ResponseModel } from '@renderer/model/response.model'; import { RequestModel } from '@renderer/model/request.model'; import { ConfigModel } from '@renderer/model/config.model'; import { TypeEnum } from '@renderer/enum/type.enum'; -import { ClickhouseConfig } from '@renderer/config/clickhouse.config'; -import { Factory } from '@renderer/factory'; import { StringUtils } from '@renderer/utils/string.utils'; import { DatabaseModel } from '@renderer/model/database.model'; import { DatabaseEnum } from '@renderer/enum/database.enum'; @@ -123,7 +121,7 @@ export class MetadataService extends ForwardService implements BaseService { } getDatabaseDDL(request: RequestModel, value: string): Promise { - const sql = StringUtils.format('SHOW CREATE DATABASE `{0}`', [value]); + const sql = StringUtils.format(this.factoryService.forward(request.config.type).showCreateDatabase, [value]); return this.getResponse(request, sql); } From 974c3be973199bdaed3bf12f429f057b40256a88 Mon Sep 17 00:00:00 2001 From: qianmoQ Date: Tue, 28 Jun 2022 16:00:02 +0800 Subject: [PATCH 05/20] Add semgrep ci --- .github/workflows/semgrep.yml | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) create mode 100644 .github/workflows/semgrep.yml diff --git a/.github/workflows/semgrep.yml b/.github/workflows/semgrep.yml new file mode 100644 index 00000000..65167d4d --- /dev/null +++ b/.github/workflows/semgrep.yml @@ -0,0 +1,16 @@ +name: Semgrep +on: + schedule: + - cron: '0 0 * * *' +jobs: + semgrep: + name: Scan + runs-on: ubuntu-20.04 + env: + SEMGREP_APP_TOKEN: ${{ secrets.SEMGREP_APP_TOKEN }} + container: + image: returntocorp/semgrep + if: (github.actor != 'dependabot[bot]') + steps: + - uses: actions/checkout@v3 + - run: semgrep ci From 909eb84489b1d6091d2361aa50bfbac8279dd4e7 Mon Sep 17 00:00:00 2001 From: qianmoQ Date: Wed, 29 Jun 2022 00:23:56 +0800 Subject: [PATCH 06/20] Support metadata management to delete database for MySQL #180 --- src/renderer/config/base.config.ts | 1 + src/renderer/config/operation.config.ts | 6 +++- .../config/plugin/clickhouse.config.ts | 6 ++++ src/renderer/config/plugin/mysql.config.ts | 8 +++++ .../config/plugin/postgresql.config.ts | 1 + src/renderer/config/plugin/presto.config.ts | 1 + .../services/management/database.service.ts | 36 ++++++++++--------- 7 files changed, 41 insertions(+), 18 deletions(-) diff --git a/src/renderer/config/base.config.ts b/src/renderer/config/base.config.ts index 10c23d93..434154db 100644 --- a/src/renderer/config/base.config.ts +++ b/src/renderer/config/base.config.ts @@ -22,4 +22,5 @@ export interface BaseConfig { serverInfo: string; stopProcessor: string; showCreateDatabase: string; + showTableWithSize: string; } diff --git a/src/renderer/config/operation.config.ts b/src/renderer/config/operation.config.ts index f0db6787..e7fced60 100644 --- a/src/renderer/config/operation.config.ts +++ b/src/renderer/config/operation.config.ts @@ -41,7 +41,11 @@ export class OperationConfig { actions: [OperationEnum.filter], supportedSource: [DatabaseEnum.clickhosue, DatabaseEnum.mysql] }, - {type: TypeEnum.database, actions: [OperationEnum.delete], supportedSource: [DatabaseEnum.clickhosue]}, + { + type: TypeEnum.database, + actions: [OperationEnum.delete], + supportedSource: [DatabaseEnum.clickhosue, DatabaseEnum.mysql] + }, { type: TypeEnum.database, actions: [OperationEnum.structure], diff --git a/src/renderer/config/plugin/clickhouse.config.ts b/src/renderer/config/plugin/clickhouse.config.ts index 99cc3da0..93870397 100644 --- a/src/renderer/config/plugin/clickhouse.config.ts +++ b/src/renderer/config/plugin/clickhouse.config.ts @@ -159,4 +159,10 @@ SELECT * FROM system.build_options `; stopProcessor = `KILL QUERY WHERE query_id = '{0}'`; showCreateDatabase = 'SHOW CREATE DATABASE `{0}`'; + showTableWithSize = ` +SELECT name, engine, total_rows AS totalRows, + formatReadableSize(total_bytes) AS totalSize +FROM system.tables +WHERE database = '{0}' + `; } diff --git a/src/renderer/config/plugin/mysql.config.ts b/src/renderer/config/plugin/mysql.config.ts index 354d6f27..c96eb753 100644 --- a/src/renderer/config/plugin/mysql.config.ts +++ b/src/renderer/config/plugin/mysql.config.ts @@ -107,4 +107,12 @@ WHERE table_schema = '{0}' AND table_name = '{1}' version = `SELECT version() AS version`; stopProcessor: string; showCreateDatabase = 'SHOW CREATE DATABASE `{0}`'; + showTableWithSize = ` +SELECT + TABLE_NAME AS name, ENGINE AS engine, TABLE_ROWS AS totalRows, + concat(round(sum(data_length/1024/1024),2), 'MB') AS totalSize +FROM information_schema.tables +WHERE table_schema = '{0}' +GROUP BY TABLE_NAME + `; } diff --git a/src/renderer/config/plugin/postgresql.config.ts b/src/renderer/config/plugin/postgresql.config.ts index dbcdd02a..3328ebd9 100644 --- a/src/renderer/config/plugin/postgresql.config.ts +++ b/src/renderer/config/plugin/postgresql.config.ts @@ -34,4 +34,5 @@ export class PostgresqlConfig implements BaseConfig { version = `SELECT current_setting('server_version') AS version`; stopProcessor: string; showCreateDatabase: string; + showTableWithSize: string; } diff --git a/src/renderer/config/plugin/presto.config.ts b/src/renderer/config/plugin/presto.config.ts index 56cbf3d1..08daaac5 100644 --- a/src/renderer/config/plugin/presto.config.ts +++ b/src/renderer/config/plugin/presto.config.ts @@ -64,4 +64,5 @@ LIMIT 100 serverInfo = this.version; stopProcessor: string; showCreateDatabase: string; + showTableWithSize: string; } diff --git a/src/renderer/services/management/database.service.ts b/src/renderer/services/management/database.service.ts index c3f46532..758a7a81 100644 --- a/src/renderer/services/management/database.service.ts +++ b/src/renderer/services/management/database.service.ts @@ -1,21 +1,23 @@ -import {Injectable} from '@angular/core'; -import {RequestModel} from '@renderer/model/request.model'; -import {ResponseModel} from '@renderer/model/response.model'; -import {BaseService} from '@renderer/services/base.service'; -import {HttpService} from '@renderer/services/http.service'; -import {StringUtils} from '@renderer/utils/string.utils'; -import {SshService} from '@renderer/services/ssh.service'; -import {BasicService} from '@renderer/services/system/basic.service'; -import {ForwardService} from '@renderer/services/forward.service'; -import {FactoryService} from "@renderer/services/factory.service"; +import { Injectable } from '@angular/core'; +import { RequestModel } from '@renderer/model/request.model'; +import { ResponseModel } from '@renderer/model/response.model'; +import { BaseService } from '@renderer/services/base.service'; +import { HttpService } from '@renderer/services/http.service'; +import { StringUtils } from '@renderer/utils/string.utils'; +import { SshService } from '@renderer/services/ssh.service'; +import { BasicService } from '@renderer/services/system/basic.service'; +import { ForwardService } from '@renderer/services/forward.service'; +import { FactoryService } from "@renderer/services/factory.service"; +import { MySQLService } from "@renderer/services/plugin/mysql.service"; @Injectable() export class DatabaseService extends ForwardService implements BaseService { constructor(httpService: HttpService, factoryService: FactoryService, sshService: SshService, - basicService: BasicService) { - super(basicService, factoryService, httpService, sshService); + basicService: BasicService, + mysqlService: MySQLService) { + super(basicService, factoryService, httpService, sshService, null, mysqlService); } getResponse(request: RequestModel, sql?: string): Promise { @@ -28,16 +30,16 @@ export class DatabaseService extends ForwardService implements BaseService { } getTables(request: RequestModel, database: string): Promise { - const sql = StringUtils.format(`SELECT name, engine, total_rows AS totalRows, formatReadableSize(total_bytes) AS totalSize FROM system.tables WHERE database = '{0}'`, - [database]); + const sql = StringUtils.format(this.factoryService.forward(request.config.type).showTableWithSize, [database]); return this.getResponse(request, sql); } getDatabase(request: RequestModel, database: string): Promise { const sql = StringUtils.format(` - SELECT - name, engine, uuid, - if(upperUTF8(engine) == 'ATOMIC', 1, 0) AS isSupport + SELECT name, + engine, + uuid, + if(upperUTF8(engine) == 'ATOMIC', 1, 0) AS isSupport FROM system.databases WHERE name = '{0}'`, [database]); return this.getResponse(request, sql); From 6e1215d4d1d50030e6b78f0bd3014ce2ad260be2 Mon Sep 17 00:00:00 2001 From: qianmoQ Date: Wed, 29 Jun 2022 00:39:15 +0800 Subject: [PATCH 07/20] Bump some dependencies --- package.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index abc62489..9d102406 100644 --- a/package.json +++ b/package.json @@ -54,7 +54,7 @@ "@dalongrong/presto-client": "^0.6.5", "@ngx-translate/core": "^14.0.0", "@ngx-translate/http-loader": "^7.0.0", - "angular-highcharts": "^13.0.1", + "angular-highcharts": "^14.1.5", "codemirror": "^5.64.0", "conventional-changelog-cli": "^2.1.1", "css-loader": "^6.7.1", @@ -109,14 +109,14 @@ "electron-reload": "1.5.0", "eslint": "7.29.0", "eslint-plugin-import": "2.23.4", - "eslint-plugin-jsdoc": "35.3.2", + "eslint-plugin-jsdoc": "^39.3.3", "eslint-plugin-prefer-arrow": "1.2.3", "jasmine-core": "~3.7.0", "karma": "~6.3.0", "karma-chrome-launcher": "~3.1.0", "karma-coverage": "~2.0.3", "karma-jasmine": "~5.0.1", - "karma-jasmine-html-reporter": "^1.5.0", + "karma-jasmine-html-reporter": "^2.0.0", "ts-loader": "^9.2.3", "typescript": "^4.2.4", "wait-on": "^5.3.0", From d6d9164ad743665a96ba2ce98588f8ab3c6791b6 Mon Sep 17 00:00:00 2001 From: qianmoQ Date: Wed, 29 Jun 2022 11:31:32 +0800 Subject: [PATCH 08/20] Support metadata management to preview table for MySQL #180 --- src/renderer/config/operation.config.ts | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/renderer/config/operation.config.ts b/src/renderer/config/operation.config.ts index e7fced60..e6c01dc6 100644 --- a/src/renderer/config/operation.config.ts +++ b/src/renderer/config/operation.config.ts @@ -58,7 +58,11 @@ export class OperationConfig { table.name = TypeEnum.table.toString(); table.type = TypeEnum.table; table.operations = [ - {type: TypeEnum.table, actions: [OperationEnum.preview], supportedSource: [DatabaseEnum.clickhosue]}, + { + type: TypeEnum.table, + actions: [OperationEnum.preview], + supportedSource: [DatabaseEnum.clickhosue, DatabaseEnum.mysql] + }, {type: TypeEnum.table, actions: [OperationEnum.delete], supportedSource: [DatabaseEnum.clickhosue]}, {type: TypeEnum.table, actions: [OperationEnum.structure], supportedSource: [DatabaseEnum.clickhosue]}, {type: TypeEnum.table, actions: [OperationEnum.rename], supportedSource: [DatabaseEnum.clickhosue]}, From 353af1ed8eae9ac075607392046cf4fd753623a7 Mon Sep 17 00:00:00 2001 From: qianmoQ Date: Wed, 29 Jun 2022 11:45:55 +0800 Subject: [PATCH 09/20] Support metadata management to show table ddl for MySQL #180 --- .../table/structure/table.structure.component.ts | 15 ++++++++++----- src/renderer/config/operation.config.ts | 6 +++++- 2 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/renderer/components/table/structure/table.structure.component.ts b/src/renderer/components/table/structure/table.structure.component.ts index f1f107f5..33389a03 100644 --- a/src/renderer/components/table/structure/table.structure.component.ts +++ b/src/renderer/components/table/structure/table.structure.component.ts @@ -10,6 +10,7 @@ import { TableService } from '@renderer/services/management/table.service'; import { ClipboardComService } from '@renderer/services/other/clipboard.service'; import { SqlUtils } from '@renderer/utils/sql.utils'; import { NzMessageService } from 'ng-zorro-antd/message'; +import { DatabaseEnum } from "@renderer/enum/database.enum"; @Component({ selector: 'app-component-structure-table', @@ -28,10 +29,10 @@ export class StructureTableComponent extends BaseComponent implements AfterViewI editorConfig: SystemEditorModel; constructor(private dataSourceService: DatasourceService, - private tableService: TableService, - private messageService: NzMessageService, - private clipboardComService: ClipboardComService, - private editorService: EditorService) { + private tableService: TableService, + private messageService: NzMessageService, + private clipboardComService: ClipboardComService, + private editorService: EditorService) { super(); this.editorConfig = this.editorService.get(); } @@ -57,7 +58,11 @@ export class StructureTableComponent extends BaseComponent implements AfterViewI _value.name = this.value; this.tableService.getCreateStatement(request, _value).then(response => { if (response.status) { - this.structure = response?.data?.columns[0]?.statement; + if (request.config.type === DatabaseEnum.mysql) { + this.structure = response?.data?.columns[0]?.['Create Table']; + } else { + this.structure = response?.data?.columns[0]?.statement; + } } else { this.messageService.error(response.message); } diff --git a/src/renderer/config/operation.config.ts b/src/renderer/config/operation.config.ts index e6c01dc6..e3ca7255 100644 --- a/src/renderer/config/operation.config.ts +++ b/src/renderer/config/operation.config.ts @@ -64,7 +64,11 @@ export class OperationConfig { supportedSource: [DatabaseEnum.clickhosue, DatabaseEnum.mysql] }, {type: TypeEnum.table, actions: [OperationEnum.delete], supportedSource: [DatabaseEnum.clickhosue]}, - {type: TypeEnum.table, actions: [OperationEnum.structure], supportedSource: [DatabaseEnum.clickhosue]}, + { + type: TypeEnum.table, + actions: [OperationEnum.structure], + supportedSource: [DatabaseEnum.clickhosue, DatabaseEnum.mysql] + }, {type: TypeEnum.table, actions: [OperationEnum.rename], supportedSource: [DatabaseEnum.clickhosue]}, {type: TypeEnum.table, actions: [OperationEnum.truncate], supportedSource: [DatabaseEnum.clickhosue]}, {type: TypeEnum.table, actions: [OperationEnum.clean], supportedSource: [DatabaseEnum.clickhosue]}, From 68045b15a3c475f714bc6c0b83335d22dc45d9e8 Mon Sep 17 00:00:00 2001 From: qianmoQ Date: Wed, 29 Jun 2022 14:32:10 +0800 Subject: [PATCH 10/20] Support metadata management to delete table for MySQL #180 --- .../table/delete/table.delete.component.ts | 21 ++++++++++++------- src/renderer/config/operation.config.ts | 6 +++++- 2 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/renderer/components/table/delete/table.delete.component.ts b/src/renderer/components/table/delete/table.delete.component.ts index a0eb090a..8e4ab46f 100644 --- a/src/renderer/components/table/delete/table.delete.component.ts +++ b/src/renderer/components/table/delete/table.delete.component.ts @@ -6,6 +6,7 @@ import { RequestModel } from '@renderer/model/request.model'; import { DatasourceService } from '@renderer/services/management/datasource.service'; import { TableService } from '@renderer/services/management/table.service'; import { NzMessageService } from 'ng-zorro-antd/message'; +import { DatabaseEnum } from "@renderer/enum/database.enum"; @Component({ selector: 'app-component-delete-table', @@ -34,14 +35,18 @@ export class DeleteTableComponent extends BaseComponent implements AfterViewInit setTimeout(async () => { const request = new RequestModel(); request.config = await this.dataSourceService.getByAliasAsync(this.config.value); - this.tableService.getSize(request, this.database, this.value) - .then(response => { - if (response.status) { - this.tableInfo = response.data?.columns[0]; - } else { - this.messageService.error(response.message); - } - }); + if (request.config.type === DatabaseEnum.clickhosue) { + this.tableService.getSize(request, this.database, this.value) + .then(response => { + if (response.status) { + this.tableInfo = response.data?.columns[0]; + } else { + this.messageService.error(response.message); + } + }); + } else { + this.tableInfo = { flag: 0 }; + } }, 0); } diff --git a/src/renderer/config/operation.config.ts b/src/renderer/config/operation.config.ts index e3ca7255..48155bd9 100644 --- a/src/renderer/config/operation.config.ts +++ b/src/renderer/config/operation.config.ts @@ -63,7 +63,11 @@ export class OperationConfig { actions: [OperationEnum.preview], supportedSource: [DatabaseEnum.clickhosue, DatabaseEnum.mysql] }, - {type: TypeEnum.table, actions: [OperationEnum.delete], supportedSource: [DatabaseEnum.clickhosue]}, + { + type: TypeEnum.table, + actions: [OperationEnum.delete], + supportedSource: [DatabaseEnum.clickhosue, DatabaseEnum.mysql] + }, { type: TypeEnum.table, actions: [OperationEnum.structure], From 2bbb45f4f5222809af89dcbb5005416ab6aaaf79 Mon Sep 17 00:00:00 2001 From: qianmoQ Date: Wed, 29 Jun 2022 21:12:28 +0800 Subject: [PATCH 11/20] Support metadata management to rename table, truncate table for MySQL #180 --- src/renderer/config/operation.config.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/renderer/config/operation.config.ts b/src/renderer/config/operation.config.ts index 48155bd9..cf6ff948 100644 --- a/src/renderer/config/operation.config.ts +++ b/src/renderer/config/operation.config.ts @@ -73,8 +73,16 @@ export class OperationConfig { actions: [OperationEnum.structure], supportedSource: [DatabaseEnum.clickhosue, DatabaseEnum.mysql] }, - {type: TypeEnum.table, actions: [OperationEnum.rename], supportedSource: [DatabaseEnum.clickhosue]}, - {type: TypeEnum.table, actions: [OperationEnum.truncate], supportedSource: [DatabaseEnum.clickhosue]}, + { + type: TypeEnum.table, + actions: [OperationEnum.rename], + supportedSource: [DatabaseEnum.clickhosue, DatabaseEnum.mysql] + }, + { + type: TypeEnum.table, + actions: [OperationEnum.truncate], + supportedSource: [DatabaseEnum.clickhosue, DatabaseEnum.mysql] + }, {type: TypeEnum.table, actions: [OperationEnum.clean], supportedSource: [DatabaseEnum.clickhosue]}, {type: TypeEnum.table, actions: [OperationEnum.optimize], supportedSource: [DatabaseEnum.clickhosue]}, { From 7acc3739ef404e4ea6e07188d702e6daee76aada Mon Sep 17 00:00:00 2001 From: qianmoQ Date: Thu, 30 Jun 2022 15:39:36 +0800 Subject: [PATCH 12/20] Support custom file names for downloading result data --- src/renderer/assets/i18n/en.json | 3 +- src/renderer/assets/i18n/zh.json | 3 +- .../table/basic/basic.table.component.html | 46 ++++++++++++++++--- .../table/basic/basic.table.component.ts | 35 +++++++++----- .../table/basic/table.export.enum.ts | 3 ++ .../table/basic/table.export.model.ts | 7 +++ 6 files changed, 77 insertions(+), 20 deletions(-) create mode 100644 src/renderer/components/table/basic/table.export.enum.ts create mode 100644 src/renderer/components/table/basic/table.export.model.ts diff --git a/src/renderer/assets/i18n/en.json b/src/renderer/assets/i18n/en.json index 90b8be44..cf24ce4c 100644 --- a/src/renderer/assets/i18n/en.json +++ b/src/renderer/assets/i18n/en.json @@ -167,7 +167,8 @@ "reset": "Reset", "mysql": "MySQL", "postgresql": "PostgreSQL", - "stop": "Stop" + "stop": "Stop", + "location": "Location" }, "language": { "english": "English", diff --git a/src/renderer/assets/i18n/zh.json b/src/renderer/assets/i18n/zh.json index 74e7ffc4..5cae7bed 100644 --- a/src/renderer/assets/i18n/zh.json +++ b/src/renderer/assets/i18n/zh.json @@ -166,7 +166,8 @@ "reset": "重置", "mysql": "MySQL", "postgresql": "PostgreSQL", - "stop": "停止" + "stop": "停止", + "location": "位置" }, "language": { "english": "英语", diff --git a/src/renderer/components/table/basic/basic.table.component.html b/src/renderer/components/table/basic/basic.table.component.html index 71af6f2d..3a469585 100644 --- a/src/renderer/components/table/basic/basic.table.component.html +++ b/src/renderer/components/table/basic/basic.table.component.html @@ -1,12 +1,12 @@
- - -
    -
  • {{'common.csv'|translate}}
  • -
-
+ + + + + @@ -20,3 +20,35 @@ + + + +  {{'common.export'|translate}}{{'common.result'|translate}} + +
+ + + {{'common.name'|translate}} + + + + + + {{'common.type'|translate}} + + + + + + + + + + +
+
diff --git a/src/renderer/components/table/basic/basic.table.component.ts b/src/renderer/components/table/basic/basic.table.component.ts index a58ed174..0305c9bd 100644 --- a/src/renderer/components/table/basic/basic.table.component.ts +++ b/src/renderer/components/table/basic/basic.table.component.ts @@ -2,11 +2,9 @@ import { AfterViewInit, Component, Input } from '@angular/core'; import { BaseComponent } from '@renderer/app/base.component'; import { Columns, Config, DefaultConfig } from 'ngx-easy-table'; import { ExportToCsv } from 'export-to-csv'; -import { StringUtils } from '@renderer/utils/string.utils'; -import { TranslateService } from '@ngx-translate/core'; import { Md5 } from 'ts-md5'; - -const lodash = require('lodash'); +import { TableExportModel } from "@renderer/components/table/basic/table.export.model"; +import { StringUtils } from "@renderer/utils/string.utils"; @Component({ selector: 'app-component-basic-table', @@ -18,14 +16,16 @@ export class BasicTableComponent extends BaseComponent implements AfterViewInit public configuration: Config; public headers: Columns[] = new Array(); public id: string; + exportInfo: TableExportModel; - constructor(private translateService: TranslateService) { + constructor() { super(); this.configuration = {...DefaultConfig}; this.configuration.horizontalScroll = true; this.configuration.paginationRangeEnabled = false; this.configuration.searchEnabled = true; this.id = Md5.hashStr(new Date().toString()); + this.exportInfo = new TableExportModel() } ngAfterViewInit(): void { @@ -33,23 +33,36 @@ export class BasicTableComponent extends BaseComponent implements AfterViewInit this.value?.headers.forEach(column => { this.headers.push({key: column.name, title: column.name}); }); + this.handlerValidate(); }, 0); } + handlerValidate() { + if (StringUtils.isNotEmpty(this.exportInfo.name)) { + this.disabled.button = false; + } else { + this.disabled.button = true; + } + } + + handlerDialog(isClose: boolean = false): void { + if (isClose) { + this.dialog.create = true; + } else { + this.dialog.create = false; + } + } + handlerExportToCSV(): void { - const filename = StringUtils.format('{0}{1}-{2}', - [this.translateService.instant('common.query'), - this.translateService.instant('common.result'), - lodash.now().toString()]); const options = { fieldSeparator: ',', - quoteStrings: '"', + quoteStrings: '', decimalSeparator: '.', showLabels: true, showTitle: false, useTextFile: false, useBom: true, - filename: filename, + filename: this.exportInfo.name, useKeysAsHeaders: true }; const csvExporter = new ExportToCsv(options); diff --git a/src/renderer/components/table/basic/table.export.enum.ts b/src/renderer/components/table/basic/table.export.enum.ts new file mode 100644 index 00000000..cde1934b --- /dev/null +++ b/src/renderer/components/table/basic/table.export.enum.ts @@ -0,0 +1,3 @@ +export enum TableExportEnum { + CSV= 'CSV' +} diff --git a/src/renderer/components/table/basic/table.export.model.ts b/src/renderer/components/table/basic/table.export.model.ts new file mode 100644 index 00000000..872de542 --- /dev/null +++ b/src/renderer/components/table/basic/table.export.model.ts @@ -0,0 +1,7 @@ +import { TableExportEnum } from "@renderer/components/table/basic/table.export.enum"; + +export class TableExportModel { + name: string; + type: TableExportEnum = TableExportEnum.CSV; + location: string; +} From dd08e5cb2a70b739cdc28cbfdd597ecd19a8b099 Mon Sep 17 00:00:00 2001 From: qianmoQ Date: Fri, 1 Jul 2022 15:35:59 +0800 Subject: [PATCH 13/20] Support metadata management to preview column for MySQL #180 --- src/renderer/config/operation.config.ts | 6 ++- .../services/management/column.service.ts | 37 ++++++++++--------- 2 files changed, 25 insertions(+), 18 deletions(-) diff --git a/src/renderer/config/operation.config.ts b/src/renderer/config/operation.config.ts index cf6ff948..b58d5c00 100644 --- a/src/renderer/config/operation.config.ts +++ b/src/renderer/config/operation.config.ts @@ -100,7 +100,11 @@ export class OperationConfig { column.name = TypeEnum.column.toString(); column.type = TypeEnum.column; column.operations = [ - {type: TypeEnum.column, actions: [OperationEnum.preview], supportedSource: [DatabaseEnum.clickhosue]}, + { + type: TypeEnum.column, + actions: [OperationEnum.preview], + supportedSource: [DatabaseEnum.clickhosue, DatabaseEnum.mysql] + }, {type: TypeEnum.column, actions: [OperationEnum.create], supportedSource: [DatabaseEnum.clickhosue]}, {type: TypeEnum.column, actions: [OperationEnum.delete], supportedSource: [DatabaseEnum.clickhosue]}, {type: TypeEnum.column, actions: [OperationEnum.rename], supportedSource: [DatabaseEnum.clickhosue]}, diff --git a/src/renderer/services/management/column.service.ts b/src/renderer/services/management/column.service.ts index 1b61fd56..9318e889 100644 --- a/src/renderer/services/management/column.service.ts +++ b/src/renderer/services/management/column.service.ts @@ -1,25 +1,27 @@ -import {Injectable} from '@angular/core'; -import {DatabaseModel} from '@renderer/model/database.model'; -import {RequestModel} from '@renderer/model/request.model'; -import {ResponseModel} from '@renderer/model/response.model'; -import {BaseService} from '@renderer/services/base.service'; -import {HttpService} from '@renderer/services/http.service'; -import {SqlUtils} from '@renderer/utils/sql.utils'; -import {StringUtils} from '@renderer/utils/string.utils'; -import {ColumnModel} from '@renderer/model/column.model'; -import {ColumnUtils} from '@renderer/utils/column.utils'; -import {SshService} from '@renderer/services/ssh.service'; -import {BasicService} from '@renderer/services/system/basic.service'; -import {ForwardService} from '@renderer/services/forward.service'; -import {FactoryService} from "@renderer/services/factory.service"; +import { Injectable } from '@angular/core'; +import { DatabaseModel } from '@renderer/model/database.model'; +import { RequestModel } from '@renderer/model/request.model'; +import { ResponseModel } from '@renderer/model/response.model'; +import { BaseService } from '@renderer/services/base.service'; +import { HttpService } from '@renderer/services/http.service'; +import { SqlUtils } from '@renderer/utils/sql.utils'; +import { StringUtils } from '@renderer/utils/string.utils'; +import { ColumnModel } from '@renderer/model/column.model'; +import { ColumnUtils } from '@renderer/utils/column.utils'; +import { SshService } from '@renderer/services/ssh.service'; +import { BasicService } from '@renderer/services/system/basic.service'; +import { ForwardService } from '@renderer/services/forward.service'; +import { FactoryService } from "@renderer/services/factory.service"; +import { MySQLService } from "@renderer/services/plugin/mysql.service"; @Injectable() export class ColumnService extends ForwardService implements BaseService { constructor(httpService: HttpService, factoryService: FactoryService, sshService: SshService, - basicService: BasicService) { - super(basicService, factoryService, httpService, sshService); + basicService: BasicService, + mysqlService: MySQLService) { + super(basicService, factoryService, httpService, sshService, null, mysqlService); } getResponse(request: RequestModel, sql?: string): Promise { @@ -27,7 +29,8 @@ export class ColumnService extends ForwardService implements BaseService { } getPreview(request: RequestModel, value: DatabaseModel): Promise { - const sql = StringUtils.format(`SELECT {0} FROM {1} LIMIT 10`, [value.name, SqlUtils.getTableName(value.database, value.table)]); + const sql = StringUtils.format(`SELECT {0} + FROM {1} LIMIT 10`, [value.name, SqlUtils.getTableName(value.database, value.table)]); return this.getResponse(request, sql); } From 71a25f688dee1aabcde870f12e96e43e5f25ad4a Mon Sep 17 00:00:00 2001 From: qianmoQ Date: Fri, 1 Jul 2022 15:42:20 +0800 Subject: [PATCH 14/20] Support metadata management to create column, delete column for MySQL #180 --- src/renderer/config/operation.config.ts | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/renderer/config/operation.config.ts b/src/renderer/config/operation.config.ts index b58d5c00..b0e07e9d 100644 --- a/src/renderer/config/operation.config.ts +++ b/src/renderer/config/operation.config.ts @@ -105,8 +105,16 @@ export class OperationConfig { actions: [OperationEnum.preview], supportedSource: [DatabaseEnum.clickhosue, DatabaseEnum.mysql] }, - {type: TypeEnum.column, actions: [OperationEnum.create], supportedSource: [DatabaseEnum.clickhosue]}, - {type: TypeEnum.column, actions: [OperationEnum.delete], supportedSource: [DatabaseEnum.clickhosue]}, + { + type: TypeEnum.column, + actions: [OperationEnum.create], + supportedSource: [DatabaseEnum.clickhosue, DatabaseEnum.mysql] + }, + { + type: TypeEnum.column, + actions: [OperationEnum.delete], + supportedSource: [DatabaseEnum.clickhosue, DatabaseEnum.mysql] + }, {type: TypeEnum.column, actions: [OperationEnum.rename], supportedSource: [DatabaseEnum.clickhosue]}, {type: TypeEnum.column, actions: [OperationEnum.comment], supportedSource: [DatabaseEnum.clickhosue]} ]; From 267695137603a4cac9b1e48b9d090e9a349154ee Mon Sep 17 00:00:00 2001 From: qianmoQ Date: Mon, 4 Jul 2022 16:43:48 +0800 Subject: [PATCH 15/20] Support metadata management to rename column for MySQL #180 --- .../common/common.column.component.html | 2 +- .../column/rename/column.rename.component.ts | 4 +- src/renderer/config/base.config.ts | 1 + src/renderer/config/operation.config.ts | 6 ++- .../config/plugin/clickhouse.config.ts | 3 ++ src/renderer/config/plugin/mysql.config.ts | 6 ++- .../config/plugin/postgresql.config.ts | 1 + src/renderer/config/plugin/presto.config.ts | 54 +++++++++---------- .../services/management/column.service.ts | 12 ++++- 9 files changed, 56 insertions(+), 33 deletions(-) diff --git a/src/renderer/components/column/common/common.column.component.html b/src/renderer/components/column/common/common.column.component.html index 6ba9f2c5..746fe064 100644 --- a/src/renderer/components/column/common/common.column.component.html +++ b/src/renderer/components/column/common/common.column.component.html @@ -10,7 +10,7 @@ + [originColumnType]="value?.origin?.value" (emitter)="handlerEmitter($event)"> (); inputValue: string; @@ -47,7 +49,7 @@ export class RenameColumnComponent extends BaseComponent { _value.database = this.database; _value.table = this.table; _value.name = this.value; - this.columnService.rename(request, _value, this.inputValue).then(response => { + this.columnService.rename(request, _value, this.inputValue, this.originColumnType).then(response => { if (response.status) { this.messageService.success(response.message); this.emitter.emit(true); diff --git a/src/renderer/config/base.config.ts b/src/renderer/config/base.config.ts index 434154db..4c98c506 100644 --- a/src/renderer/config/base.config.ts +++ b/src/renderer/config/base.config.ts @@ -19,6 +19,7 @@ export interface BaseConfig { tableItemsFilterPrecise: string; tableItemsFilterFuzzy: string; columnItems: string; + columnRename: string; serverInfo: string; stopProcessor: string; showCreateDatabase: string; diff --git a/src/renderer/config/operation.config.ts b/src/renderer/config/operation.config.ts index b0e07e9d..8592cdbc 100644 --- a/src/renderer/config/operation.config.ts +++ b/src/renderer/config/operation.config.ts @@ -115,7 +115,11 @@ export class OperationConfig { actions: [OperationEnum.delete], supportedSource: [DatabaseEnum.clickhosue, DatabaseEnum.mysql] }, - {type: TypeEnum.column, actions: [OperationEnum.rename], supportedSource: [DatabaseEnum.clickhosue]}, + { + type: TypeEnum.column, + actions: [OperationEnum.rename], + supportedSource: [DatabaseEnum.clickhosue, DatabaseEnum.mysql] + }, {type: TypeEnum.column, actions: [OperationEnum.comment], supportedSource: [DatabaseEnum.clickhosue]} ]; opertions.push(column); diff --git a/src/renderer/config/plugin/clickhouse.config.ts b/src/renderer/config/plugin/clickhouse.config.ts index 93870397..e4a3e468 100644 --- a/src/renderer/config/plugin/clickhouse.config.ts +++ b/src/renderer/config/plugin/clickhouse.config.ts @@ -165,4 +165,7 @@ SELECT name, engine, total_rows AS totalRows, FROM system.tables WHERE database = '{0}' `; + columnRename = ` +ALTER TABLE {0} RENAME COLUMN {1} TO {2} + `; } diff --git a/src/renderer/config/plugin/mysql.config.ts b/src/renderer/config/plugin/mysql.config.ts index c96eb753..2b4988d3 100644 --- a/src/renderer/config/plugin/mysql.config.ts +++ b/src/renderer/config/plugin/mysql.config.ts @@ -5,7 +5,8 @@ export class MySQLConfig implements BaseConfig { columnItems = ` SELECT TABLE_SCHEMA AS "database", TABLE_NAME AS tableName, COLUMN_NAME AS name, - DATA_TYPE AS type + -- DATA_TYPE AS type + concat(DATA_TYPE, '(', CHARACTER_MAXIMUM_LENGTH, ')') AS type FROM information_schema.columns WHERE table_schema = '{0}' AND table_name = '{1}' GROUP BY COLUMN_NAME @@ -115,4 +116,7 @@ FROM information_schema.tables WHERE table_schema = '{0}' GROUP BY TABLE_NAME `; + columnRename= ` +ALTER TABLE {0} CHANGE COLUMN {1} {2} {3} + `; } diff --git a/src/renderer/config/plugin/postgresql.config.ts b/src/renderer/config/plugin/postgresql.config.ts index 3328ebd9..b2bac35d 100644 --- a/src/renderer/config/plugin/postgresql.config.ts +++ b/src/renderer/config/plugin/postgresql.config.ts @@ -35,4 +35,5 @@ export class PostgresqlConfig implements BaseConfig { stopProcessor: string; showCreateDatabase: string; showTableWithSize: string; + columnRename: string; } diff --git a/src/renderer/config/plugin/presto.config.ts b/src/renderer/config/plugin/presto.config.ts index 08daaac5..23c40a8d 100644 --- a/src/renderer/config/plugin/presto.config.ts +++ b/src/renderer/config/plugin/presto.config.ts @@ -1,15 +1,13 @@ -import {BaseConfig} from "@renderer/config/base.config"; +import { BaseConfig } from "@renderer/config/base.config"; export class PrestoConfig implements BaseConfig { version = ` -SELECT node_version AS version -FROM system.runtime.nodes -LIMIT 1 + SELECT node_version AS version + FROM system.runtime.nodes LIMIT 1 `; processesFetchAll = ` -SELECT - query_id AS id, - now() AS time, + SELECT query_id AS id, + now() AS time, query AS query, '0' AS rows, analysis_time_ms + planning_time_ms + queued_time_ms AS elapsed, @@ -19,37 +17,38 @@ SELECT '0' AS bytesWritten, '' AS hash, '' AS host -FROM - system.runtime.queries -WHERE - state = 'RUNNING' -`; + FROM + system.runtime.queries + WHERE + state = 'RUNNING' + `; connectionFetchAll = ` -SELECT - source AS categories, - COUNT(1) AS value -FROM system.runtime.queries -WHERE state = 'RUNNING' -GROUP BY source -ORDER BY source DESC -`; + SELECT source AS categories, + COUNT(1) AS value + FROM system.runtime.queries + WHERE state = 'RUNNING' + GROUP BY source + ORDER BY source DESC + `; slowQueryFetchAll = ` -SELECT - query_id AS id, now() AS time, query AS query, '0' AS rows, + SELECT query_id AS id, + now() AS time, query AS query, '0' AS rows, (analysis_time_ms + planning_time_ms + queued_time_ms) AS elapsed, '0' AS bytes, '0' AS memoryUsage, '0' AS bytesRead, '0' AS bytesWritten, '' AS hash, '' AS host -FROM system.runtime.queries -WHERE (analysis_time_ms + planning_time_ms + queued_time_ms) >= {0} -ORDER BY (analysis_time_ms + planning_time_ms + queued_time_ms) DESC -LIMIT 100 + FROM system.runtime.queries + WHERE (analysis_time_ms + planning_time_ms + queued_time_ms) >= {0} + ORDER BY (analysis_time_ms + planning_time_ms + queued_time_ms) DESC + LIMIT 100 `; databaseFetchAll = `SHOW CATALOGS`; databaseCreate = `CREATE SCHEMA {0}`; schemaFetchAll = 'SHOW SCHEMAS FROM {0}'; tableFetchAll = 'SHOW TABLES FROM {0}.{1}'; - tableSchemaFetchAll = `SELECT table_name AS name FROM {0}.information_schema.tables WHERE table_schema='{1}'`; + tableSchemaFetchAll = `SELECT table_name AS name + FROM {0}.information_schema.tables + WHERE table_schema='{1}'`; columnDiskUsedRatio: string; columnItems: string; databaseDiskUsedRatio: string; @@ -65,4 +64,5 @@ LIMIT 100 stopProcessor: string; showCreateDatabase: string; showTableWithSize: string; + columnRename: string; } diff --git a/src/renderer/services/management/column.service.ts b/src/renderer/services/management/column.service.ts index 9318e889..c6a00a97 100644 --- a/src/renderer/services/management/column.service.ts +++ b/src/renderer/services/management/column.service.ts @@ -13,6 +13,7 @@ import { BasicService } from '@renderer/services/system/basic.service'; import { ForwardService } from '@renderer/services/forward.service'; import { FactoryService } from "@renderer/services/factory.service"; import { MySQLService } from "@renderer/services/plugin/mysql.service"; +import { DatabaseEnum } from "@renderer/enum/database.enum"; @Injectable() export class ColumnService extends ForwardService implements BaseService { @@ -45,8 +46,15 @@ export class ColumnService extends ForwardService implements BaseService { return this.getResponse(request, sql); } - rename(request: RequestModel, value: DatabaseModel, newName: string): Promise { - const sql = StringUtils.format('ALTER TABLE {0} RENAME COLUMN {1} TO {2}', [SqlUtils.getTableName(value.database, value.table), value.name, newName]); + rename(request: RequestModel, value: DatabaseModel, newName: string, originColumnType: string): Promise { + let sql; + if (request.config.type === DatabaseEnum.mysql) { + sql = StringUtils.format(this.factoryService.forward(request.config.type).columnRename, + [SqlUtils.getTableName(value.database, value.table), value.name, newName, originColumnType]); + } else { + sql = StringUtils.format(this.factoryService.forward(request.config.type).columnRename, + [SqlUtils.getTableName(value.database, value.table), value.name, newName]); + } return this.getResponse(request, sql); } From 9002e85c1e43f6d2ecbf84cc3bc080287eb292b2 Mon Sep 17 00:00:00 2001 From: qianmoQ Date: Mon, 4 Jul 2022 16:49:27 +0800 Subject: [PATCH 16/20] Add multiple editor theme --- src/renderer/editor.theme.scss | 7 ++++++- src/renderer/enum/editor/theme.enum.ts | 8 +++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/renderer/editor.theme.scss b/src/renderer/editor.theme.scss index d8861585..d8e670ce 100644 --- a/src/renderer/editor.theme.scss +++ b/src/renderer/editor.theme.scss @@ -56,7 +56,12 @@ @import "~codemirror/theme/tomorrow-night-eighties.css"; @import "~codemirror/theme/ttcn.css"; @import "~codemirror/theme/twilight.css"; -//@import "~codemirror/theme/"; +@import "~codemirror/theme/vibrant-ink.css"; +@import "~codemirror/theme/xq-dark.css"; +@import "~codemirror/theme/xq-light.css"; +@import "~codemirror/theme/yeti.css"; +@import "~codemirror/theme/yonce.css"; +@import "~codemirror/theme/zenburn.css"; // Wait for all themes to load after loading, load the hint style to prevent style confusion @import './editor.hints.css'; diff --git a/src/renderer/enum/editor/theme.enum.ts b/src/renderer/enum/editor/theme.enum.ts index 6072b01e..2d8c66db 100644 --- a/src/renderer/enum/editor/theme.enum.ts +++ b/src/renderer/enum/editor/theme.enum.ts @@ -55,5 +55,11 @@ export enum EditorThemeEnum { 'tomorrow-night-bright' = ('tomorrow-night-bright'), 'tomorrow-night-eighties' = ('tomorrow-night-eighties'), 'ttcn' = ('ttcn'), - 'twilight' = ('twilight') + 'twilight' = ('twilight'), + 'vibrant-ink' = ('vibrant-ink'), + 'xq-dark' = ('xq-dark'), + 'xq-light' = ('xq-light'), + 'yeti' = ('yeti'), + 'yonce' = ('yonce'), + 'zenburn' = ('zenburn') } From f5c8c2d23efd1dfbee9a22e409cef33ac65ee15e Mon Sep 17 00:00:00 2001 From: qianmoQ Date: Tue, 5 Jul 2022 18:14:22 +0800 Subject: [PATCH 17/20] Support metadata management to add column comment for MySQL #180 --- .../column/comment/column.comment.component.ts | 4 +++- .../column/common/common.column.component.html | 2 +- src/renderer/config/base.config.ts | 1 + src/renderer/config/operation.config.ts | 6 +++++- src/renderer/config/plugin/clickhouse.config.ts | 3 +++ src/renderer/config/plugin/mysql.config.ts | 3 +++ src/renderer/config/plugin/postgresql.config.ts | 1 + src/renderer/config/plugin/presto.config.ts | 1 + src/renderer/services/management/column.service.ts | 14 +++++++++++--- 9 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/renderer/components/column/comment/column.comment.component.ts b/src/renderer/components/column/comment/column.comment.component.ts index b648acc1..c5681888 100644 --- a/src/renderer/components/column/comment/column.comment.component.ts +++ b/src/renderer/components/column/comment/column.comment.component.ts @@ -21,6 +21,8 @@ export class CommentColumnComponent extends BaseComponent implements AfterViewIn database: string; @Input() table: string; + @Input() + originColumnType: string; @Output() emitter = new EventEmitter(); inputValue: string; @@ -47,7 +49,7 @@ export class CommentColumnComponent extends BaseComponent implements AfterViewIn _value.database = this.database; _value.table = this.table; _value.name = this.value; - this.columnService.comment(request, _value, this.inputValue).then(response => { + this.columnService.comment(request, _value, this.inputValue, this.originColumnType).then(response => { if (response.status) { this.messageService.success(response.message); this.config.status = false; diff --git a/src/renderer/components/column/common/common.column.component.html b/src/renderer/components/column/common/common.column.component.html index 746fe064..d62874e7 100644 --- a/src/renderer/components/column/common/common.column.component.html +++ b/src/renderer/components/column/common/common.column.component.html @@ -18,7 +18,7 @@ + [originColumnType]="value?.origin?.value" (emitter)="handlerEmitter($event)">
diff --git a/src/renderer/config/base.config.ts b/src/renderer/config/base.config.ts index 4c98c506..d87d7077 100644 --- a/src/renderer/config/base.config.ts +++ b/src/renderer/config/base.config.ts @@ -20,6 +20,7 @@ export interface BaseConfig { tableItemsFilterFuzzy: string; columnItems: string; columnRename: string; + columnAddComment: string; serverInfo: string; stopProcessor: string; showCreateDatabase: string; diff --git a/src/renderer/config/operation.config.ts b/src/renderer/config/operation.config.ts index 8592cdbc..c6b7fecd 100644 --- a/src/renderer/config/operation.config.ts +++ b/src/renderer/config/operation.config.ts @@ -120,7 +120,11 @@ export class OperationConfig { actions: [OperationEnum.rename], supportedSource: [DatabaseEnum.clickhosue, DatabaseEnum.mysql] }, - {type: TypeEnum.column, actions: [OperationEnum.comment], supportedSource: [DatabaseEnum.clickhosue]} + { + type: TypeEnum.column, + actions: [OperationEnum.comment], + supportedSource: [DatabaseEnum.clickhosue, DatabaseEnum.mysql] + } ]; opertions.push(column); return opertions; diff --git a/src/renderer/config/plugin/clickhouse.config.ts b/src/renderer/config/plugin/clickhouse.config.ts index e4a3e468..14caed3f 100644 --- a/src/renderer/config/plugin/clickhouse.config.ts +++ b/src/renderer/config/plugin/clickhouse.config.ts @@ -168,4 +168,7 @@ WHERE database = '{0}' columnRename = ` ALTER TABLE {0} RENAME COLUMN {1} TO {2} `; + columnAddComment = ` +ALTER TABLE {0} COMMENT COLUMN {1} '{2}' + `; } diff --git a/src/renderer/config/plugin/mysql.config.ts b/src/renderer/config/plugin/mysql.config.ts index 2b4988d3..60f75e39 100644 --- a/src/renderer/config/plugin/mysql.config.ts +++ b/src/renderer/config/plugin/mysql.config.ts @@ -119,4 +119,7 @@ GROUP BY TABLE_NAME columnRename= ` ALTER TABLE {0} CHANGE COLUMN {1} {2} {3} `; + columnAddComment = ` +ALTER TABLE {0} CHANGE COLUMN {1} {2} {3} COMMENT '{4}' + `; } diff --git a/src/renderer/config/plugin/postgresql.config.ts b/src/renderer/config/plugin/postgresql.config.ts index b2bac35d..a68725b0 100644 --- a/src/renderer/config/plugin/postgresql.config.ts +++ b/src/renderer/config/plugin/postgresql.config.ts @@ -36,4 +36,5 @@ export class PostgresqlConfig implements BaseConfig { showCreateDatabase: string; showTableWithSize: string; columnRename: string; + columnAddComment: string; } diff --git a/src/renderer/config/plugin/presto.config.ts b/src/renderer/config/plugin/presto.config.ts index 23c40a8d..fb8a6395 100644 --- a/src/renderer/config/plugin/presto.config.ts +++ b/src/renderer/config/plugin/presto.config.ts @@ -65,4 +65,5 @@ export class PrestoConfig implements BaseConfig { showCreateDatabase: string; showTableWithSize: string; columnRename: string; + columnAddComment: string; } diff --git a/src/renderer/services/management/column.service.ts b/src/renderer/services/management/column.service.ts index c6a00a97..3d4f0331 100644 --- a/src/renderer/services/management/column.service.ts +++ b/src/renderer/services/management/column.service.ts @@ -40,9 +40,17 @@ export class ColumnService extends ForwardService implements BaseService { return this.getResponse(request, sql); } - comment(request: RequestModel, value: DatabaseModel, comment: string): Promise { - const sql = StringUtils.format(`ALTER TABLE {0} COMMENT COLUMN {1} '{2}'`, - [SqlUtils.getTableName(value.database, value.table), value.name, StringUtils.appendBackslash(comment)]); + comment(request: RequestModel, value: DatabaseModel, comment: string, originColumnType: string): Promise { + let sql; + if (request.config.type === DatabaseEnum.mysql) { + sql = StringUtils.format(this.factoryService.forward(request.config.type).columnAddComment, + [SqlUtils.getTableName(value.database, value.table), value.name, value.name, originColumnType, comment]); + console.log(sql); + } + else { + sql = StringUtils.format(this.factoryService.forward(request.config.type).columnAddComment, + [SqlUtils.getTableName(value.database, value.table), value.name, StringUtils.appendBackslash(comment)]); + } return this.getResponse(request, sql); } From 8701855f37cb7af6b7dfbdd442bb624fca24bd45 Mon Sep 17 00:00:00 2001 From: qianmoQ Date: Wed, 6 Jul 2022 00:53:12 +0800 Subject: [PATCH 18/20] Support metadata management menu server related operations for PostgreSQL --- .../app/pages/management/metadata/metadata.component.ts | 5 +---- src/renderer/config/operation.config.ts | 2 +- src/renderer/config/plugin/postgresql.config.ts | 8 ++++++-- src/renderer/services/management/metadata.service.ts | 6 ++++-- 4 files changed, 12 insertions(+), 9 deletions(-) diff --git a/src/renderer/app/pages/management/metadata/metadata.component.ts b/src/renderer/app/pages/management/metadata/metadata.component.ts index 0913ce48..eecb9c85 100644 --- a/src/renderer/app/pages/management/metadata/metadata.component.ts +++ b/src/renderer/app/pages/management/metadata/metadata.component.ts @@ -56,10 +56,7 @@ export class MetadataComponent extends BaseComponent implements OnInit { configModel.title = k.alias; configModel.type = TypeEnum.disk; configModel.disabled = k.status ? false : true; - if (k.type === DatabaseEnum.postgresql) { - configModel.disabled = true; - } - if (k.type === DatabaseEnum.presto || k.type === DatabaseEnum.trino) { + if (k.type === DatabaseEnum.presto || k.type === DatabaseEnum.trino || k.type === DatabaseEnum.postgresql) { configModel.isLeaf = true; } if (configModel.disabled) { diff --git a/src/renderer/config/operation.config.ts b/src/renderer/config/operation.config.ts index c6b7fecd..eb5c8d1a 100644 --- a/src/renderer/config/operation.config.ts +++ b/src/renderer/config/operation.config.ts @@ -13,7 +13,7 @@ export class OperationConfig { { type: TypeEnum.server, actions: [OperationEnum.info], - supportedSource: [DatabaseEnum.clickhosue, DatabaseEnum.trino, DatabaseEnum.presto, DatabaseEnum.mysql] + supportedSource: [DatabaseEnum.clickhosue, DatabaseEnum.trino, DatabaseEnum.presto, DatabaseEnum.mysql, DatabaseEnum.postgresql] }, { type: TypeEnum.database, diff --git a/src/renderer/config/plugin/postgresql.config.ts b/src/renderer/config/plugin/postgresql.config.ts index a68725b0..bc5c43c2 100644 --- a/src/renderer/config/plugin/postgresql.config.ts +++ b/src/renderer/config/plugin/postgresql.config.ts @@ -18,14 +18,18 @@ export class PostgresqlConfig implements BaseConfig { diskUsedRatio: string; processesFetchAll: string; schemaFetchAll: string; - serverInfo: string; + serverInfo = ` + SELECT name AS name, setting AS value + FROM pg_catalog.pg_settings + ORDER BY category + `; slowQueryFetchAll: string; tableDiskUsedRatio: string; tableFetchAll = ` SELECT table_name AS name FROM information_schema.tables WHERE table_type = 'BASE TABLE' - AND table_schema = 'public' + AND table_schema = 'public' `; tableItems: string; tableItemsFilterFuzzy: string; diff --git a/src/renderer/services/management/metadata.service.ts b/src/renderer/services/management/metadata.service.ts index 08e99c94..1e1b6b3f 100644 --- a/src/renderer/services/management/metadata.service.ts +++ b/src/renderer/services/management/metadata.service.ts @@ -16,6 +16,7 @@ import { FilterModel } from '@renderer/model/filter.model'; import { FactoryService } from "@renderer/services/factory.service"; import { PrestoService } from "@renderer/services/presto.service"; import { MySQLService } from "@renderer/services/plugin/mysql.service"; +import { PostgresqlService } from "@renderer/services/plugin/postgresql.service"; @Injectable() export class MetadataService extends ForwardService implements BaseService { @@ -26,8 +27,9 @@ export class MetadataService extends ForwardService implements BaseService { httpService: HttpService, sshService: SshService, prestoService: PrestoService, - mysqlService: MySQLService) { - super(basicService, factoryService, httpService, sshService, prestoService, mysqlService); + mysqlService: MySQLService, + postgresqlService: PostgresqlService) { + super(basicService, factoryService, httpService, sshService, prestoService, mysqlService, postgresqlService); } getResponse(request: RequestModel, sql?: string): Promise { From 5fb90a030267a53863e6995eaee830f011957d21 Mon Sep 17 00:00:00 2001 From: qianmoQ Date: Wed, 6 Jul 2022 01:14:38 +0800 Subject: [PATCH 19/20] Supports metadata management of disk usage for PostgreSQL --- src/renderer/config/plugin/postgresql.config.ts | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/renderer/config/plugin/postgresql.config.ts b/src/renderer/config/plugin/postgresql.config.ts index bc5c43c2..9e32839b 100644 --- a/src/renderer/config/plugin/postgresql.config.ts +++ b/src/renderer/config/plugin/postgresql.config.ts @@ -15,7 +15,14 @@ export class PostgresqlConfig implements BaseConfig { databaseItems: string; databaseItemsFilterFuzzy: string; databaseItemsFilterPrecise: string; - diskUsedRatio: string; + diskUsedRatio = ` + SELECT + 'default' AS name, '/' AS path, + SUM(pg_database_size(pg_database.datname)) AS totalBytes, + pg_size_pretty(SUM(pg_database_size(pg_database.datname))) AS totalSize, + 0 AS value + FROM pg_database + `; processesFetchAll: string; schemaFetchAll: string; serverInfo = ` From 92121460ae0214c084ff25d4e531b61dced978f7 Mon Sep 17 00:00:00 2001 From: qianmoQ Date: Wed, 6 Jul 2022 01:34:57 +0800 Subject: [PATCH 20/20] Release 1.20.0 --- README.md | 7 --- docs/docs/release/1.20.0-20220706.md | 52 +++++++++++++++++++++++ docs/mkdocs.yml | 7 +-- electron-builder.yml | 38 +++++++++++++++++ package.json | 2 +- src/renderer/config/source.type.config.ts | 16 +++---- 6 files changed, 103 insertions(+), 19 deletions(-) create mode 100644 docs/docs/release/1.20.0-20220706.md diff --git a/README.md b/README.md index 2ed57acd..8baae892 100644 --- a/README.md +++ b/README.md @@ -84,13 +84,6 @@ DBM can query data from any SQL-speaking datastore or data engine (ClickHouse an Here are some of the major database solutions that are supported: - -

ClickHouse Trino diff --git a/docs/docs/release/1.20.0-20220706.md b/docs/docs/release/1.20.0-20220706.md new file mode 100644 index 00000000..28f0abff --- /dev/null +++ b/docs/docs/release/1.20.0-20220706.md @@ -0,0 +1,52 @@ +--- +template: overrides/main.html +icon: material/gesture-tap-button +--- + +DBM Version for `1.20.0` is released! + +Release Time: `2022-07-06` + +#### General + +--- + +- Support custom file names for downloading result data +- Add multiple editor theme + +#### Dependencies + +--- + +- Bump eslint-plugin-jsdoc from 35.3.2 to 39.3.3 +- Bump angular-highcharts from 13.0.1 to 14.1.5 +- Bump karma-jasmine-html-reporter from 1.7.0 to 2.0.0 + +#### MySQL + +--- + +- Support metadata management to build data tables [issues-180](https://github.com/EdurtIO/dbm/issues/180) +- Support metadata management to filter tables [issues-180](https://github.com/EdurtIO/dbm/issues/180) +- Support metadata management to show database ddl [issues-180](https://github.com/EdurtIO/dbm/issues/180) +- Support metadata management to delete database [issues-180](https://github.com/EdurtIO/dbm/issues/180) +- Support metadata management to preview table [issues-180](https://github.com/EdurtIO/dbm/issues/180) +- Support metadata management to show table ddl [issues-180](https://github.com/EdurtIO/dbm/issues/180) +- Support metadata management to delete table [issues-180](https://github.com/EdurtIO/dbm/issues/180) +- Support metadata management to rename table, truncate table [issues-180](https://github.com/EdurtIO/dbm/issues/180) +- Support metadata management to preview column [issues-180](https://github.com/EdurtIO/dbm/issues/180) +- Support metadata management to create column, delete column [issues-180](https://github.com/EdurtIO/dbm/issues/180) +- Support metadata management to rename column [issues-180](https://github.com/EdurtIO/dbm/issues/180) +- Support metadata management to add column comment [issues-180](https://github.com/EdurtIO/dbm/issues/180) + +#### PostgreSQL + +--- + +- Supports quick query +- Support metadata management menu server related operations +- Supports metadata management of disk usage + +--- + +- @qianmoQ diff --git a/docs/mkdocs.yml b/docs/mkdocs.yml index 2e38fec3..4f93d685 100755 --- a/docs/mkdocs.yml +++ b/docs/mkdocs.yml @@ -128,7 +128,7 @@ plugins: en: Home: Home Download: Get started with dbm - Datasource_MySQL: MySQL (Experimental) + Datasource_MySQL: MySQL Datasource_Presto_Trino: Presto & Trino (Experimental) Datasource_ClickHouse: ClickHouse Datasource_PostgreSQL: PostgreSQL (Experimental) @@ -156,7 +156,7 @@ plugins: Datasource_PostgreSQL: PostgreSQL (Experimental) - redirects: redirect_maps: - release-latest.md: release/1.19.0-20220623.md + release-latest.md: release/1.20.0-20220706.md nav: - Home: index.md @@ -178,7 +178,8 @@ nav: - Mutations: reference/monitor/monitor_mutations.md - Query: reference/monitor/monitor_query.md - Release Note: - - 1.19.0 (latest): release/1.19.0-20220623.md + - 1.20.0 (latest): release/1.20.0-20220706.md + - 1.19.0: release/1.19.0-20220623.md - 1.18.0: release/1.18.0-20220610.md - 1.17.0: release/1.17.0-20220529.md - 1.16.0: release/1.16.0-20220513.md diff --git a/electron-builder.yml b/electron-builder.yml index 7273066d..4ee9855a 100644 --- a/electron-builder.yml +++ b/electron-builder.yml @@ -14,7 +14,45 @@ forceCodeSigning: false releaseInfo: releaseNotes: | + #### General + --- + + - Support custom file names for downloading result data + - Add multiple editor theme + + #### Dependencies + + --- + + - Bump eslint-plugin-jsdoc from 35.3.2 to 39.3.3 + - Bump angular-highcharts from 13.0.1 to 14.1.5 + - Bump karma-jasmine-html-reporter from 1.7.0 to 2.0.0 + + #### MySQL + + --- + + - Support metadata management to build data tables [issues-180](https://github.com/EdurtIO/dbm/issues/180) + - Support metadata management to filter tables [issues-180](https://github.com/EdurtIO/dbm/issues/180) + - Support metadata management to show database ddl [issues-180](https://github.com/EdurtIO/dbm/issues/180) + - Support metadata management to delete database [issues-180](https://github.com/EdurtIO/dbm/issues/180) + - Support metadata management to preview table [issues-180](https://github.com/EdurtIO/dbm/issues/180) + - Support metadata management to show table ddl [issues-180](https://github.com/EdurtIO/dbm/issues/180) + - Support metadata management to delete table [issues-180](https://github.com/EdurtIO/dbm/issues/180) + - Support metadata management to rename table, truncate table [issues-180](https://github.com/EdurtIO/dbm/issues/180) + - Support metadata management to preview column [issues-180](https://github.com/EdurtIO/dbm/issues/180) + - Support metadata management to create column, delete column [issues-180](https://github.com/EdurtIO/dbm/issues/180) + - Support metadata management to rename column [issues-180](https://github.com/EdurtIO/dbm/issues/180) + - Support metadata management to add column comment [issues-180](https://github.com/EdurtIO/dbm/issues/180) + + #### PostgreSQL + + --- + + - Supports quick query + - Support metadata management menu server related operations + - Supports metadata management of disk usage directories: output: ./release diff --git a/package.json b/package.json index 9d102406..c311a0f4 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "dbm", - "version": "1.20.0-SNAPSHOT", + "version": "1.20.0", "author": "qianmoQ ", "description": "DataBase GUI", "github": "https://github.com/EdurtIO/dbm.git", diff --git a/src/renderer/config/source.type.config.ts b/src/renderer/config/source.type.config.ts index c49b93aa..ba852d49 100644 --- a/src/renderer/config/source.type.config.ts +++ b/src/renderer/config/source.type.config.ts @@ -21,6 +21,14 @@ export class SourceTypeConfig { false, null, './renderer/assets/icon/source/ClickHouse.svg')); + // MySQL + basicEngines.push(DatabaseModel.builder(TranslateUtils.getValue('common.mysql'), + TranslateUtils.getValue('tooltip.source.mysql'), + DatabaseEnum.mysql, + null, + false, + null, + './renderer/assets/icon/source/MySQL.svg')); basicType.engines = basicEngines; // -------------- Experimental ---------------- @@ -45,14 +53,6 @@ export class SourceTypeConfig { true, null, './renderer/assets/icon/source/Trino.svg')); - // MySQL - experimentalEngines.push(DatabaseModel.builder(TranslateUtils.getValue('common.mysql'), - TranslateUtils.getValue('tooltip.source.mysql'), - DatabaseEnum.mysql, - null, - true, - null, - './renderer/assets/icon/source/MySQL.svg')); // PostgreSQL experimentalEngines.push(DatabaseModel.builder(TranslateUtils.getValue('common.postgresql'), TranslateUtils.getValue('tooltip.source.postgresql'),