From d9b86885dbe47e69de7be8c1700daf56f48af58e Mon Sep 17 00:00:00 2001 From: ljc <1194570458@qq.com> Date: Thu, 2 Nov 2023 17:40:12 +0800 Subject: [PATCH 01/40] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E9=87=8D?= =?UTF-8?q?=E5=A4=8D=E9=80=89=E4=B8=AD=E6=95=B0=E6=8D=AE=E5=BA=93=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/chat2db/plugin/clickhouse/ClickHouseDBManage.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/chat2db-server/chat2db-plugins/chat2db-clickhouse/src/main/java/ai/chat2db/plugin/clickhouse/ClickHouseDBManage.java b/chat2db-server/chat2db-plugins/chat2db-clickhouse/src/main/java/ai/chat2db/plugin/clickhouse/ClickHouseDBManage.java index 942090520..4bf544393 100644 --- a/chat2db-server/chat2db-plugins/chat2db-clickhouse/src/main/java/ai/chat2db/plugin/clickhouse/ClickHouseDBManage.java +++ b/chat2db-server/chat2db-plugins/chat2db-clickhouse/src/main/java/ai/chat2db/plugin/clickhouse/ClickHouseDBManage.java @@ -29,10 +29,14 @@ private String setDatabaseInJdbcUrl(ConnectInfo connectInfo) { String connectAddress = connectInfo.getHost() + ":" + connectInfo.getPort(); String[] addressSplit = url.split(connectAddress); - String connectParams = addressSplit[1]; + String connectParams = addressSplit.length == 2 ? addressSplit[1] : ""; if (connectParams.startsWith("/")) { // 删除连接参数中的 / connectParams = connectParams.substring(1); + if(connectParams.startsWith(databaseName)){ + // 删除连接参数中的数据库名 + connectParams = connectParams.substring(databaseName.length()); + } } // 添加数据库名 return addressSplit[0] + connectAddress + "/" + databaseName + connectParams; From 02c3078cc4f607bb3fb77a412a0fec756039c60d Mon Sep 17 00:00:00 2001 From: ljc <1194570458@qq.com> Date: Thu, 2 Nov 2023 18:01:42 +0800 Subject: [PATCH 02/40] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E9=87=8D?= =?UTF-8?q?=E5=A4=8D=E9=80=89=E4=B8=AD=E6=95=B0=E6=8D=AE=E5=BA=93=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plugin/clickhouse/ClickHouseDBManage.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/chat2db-server/chat2db-plugins/chat2db-clickhouse/src/main/java/ai/chat2db/plugin/clickhouse/ClickHouseDBManage.java b/chat2db-server/chat2db-plugins/chat2db-clickhouse/src/main/java/ai/chat2db/plugin/clickhouse/ClickHouseDBManage.java index 4bf544393..06760b6d0 100644 --- a/chat2db-server/chat2db-plugins/chat2db-clickhouse/src/main/java/ai/chat2db/plugin/clickhouse/ClickHouseDBManage.java +++ b/chat2db-server/chat2db-plugins/chat2db-clickhouse/src/main/java/ai/chat2db/plugin/clickhouse/ClickHouseDBManage.java @@ -33,9 +33,19 @@ private String setDatabaseInJdbcUrl(ConnectInfo connectInfo) { if (connectParams.startsWith("/")) { // 删除连接参数中的 / connectParams = connectParams.substring(1); - if(connectParams.startsWith(databaseName)){ + if (connectParams.startsWith(databaseName)) { // 删除连接参数中的数据库名 connectParams = connectParams.substring(databaseName.length()); + } else { + // 是否有连接参数 + int beginIndex = connectParams.indexOf("?"); + // 无连接参数直接设置 "" + if (beginIndex == -1) { + connectParams = ""; + } else { + // 删除连接参数前的数据库名 + connectParams = connectParams.substring(beginIndex); + } } } // 添加数据库名 From e2cd110c70e4ccdf6e5ae201ffdb8c9c1abaaf64 Mon Sep 17 00:00:00 2001 From: ljc <1194570458@qq.com> Date: Thu, 2 Nov 2023 18:01:42 +0800 Subject: [PATCH 03/40] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=E9=87=8D?= =?UTF-8?q?=E5=A4=8D=E9=80=89=E4=B8=AD=E6=95=B0=E6=8D=AE=E5=BA=93=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98=20#650?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plugin/clickhouse/ClickHouseDBManage.java | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/chat2db-server/chat2db-plugins/chat2db-clickhouse/src/main/java/ai/chat2db/plugin/clickhouse/ClickHouseDBManage.java b/chat2db-server/chat2db-plugins/chat2db-clickhouse/src/main/java/ai/chat2db/plugin/clickhouse/ClickHouseDBManage.java index 4bf544393..06760b6d0 100644 --- a/chat2db-server/chat2db-plugins/chat2db-clickhouse/src/main/java/ai/chat2db/plugin/clickhouse/ClickHouseDBManage.java +++ b/chat2db-server/chat2db-plugins/chat2db-clickhouse/src/main/java/ai/chat2db/plugin/clickhouse/ClickHouseDBManage.java @@ -33,9 +33,19 @@ private String setDatabaseInJdbcUrl(ConnectInfo connectInfo) { if (connectParams.startsWith("/")) { // 删除连接参数中的 / connectParams = connectParams.substring(1); - if(connectParams.startsWith(databaseName)){ + if (connectParams.startsWith(databaseName)) { // 删除连接参数中的数据库名 connectParams = connectParams.substring(databaseName.length()); + } else { + // 是否有连接参数 + int beginIndex = connectParams.indexOf("?"); + // 无连接参数直接设置 "" + if (beginIndex == -1) { + connectParams = ""; + } else { + // 删除连接参数前的数据库名 + connectParams = connectParams.substring(beginIndex); + } } } // 添加数据库名 From a9ef4c03c9c3d5d3f13106c65ec781db39fef701 Mon Sep 17 00:00:00 2001 From: wuchuanpeng Date: Wed, 15 Nov 2023 18:28:32 +0800 Subject: [PATCH 04/40] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E8=87=AA=E5=AE=9A?= =?UTF-8?q?=E4=B9=89AI=E4=B8=8D=E8=83=BD=E4=BD=BF=E7=94=A8=E7=9A=84?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/chat2db/server/web/api/controller/ai/ChatController.java | 1 + 1 file changed, 1 insertion(+) diff --git a/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ai/ChatController.java b/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ai/ChatController.java index 6a67be49b..38629b494 100644 --- a/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ai/ChatController.java +++ b/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ai/ChatController.java @@ -235,6 +235,7 @@ public SseEmitter distributeAISql(ChatQueryRequest queryRequest, SseEmitter sseE case CHAT2DBAI: return chatWithChat2dbAi(queryRequest, sseEmitter, uid); case RESTAI : + return chatWithRestAi(queryRequest, sseEmitter); case FASTCHATAI: return chatWithFastChatAi(queryRequest, sseEmitter, uid); case AZUREAI : From 4494f95d4f1dd4a5d9fb89848498a0c06ff66020 Mon Sep 17 00:00:00 2001 From: evrentan Date: Wed, 22 Nov 2023 00:28:25 +0300 Subject: [PATCH 05/40] refactor(Chat2dbAIClient): refactor Chat2dbAIClient class --- .../ai/chat2db/client/Chat2dbAIClient.java | 65 ++++++++++++------- 1 file changed, 43 insertions(+), 22 deletions(-) diff --git a/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ai/chat2db/client/Chat2dbAIClient.java b/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ai/chat2db/client/Chat2dbAIClient.java index a687d4596..541c4f68a 100644 --- a/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ai/chat2db/client/Chat2dbAIClient.java +++ b/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ai/chat2db/client/Chat2dbAIClient.java @@ -4,11 +4,10 @@ import ai.chat2db.server.domain.api.model.Config; import ai.chat2db.server.domain.api.service.ConfigService; import ai.chat2db.server.web.api.util.ApplicationContextUtil; -import com.google.common.collect.Lists; -import com.unfbx.chatgpt.OpenAiStreamClient; import com.unfbx.chatgpt.constant.OpenAIConst; import lombok.extern.slf4j.Slf4j; -import org.apache.commons.lang3.StringUtils; + +import java.util.Objects; /** * @author jipengfei @@ -35,7 +34,7 @@ public class Chat2dbAIClient { public static final String CHAT2DB_EMBEDDING_MODEL= "fastchat.embedding.model"; - private static Chat2DBAIStreamClient CHAT2DB_AI_STREAM_CLIENT; + private static volatile Chat2DBAIStreamClient CHAT2DB_AI_STREAM_CLIENT; public static Chat2DBAIStreamClient getInstance() { if (CHAT2DB_AI_STREAM_CLIENT != null) { @@ -57,35 +56,57 @@ private static Chat2DBAIStreamClient singleton() { } public static void refresh() { - String apikey; - String apiHost = ApplicationContextUtil.getProperty(CHAT2DB_OPENAI_HOST); - if (StringUtils.isBlank(apiHost)) { - apiHost = OpenAIConst.OPENAI_HOST; - } ConfigService configService = ApplicationContextUtil.getBean(ConfigService.class); + + CHAT2DB_AI_STREAM_CLIENT = Chat2DBAIStreamClient.builder().apiHost(getApiHost(configService)) + .apiKey(getApiKey(configService)).model(getModel(configService)).build(); + } + + private static String getApiHost(ConfigService configService) { Config apiHostConfig = configService.find(CHAT2DB_OPENAI_HOST).getData(); - if (apiHostConfig != null) { - apiHost = apiHostConfig.getContent(); + + if (Objects.nonNull(apiHostConfig)) { + return apiHostConfig.getContent(); + } + + String apiHost = ApplicationContextUtil.getProperty(CHAT2DB_OPENAI_HOST); + + if (apiHost.isBlank()) { + return OpenAIConst.OPENAI_HOST; } + + return apiHost; + } + + private static String getApiKey(ConfigService configService) { + String apiKey; + Config config = configService.find(CHAT2DB_OPENAI_KEY).getData(); - if (config != null) { - apikey = config.getContent(); + + if (Objects.nonNull(config)) { + apiKey = config.getContent(); } else { - apikey = ApplicationContextUtil.getProperty(CHAT2DB_OPENAI_KEY); + apiKey = ApplicationContextUtil.getProperty(CHAT2DB_OPENAI_KEY); } + + log.info("refresh chat2db apikey:{}", maskApiKey(apiKey)); + + return apiKey; + } + + private static String getModel(ConfigService configService) { Config modelConfig = configService.find(CHAT2DB_OPENAI_MODEL).getData(); - String model = ""; - if (modelConfig != null) { - model = modelConfig.getContent(); + + if (Objects.nonNull(modelConfig)) { + return modelConfig.getContent(); } - log.info("refresh chat2db apikey:{}", maskApiKey(apikey)); - CHAT2DB_AI_STREAM_CLIENT = Chat2DBAIStreamClient.builder().apiHost(apiHost) - .apiKey(apikey).model(model).build(); + + return null; } private static String maskApiKey(String input) { - if (input == null) { - return input; + if (Objects.isNull(input)) { + return null; } StringBuilder maskedString = new StringBuilder(input); From 20e810e8bfd8a0cc8a889aa62bd78ae49574f953 Mon Sep 17 00:00:00 2001 From: Zhou Tong Date: Wed, 17 Apr 2024 10:36:08 +0800 Subject: [PATCH 06/40] Fix HiveSqlBuilder build error --- .../java/ai/chat2db/plugin/hive/builder/HiveSqlBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chat2db-server/chat2db-plugins/chat2db-hive/src/main/java/ai/chat2db/plugin/hive/builder/HiveSqlBuilder.java b/chat2db-server/chat2db-plugins/chat2db-hive/src/main/java/ai/chat2db/plugin/hive/builder/HiveSqlBuilder.java index 66d918558..1ddc6db4f 100644 --- a/chat2db-server/chat2db-plugins/chat2db-hive/src/main/java/ai/chat2db/plugin/hive/builder/HiveSqlBuilder.java +++ b/chat2db-server/chat2db-plugins/chat2db-hive/src/main/java/ai/chat2db/plugin/hive/builder/HiveSqlBuilder.java @@ -16,7 +16,7 @@ import java.util.Map; -public class HiveSqlBuilder extends DefaultSqlBuilder implements SqlBuilder { +public class HiveSqlBuilder extends DefaultSqlBuilder implements SqlBuilder { @Override public String buildCreateTableSql(Table table) { StringBuilder script = new StringBuilder(); From 014a0e04559ad126e8833b6019eae32691baa8a4 Mon Sep 17 00:00:00 2001 From: arjun12102019 Date: Mon, 6 May 2024 18:16:03 +0530 Subject: [PATCH 07/40] Changes for Issue 1360 --- .../chat2db/server/domain/core/impl/DatabaseServiceImpl.java | 3 ++- .../ai/chat2db/server/tools/common/util/EasyStringUtils.java | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/chat2db-server/chat2db-server-domain/chat2db-server-domain-core/src/main/java/ai/chat2db/server/domain/core/impl/DatabaseServiceImpl.java b/chat2db-server/chat2db-server-domain/chat2db-server-domain-core/src/main/java/ai/chat2db/server/domain/core/impl/DatabaseServiceImpl.java index 3d5389280..eed4884e8 100644 --- a/chat2db-server/chat2db-server-domain/chat2db-server-domain-core/src/main/java/ai/chat2db/server/domain/core/impl/DatabaseServiceImpl.java +++ b/chat2db-server/chat2db-server-domain/chat2db-server-domain-core/src/main/java/ai/chat2db/server/domain/core/impl/DatabaseServiceImpl.java @@ -118,9 +118,10 @@ public DataResult queryDatabaseSchema(MetaDataQueryParam param) { ThreadUtil.execute(() -> { try { database.setSchemas(metaData.schemas(connection, database.getName())); - countDownLatch.countDown(); } catch (Exception e) { log.error("queryDatabaseSchema error", e); + } finally{ + countDownLatch.countDown(); } }); } diff --git a/chat2db-server/chat2db-server-tools/chat2db-server-tools-common/src/main/java/ai/chat2db/server/tools/common/util/EasyStringUtils.java b/chat2db-server/chat2db-server-tools/chat2db-server-tools-common/src/main/java/ai/chat2db/server/tools/common/util/EasyStringUtils.java index 5f2987bb9..010c15d2f 100644 --- a/chat2db-server/chat2db-server-tools/chat2db-server-tools-common/src/main/java/ai/chat2db/server/tools/common/util/EasyStringUtils.java +++ b/chat2db-server/chat2db-server-tools/chat2db-server-tools-common/src/main/java/ai/chat2db/server/tools/common/util/EasyStringUtils.java @@ -26,7 +26,7 @@ public class EasyStringUtils { * @return modified job number */ public static String cutUserId(String userId) { - if (!org.apache.commons.lang3.StringUtils.isNumeric(userId)) { + if (!StringUtils.isNumeric(userId)) { return userId; } int startIndex = 0; From c60c24b9d2f1d7c705a27d3a35cefe67ec6b73a3 Mon Sep 17 00:00:00 2001 From: arjun12102019 Date: Mon, 6 May 2024 22:50:20 +0530 Subject: [PATCH 08/40] changes for issue 1362 --- .../builder/ClickHouseSqlBuilder.java | 110 ++++++++++++------ .../java/ai/chat2db/plugin/h2/H2Meta.java | 69 ++++++----- .../plugin/hive/builder/HiveSqlBuilder.java | 37 +++--- 3 files changed, 139 insertions(+), 77 deletions(-) diff --git a/chat2db-server/chat2db-plugins/chat2db-clickhouse/src/main/java/ai/chat2db/plugin/clickhouse/builder/ClickHouseSqlBuilder.java b/chat2db-server/chat2db-plugins/chat2db-clickhouse/src/main/java/ai/chat2db/plugin/clickhouse/builder/ClickHouseSqlBuilder.java index f093c198a..67c732218 100644 --- a/chat2db-server/chat2db-plugins/chat2db-clickhouse/src/main/java/ai/chat2db/plugin/clickhouse/builder/ClickHouseSqlBuilder.java +++ b/chat2db-server/chat2db-plugins/chat2db-clickhouse/src/main/java/ai/chat2db/plugin/clickhouse/builder/ClickHouseSqlBuilder.java @@ -14,58 +14,100 @@ public class ClickHouseSqlBuilder extends DefaultSqlBuilder { @Override public String buildCreateTableSql(Table table) { - StringBuilder script = new StringBuilder(); - script.append("CREATE TABLE "); - if (StringUtils.isNotBlank(table.getDatabaseName())) { - script.append("`").append(table.getDatabaseName()).append("`").append("."); - } + // Initialize StringBuilder to build the SQL script + StringBuilder script = new StringBuilder("CREATE TABLE "); + + // Append the database name, if present + appendDatabaseName(script, table.getDatabaseName()); + + // Append the table name script.append("`").append(table.getName()).append("`").append(" (").append("\n"); // append column - for (TableColumn column : table.getColumnList()) { - if (StringUtils.isBlank(column.getName()) || StringUtils.isBlank(column.getColumnType())) { - continue; - } - ClickHouseColumnTypeEnum typeEnum = ClickHouseColumnTypeEnum.getByType(column.getColumnType()); - script.append("\t").append(typeEnum.buildCreateColumnSql(column)).append(",\n"); - } + appendColumns(script, table.getColumnList()); // append index - for (TableIndex tableIndex : table.getIndexList()) { - if (StringUtils.isBlank(tableIndex.getName()) || StringUtils.isBlank(tableIndex.getType())) { - continue; - } - ClickHouseIndexTypeEnum mysqlIndexTypeEnum = ClickHouseIndexTypeEnum.getByType(tableIndex.getType()); - if (!ClickHouseIndexTypeEnum.PRIMARY.equals(mysqlIndexTypeEnum) ) { - script.append("\t").append("").append(mysqlIndexTypeEnum.buildIndexScript(tableIndex)).append(",\n"); - } - } + appendIndexes(script, table.getIndexList()); + // Remove the last comma script = new StringBuilder(script.substring(0, script.length() - 2)); script.append("\n)"); + // Append the engine, if present + appendEngine(script, table.getEngine()); - if (StringUtils.isNotBlank(table.getEngine())) { - script.append(" ENGINE=").append(table.getEngine()).append("\n"); + // append primary key + appendPrimaryKey(script, table.getIndexList()); + + // Append the comment, if present + appendComment(script, table.getComment()); + + // Append a semicolon to complete the SQL statement + script.append(";"); + + // Return the complete SQL script + return script.toString(); + } + + // Method to append the database name to the SQL script + private void appendDatabaseName(StringBuilder script, String databaseName) { + if (StringUtils.isNotBlank(databaseName)) { + script.append("`").append(databaseName).append("`."); } - // append primary key - for (TableIndex tableIndex : table.getIndexList()) { - if (StringUtils.isBlank(tableIndex.getName()) || StringUtils.isBlank(tableIndex.getType())) { - continue; + } + + // Method to append columns to the SQL script + private void appendColumns(StringBuilder script, List columns) { + for (TableColumn column : columns) { + // Check if column name and type are not blank + if (StringUtils.isNotBlank(column.getName()) && StringUtils.isNotBlank(column.getColumnType())) { + // Get the column type enum and append the column SQL to the script + ClickHouseColumnTypeEnum typeEnum = ClickHouseColumnTypeEnum.getByType(column.getColumnType()); + script.append("\t").append(typeEnum.buildCreateColumnSql(column)).append(",\n"); } - ClickHouseIndexTypeEnum mysqlIndexTypeEnum = ClickHouseIndexTypeEnum.getByType(tableIndex.getType()); - if (ClickHouseIndexTypeEnum.PRIMARY.equals(mysqlIndexTypeEnum) ) { - script.append("\t").append("").append(mysqlIndexTypeEnum.buildIndexScript(tableIndex)).append("\n"); + } + } + + // Method to append indexes to the SQL script + private void appendIndexes(StringBuilder script, List indexes) { + for (TableIndex index : indexes) { + // Check if index name and type are not blank + if (StringUtils.isNotBlank(index.getName()) && StringUtils.isNotBlank(index.getType())) { + // Get the index type enum and append the index script to the script + ClickHouseIndexTypeEnum indexTypeEnum = ClickHouseIndexTypeEnum.getByType(index.getType()); + if (!ClickHouseIndexTypeEnum.PRIMARY.equals(indexTypeEnum)) { + script.append("\t").append(indexTypeEnum.buildIndexScript(index)).append(",\n"); + } } } + } - if (StringUtils.isNotBlank(table.getComment())) { - script.append(" COMMENT '").append(table.getComment()).append("'"); + // Method to append the engine to the SQL script + private void appendEngine(StringBuilder script, String engine) { + if (StringUtils.isNotBlank(engine)) { + script.append(" ENGINE=").append(engine).append("\n"); } + } - script.append(";"); + // Method to append the primary key to the SQL script + private void appendPrimaryKey(StringBuilder script, List indexes) { + for (TableIndex index : indexes) { + // Check if index name and type are not blank + if (StringUtils.isNotBlank(index.getName()) && StringUtils.isNotBlank(index.getType())) { + // Get the index type enum and append the index script to the script + ClickHouseIndexTypeEnum indexTypeEnum = ClickHouseIndexTypeEnum.getByType(index.getType()); + if (ClickHouseIndexTypeEnum.PRIMARY.equals(indexTypeEnum)) { + script.append("\t").append(indexTypeEnum.buildIndexScript(index)).append("\n"); + } + } + } + } - return script.toString(); + // Method to append the comment to the SQL script + private void appendComment(StringBuilder script, String comment) { + if (StringUtils.isNotBlank(comment)) { + script.append(" COMMENT '").append(comment).append("'"); + } } @Override diff --git a/chat2db-server/chat2db-plugins/chat2db-h2/src/main/java/ai/chat2db/plugin/h2/H2Meta.java b/chat2db-server/chat2db-plugins/chat2db-h2/src/main/java/ai/chat2db/plugin/h2/H2Meta.java index 5caffc8cf..00f3596b8 100644 --- a/chat2db-server/chat2db-plugins/chat2db-h2/src/main/java/ai/chat2db/plugin/h2/H2Meta.java +++ b/chat2db-server/chat2db-plugins/chat2db-h2/src/main/java/ai/chat2db/plugin/h2/H2Meta.java @@ -33,10 +33,33 @@ public String tableDDL(Connection connection, @NotEmpty String databaseName, Str } private String getDDL(Connection connection, String databaseName, String schemaName, String tableName) { - try { - // Query table structure information - ResultSet columns = connection.getMetaData().getColumns(databaseName, schemaName, tableName, null); - List columnDefinitions = new ArrayList<>(); + + try{ + List columnDefinitions = getColumnDefinitions(connection, databaseName, schemaName, tableName); + Map> indexMap = getIndexInfo(connection, databaseName, schemaName, tableName); + StringBuilder createTableDDL = new StringBuilder("CREATE TABLE "); + createTableDDL.append(tableName).append(" (\n"); + createTableDDL.append(String.join(",\n", columnDefinitions)); + createTableDDL.append("\n);\n"); + + // Output index information + for (Map.Entry> entry : indexMap.entrySet()) { + String indexName = entry.getKey(); + List columnList = entry.getValue(); + String indexColumns = String.join(", ", columnList); + String createIndexDDL = String.format("CREATE INDEX %s ON %s (%s);", indexName, tableName, indexColumns); + createTableDDL.append(createIndexDDL); + } + return createTableDDL.toString(); + } catch (Exception e) { + e.printStackTrace(); + } + return ""; + } + + private List getColumnDefinitions(Connection connection, String databaseName, String schemaName, String tableName) { + List columnDefinitions = new ArrayList<>(); + try (ResultSet columns = connection.getMetaData().getColumns(databaseName, schemaName, tableName, null)) { while (columns.next()) { String columnName = columns.getString("COLUMN_NAME"); String columnType = columns.getString("TYPE_NAME"); @@ -58,40 +81,26 @@ private String getDDL(Connection connection, String databaseName, String schemaN } columnDefinitions.add(columnDefinition.toString()); } + } catch (Exception e) { + throw new RuntimeException(e); + } + return columnDefinitions; + } - // Query table index information - ResultSet indexes = connection.getMetaData().getIndexInfo(databaseName, schemaName, tableName, false, - false); - Map> indexMap = new HashMap<>(); + private Map> getIndexInfo(Connection connection, String databaseName, String schemaName, String tableName) { + Map> indexMap = new HashMap<>(); + try (ResultSet indexes = connection.getMetaData().getIndexInfo(databaseName, schemaName, tableName, false, false)) { while (indexes.next()) { String indexName = indexes.getString("INDEX_NAME"); String columnName = indexes.getString("COLUMN_NAME"); if (indexName != null) { - if (!indexMap.containsKey(indexName)) { - indexMap.put(indexName, new ArrayList<>()); - } - indexMap.get(indexName).add(columnName); + indexMap.computeIfAbsent(indexName, k -> new ArrayList<>()).add(columnName); } } - StringBuilder createTableDDL = new StringBuilder("CREATE TABLE "); - createTableDDL.append(tableName).append(" (\n"); - createTableDDL.append(String.join(",\n", columnDefinitions)); - createTableDDL.append("\n);\n"); - // Output index information - for (Map.Entry> entry : indexMap.entrySet()) { - String indexName = entry.getKey(); - List columnList = entry.getValue(); - String indexColumns = String.join(", ", columnList); - String createIndexDDL = String.format("CREATE INDEX %s ON %s (%s);", indexName, tableName, - indexColumns); - createTableDDL.append(createIndexDDL); - } - return createTableDDL.toString(); - - } catch (Exception e) { - e.printStackTrace(); + } catch (SQLException e) { + throw new RuntimeException(e); } - return ""; + return indexMap; } private static String ROUTINES_SQL diff --git a/chat2db-server/chat2db-plugins/chat2db-hive/src/main/java/ai/chat2db/plugin/hive/builder/HiveSqlBuilder.java b/chat2db-server/chat2db-plugins/chat2db-hive/src/main/java/ai/chat2db/plugin/hive/builder/HiveSqlBuilder.java index 66d918558..f14f1d16f 100644 --- a/chat2db-server/chat2db-plugins/chat2db-hive/src/main/java/ai/chat2db/plugin/hive/builder/HiveSqlBuilder.java +++ b/chat2db-server/chat2db-plugins/chat2db-hive/src/main/java/ai/chat2db/plugin/hive/builder/HiveSqlBuilder.java @@ -27,27 +27,41 @@ public String buildCreateTableSql(Table table) { script.append("`").append(table.getName()).append("`").append(" (").append("\n"); // append column - for (TableColumn column : table.getColumnList()) { + appendColumns(script, table.getColumnList()); + + // append primary key and index + appendIndexes(script, table.getIndexList()); + script = new StringBuilder(script.substring(0, script.length() - 2)); + script.append("\n)"); + + // append engine, charset, collate, auto_increment, comment, and partition + appendTableOptions(script, table); + script.append(";"); + + return script.toString(); + } + + private void appendColumns(StringBuilder script, List columns) { + for (TableColumn column : columns) { if (StringUtils.isBlank(column.getName()) || StringUtils.isBlank(column.getColumnType())) { continue; } HiveColumnTypeEnum typeEnum = HiveColumnTypeEnum.getByType(column.getColumnType()); script.append("\t").append(typeEnum.buildCreateColumnSql(column)).append(",\n"); } + } - // append primary key and index - for (TableIndex tableIndex : table.getIndexList()) { - if (StringUtils.isBlank(tableIndex.getName()) || StringUtils.isBlank(tableIndex.getType())) { + private void appendIndexes(StringBuilder script, List indexes) { + for (TableIndex index : indexes) { + if (StringUtils.isBlank(index.getName()) || StringUtils.isBlank(index.getType())) { continue; } - HiveIndexTypeEnum hiveIndexTypeEnum = HiveIndexTypeEnum.getByType(tableIndex.getType()); - script.append("\t").append("").append(hiveIndexTypeEnum.buildIndexScript(tableIndex)).append(",\n"); + HiveIndexTypeEnum hiveIndexTypeEnum = HiveIndexTypeEnum.getByType(index.getType()); + script.append("\t").append("").append(hiveIndexTypeEnum.buildIndexScript(index)).append(",\n"); } + } - script = new StringBuilder(script.substring(0, script.length() - 2)); - script.append("\n)"); - - + private void appendTableOptions(StringBuilder script, Table table) { if (StringUtils.isNotBlank(table.getEngine())) { script.append(" ENGINE=").append(table.getEngine()); } @@ -71,9 +85,6 @@ public String buildCreateTableSql(Table table) { if (StringUtils.isNotBlank(table.getPartition())) { script.append(" \n").append(table.getPartition()); } - script.append(";"); - - return script.toString(); } @Override From 6e21f154d138c09fd693f36926f020e6d2f6c05b Mon Sep 17 00:00:00 2001 From: H_C_ Date: Tue, 21 May 2024 15:35:41 +0800 Subject: [PATCH 09/40] Update index.tsx fix No date selected to No data selected --- chat2db-client/src/pages/main/dashboard/chart-item/index.tsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chat2db-client/src/pages/main/dashboard/chart-item/index.tsx b/chat2db-client/src/pages/main/dashboard/chart-item/index.tsx index 076a7532c..57f500f27 100644 --- a/chat2db-client/src/pages/main/dashboard/chart-item/index.tsx +++ b/chat2db-client/src/pages/main/dashboard/chart-item/index.tsx @@ -317,7 +317,7 @@ function ChartItem(props: IChartItemProps) {
-
No date selected
+
No data selected
result = tableService.query(param, selector); + System.out.println(result.getData()); + Assertions.assertTrue(result.getSuccess(), result.errorMessage()); + } else if (Objects.equals(dialectProperties.getDbType(), "ORACLE")) { + TableQueryParam param = new TableQueryParam(); + param.setDatabaseName(dialectProperties.getDatabaseName()); + param.setSchemaName("TEST_USER"); + param.setTableName("DEMO_TABLE"); + TableSelector selector = new TableSelector(); + selector.setColumnList(true); + selector.setIndexList(false); + + DataResult
result = tableService.query(param, selector); + System.out.println(result.getData()); + Assertions.assertTrue(result.getSuccess(), result.errorMessage()); + } else if (Objects.equals(dialectProperties.getDbType(), "POSTGRESQL")) { + TableQueryParam param = new TableQueryParam(); + param.setDatabaseName(dialectProperties.getDatabaseName()); + param.setSchemaName("test"); + param.setTableName("dept"); + TableSelector selector = new TableSelector(); + selector.setColumnList(true); + selector.setIndexList(false); + + DataResult
result = tableService.query(param, selector); + System.out.println(result.getData()); + Assertions.assertTrue(result.getSuccess(), result.errorMessage()); + } + } + } + + /** + * Save the current user identity (administrator or normal user) and user ID to the context and database session for subsequent use. + * + * @param isAdmin + * @param userId + */ + private static void userLoginIdentity(boolean isAdmin, Long userId) { + Context context = Context.builder().loginUser( + LoginUser.builder().admin(isAdmin).id(userId).build() + ).build(); + ContextUtils.setContext(context); + Dbutils.setSession(); + } +} From d96bafb6dddcbaeb7467d5e73669e3bd190af7e1 Mon Sep 17 00:00:00 2001 From: suyue <2016494681@qq.com> Date: Tue, 13 Aug 2024 11:48:13 +0800 Subject: [PATCH 19/40] =?UTF-8?q?Fix=20Issue=EF=BC=9A#1490?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/java/ai/chat2db/spi/jdbc/DefaultSqlBuilder.java | 1 + 1 file changed, 1 insertion(+) diff --git a/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/jdbc/DefaultSqlBuilder.java b/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/jdbc/DefaultSqlBuilder.java index cfffd4521..4f6a411ac 100644 --- a/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/jdbc/DefaultSqlBuilder.java +++ b/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/jdbc/DefaultSqlBuilder.java @@ -389,6 +389,7 @@ private String getInsertSql(String tableName, List
headerList, List Date: Tue, 13 Aug 2024 13:49:03 +0800 Subject: [PATCH 20/40] =?UTF-8?q?Fix=20Issue=EF=BC=9A#1490?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/ai/chat2db/spi/jdbc/DefaultSqlBuilder.java | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/jdbc/DefaultSqlBuilder.java b/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/jdbc/DefaultSqlBuilder.java index 4f6a411ac..04d2f7928 100644 --- a/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/jdbc/DefaultSqlBuilder.java +++ b/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/jdbc/DefaultSqlBuilder.java @@ -388,8 +388,13 @@ private String getInsertSql(String tableName, List
headerList, List Date: Wed, 14 Aug 2024 00:20:44 +0800 Subject: [PATCH 21/40] zhipu updata api interface --- .../blocks/Setting/AiSetting/aiTypeConfig.ts | 4 +- chat2db-client/src/typings/ai.ts | 4 +- .../ai/zhipu/client/ZhipuChatAIClient.java | 4 +- .../zhipu/client/ZhipuChatAIStreamClient.java | 5 +- .../ZhipuChatAIEventSourceListener.java | 26 +++-------- .../ai/zhipu/model/ZhipuChatBody.java | 10 +++- .../ai/zhipu/model/ZhipuChatCompletions.java | 46 ++++++++----------- .../model/ZhipuChatCompletionsOptions.java | 4 +- 8 files changed, 45 insertions(+), 58 deletions(-) diff --git a/chat2db-client/src/blocks/Setting/AiSetting/aiTypeConfig.ts b/chat2db-client/src/blocks/Setting/AiSetting/aiTypeConfig.ts index e2fbef8bc..8867614b1 100644 --- a/chat2db-client/src/blocks/Setting/AiSetting/aiTypeConfig.ts +++ b/chat2db-client/src/blocks/Setting/AiSetting/aiTypeConfig.ts @@ -23,8 +23,8 @@ const AIFormConfig: Record = { }, [AIType.ZHIPUAI]: { apiKey: true, - apiHost: 'https://open.bigmodel.cn/api/paas/v3/model-api/', - model: 'chatglm_turbo', + apiHost: 'https://open.bigmodel.cn/api/paas/v4/chat/completions', + model: 'codegeex-4', }, [AIType.BAICHUANAI]: { apiKey: true, diff --git a/chat2db-client/src/typings/ai.ts b/chat2db-client/src/typings/ai.ts index e7baf564b..0ed1d7b2e 100644 --- a/chat2db-client/src/typings/ai.ts +++ b/chat2db-client/src/typings/ai.ts @@ -1,9 +1,9 @@ export enum AIType { - CHAT2DBAI = 'CHAT2DBAI', + // CHAT2DBAI = 'CHAT2DBAI', ZHIPUAI = 'ZHIPUAI', BAICHUANAI='BAICHUANAI', WENXINAI='WENXINAI', - // TONGYIQIANWENAI='TONGYIQIANWENAI', + TONGYIQIANWENAI='TONGYIQIANWENAI', OPENAI = 'OPENAI', AZUREAI = 'AZUREAI', RESTAI = 'RESTAI', diff --git a/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ai/zhipu/client/ZhipuChatAIClient.java b/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ai/zhipu/client/ZhipuChatAIClient.java index f205f17f5..77e2aa0ad 100644 --- a/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ai/zhipu/client/ZhipuChatAIClient.java +++ b/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ai/zhipu/client/ZhipuChatAIClient.java @@ -58,8 +58,8 @@ private static ZhipuChatAIStreamClient singleton() { public static void refresh() { String apiKey = ""; - String apiHost = "https://open.bigmodel.cn/api/paas/v3/model-api/"; - String model = "chatglm_turbo"; + String apiHost = ""; + String model = ""; ConfigService configService = ApplicationContextUtil.getBean(ConfigService.class); Config apiHostConfig = configService.find(ZHIPU_HOST).getData(); if (apiHostConfig != null && StringUtils.isNotBlank(apiHostConfig.getContent())) { diff --git a/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ai/zhipu/client/ZhipuChatAIStreamClient.java b/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ai/zhipu/client/ZhipuChatAIStreamClient.java index 04bdb4b9d..6ae3f1ee9 100644 --- a/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ai/zhipu/client/ZhipuChatAIStreamClient.java +++ b/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ai/zhipu/client/ZhipuChatAIStreamClient.java @@ -204,11 +204,10 @@ public void streamCompletions(List chatMessages, EventSourceLis ObjectMapper mapper = new ObjectMapper(); mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); String requestBody = mapper.writeValueAsString(completionsOptions); - - String url = this.apiHost + "/" + this.model + "/" + "sse-invoke"; + log.info("使用的model:{}", this.model); EventSource.Factory factory = EventSources.createFactory(this.okHttpClient); Request request = new Request.Builder() - .url(url) + .url(apiHost) .post(RequestBody.create(MediaType.parse(ContentType.JSON.getValue()), requestBody)) .build(); //Create event diff --git a/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ai/zhipu/listener/ZhipuChatAIEventSourceListener.java b/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ai/zhipu/listener/ZhipuChatAIEventSourceListener.java index 91ce3c788..efbc9f827 100644 --- a/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ai/zhipu/listener/ZhipuChatAIEventSourceListener.java +++ b/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ai/zhipu/listener/ZhipuChatAIEventSourceListener.java @@ -1,6 +1,5 @@ package ai.chat2db.server.web.api.controller.ai.zhipu.listener; -import ai.chat2db.server.web.api.controller.ai.fastchat.model.FastChatMessage; import ai.chat2db.server.web.api.controller.ai.zhipu.model.ZhipuChatCompletions; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; @@ -12,9 +11,9 @@ import okhttp3.sse.EventSource; import okhttp3.sse.EventSourceListener; import org.apache.commons.lang3.StringUtils; +import org.jetbrains.annotations.NotNull; import org.springframework.web.servlet.mvc.method.annotation.SseEmitter; -import java.io.IOException; import java.util.Objects; /** @@ -47,7 +46,7 @@ public void onOpen(EventSource eventSource, Response response) { */ @SneakyThrows @Override - public void onEvent(EventSource eventSource, String id, String type, String data) { + public void onEvent(EventSource eventSource, String id, String type, @NotNull String data) { log.info("Zhipu Chat AI response data:{}", data); if (data.equals("[DONE]")) { log.info("Zhipu Chat AI closed"); @@ -60,14 +59,9 @@ public void onEvent(EventSource eventSource, String id, String type, String data } ZhipuChatCompletions chatCompletions = mapper.readValue(data, ZhipuChatCompletions.class); - String text = chatCompletions.getData(); - if (Objects.isNull(text)) { - for (FastChatMessage message : chatCompletions.getBody().getChoices()) { - if (message != null && message.getContent() != null) { - text = message.getContent(); - } - } - } + String text = chatCompletions.getChoices().get(0).getDelta()==null? + chatCompletions.getChoices().get(0).getText() + :chatCompletions.getChoices().get(0).getDelta().getContent(); Message message = new Message(); message.setContent(text); @@ -79,15 +73,7 @@ public void onEvent(EventSource eventSource, String id, String type, String data @Override public void onClosed(EventSource eventSource) { - try { - sseEmitter.send(SseEmitter.event() - .id("[DONE]") - .data("[DONE]")); - } catch (IOException e) { - throw new RuntimeException(e); - } - sseEmitter.complete(); - log.info("ZhipuChatAI close sse connection..."); + log.info("Zhipu Chat AI closes sse connection closed"); } @Override diff --git a/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ai/zhipu/model/ZhipuChatBody.java b/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ai/zhipu/model/ZhipuChatBody.java index e84c81ed0..d9bac3527 100644 --- a/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ai/zhipu/model/ZhipuChatBody.java +++ b/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ai/zhipu/model/ZhipuChatBody.java @@ -4,6 +4,7 @@ package ai.chat2db.server.web.api.controller.ai.zhipu.model; import ai.chat2db.server.web.api.controller.ai.baichuan.model.BaichuanChatMessage; +import ai.chat2db.server.web.api.controller.ai.fastchat.model.FastChatChoice; import ai.chat2db.server.web.api.controller.ai.fastchat.model.FastChatCompletionsUsage; import ai.chat2db.server.web.api.controller.ai.fastchat.model.FastChatMessage; import com.fasterxml.jackson.annotation.JsonCreator; @@ -24,9 +25,16 @@ public final class ZhipuChatBody { * The log probabilities model for tokens associated with this completions choice. */ @JsonProperty(value = "choices") - private List choices; + private List choices; @JsonProperty(value = "usage") private FastChatCompletionsUsage usage; + @JsonCreator + private ZhipuChatBody( + @JsonProperty(value = "choices") List choices, + @JsonProperty(value = "usage") FastChatCompletionsUsage usage) { + this.choices = choices; + this.usage = usage; + } } diff --git a/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ai/zhipu/model/ZhipuChatCompletions.java b/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ai/zhipu/model/ZhipuChatCompletions.java index 323b63fb0..00f781337 100644 --- a/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ai/zhipu/model/ZhipuChatCompletions.java +++ b/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ai/zhipu/model/ZhipuChatCompletions.java @@ -1,44 +1,38 @@ package ai.chat2db.server.web.api.controller.ai.zhipu.model; +import ai.chat2db.server.web.api.controller.ai.fastchat.model.FastChatChoice; +import ai.chat2db.server.web.api.controller.ai.fastchat.model.FastChatCompletionsUsage; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonProperty; import lombok.Data; +import java.util.List; + @Data public class ZhipuChatCompletions { /* * A unique identifier associated with this chat completions response. */ - private String msg; - - private int statusCode; + @JsonProperty(value = "id") + private String id; + @JsonProperty(value = "created") + private Long created; - private String data; + @JsonProperty(value = "choices") + private List choices; - /* - * The collection of completions choices associated with this completions response. - * Generally, `n` choices are generated per provided prompt with a default value of 1. - * Token limits and other settings may limit the number of choices generated. - */ - @JsonProperty(value = "body") - private ZhipuChatBody body; - - /** - * Creates an instance of ChatCompletions class. - * - * @param msg the id value to set. - * @param code the created value to set. - * @param body the body value to set. - */ + @JsonProperty(value = "usage") + private FastChatCompletionsUsage usage; @JsonCreator private ZhipuChatCompletions( - @JsonProperty(value = "msg") String msg, - @JsonProperty(value = "code") int code, - @JsonProperty(value = "body") ZhipuChatBody body) { - this.msg = msg; - this.statusCode = code; - this.body = body; + @JsonProperty(value = "id") String id, + @JsonProperty(value = "created") Long created, + @JsonProperty(value = "choices") List choices, + @JsonProperty(value = "usage") FastChatCompletionsUsage usage) { + this.id = id; + this.created = created; + this.choices = choices; + this.usage = usage; } - } diff --git a/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ai/zhipu/model/ZhipuChatCompletionsOptions.java b/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ai/zhipu/model/ZhipuChatCompletionsOptions.java index 4b6359cc2..931e48280 100644 --- a/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ai/zhipu/model/ZhipuChatCompletionsOptions.java +++ b/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ai/zhipu/model/ZhipuChatCompletionsOptions.java @@ -20,7 +20,7 @@ public final class ZhipuChatCompletionsOptions { private String requestId; // sse-params - @JsonProperty(value = "incremental") + @JsonProperty(value = "stream") private Boolean stream = true; @JsonProperty(value = "sseFormat") @@ -33,7 +33,7 @@ public final class ZhipuChatCompletionsOptions { * the behavior of the assistant, followed by alternating messages between the User and * Assistant roles. */ - @JsonProperty(value = "prompt") + @JsonProperty(value = "messages") private List prompt; From 63a8da63883254b7e83f6b6b1252c5b18862b51f Mon Sep 17 00:00:00 2001 From: suyue <2016494681@qq.com> Date: Wed, 14 Aug 2024 16:48:09 +0800 Subject: [PATCH 22/40] unit test --- .../start/test/core/TaskServiceTest.java | 126 ++++++++++++++++++ .../start/test/core/TeamServiceTest.java | 100 ++++++++++++++ .../start/test/core/TeamUserServiceTest.java | 81 +++++++++++ 3 files changed, 307 insertions(+) create mode 100644 chat2db-server/chat2db-server-start/src/test/java/ai/chat2db/server/start/test/core/TaskServiceTest.java create mode 100644 chat2db-server/chat2db-server-start/src/test/java/ai/chat2db/server/start/test/core/TeamServiceTest.java create mode 100644 chat2db-server/chat2db-server-start/src/test/java/ai/chat2db/server/start/test/core/TeamUserServiceTest.java diff --git a/chat2db-server/chat2db-server-start/src/test/java/ai/chat2db/server/start/test/core/TaskServiceTest.java b/chat2db-server/chat2db-server-start/src/test/java/ai/chat2db/server/start/test/core/TaskServiceTest.java new file mode 100644 index 000000000..21e9916e9 --- /dev/null +++ b/chat2db-server/chat2db-server-start/src/test/java/ai/chat2db/server/start/test/core/TaskServiceTest.java @@ -0,0 +1,126 @@ +package ai.chat2db.server.start.test.core; + +import ai.chat2db.server.domain.api.model.Task; +import ai.chat2db.server.domain.api.param.TaskCreateParam; +import ai.chat2db.server.domain.api.param.TaskPageParam; +import ai.chat2db.server.domain.api.param.TaskUpdateParam; +import ai.chat2db.server.domain.api.service.TaskService; +import ai.chat2db.server.domain.repository.Dbutils; +import ai.chat2db.server.start.test.TestApplication; +import ai.chat2db.server.start.test.dialect.DialectProperties; +import ai.chat2db.server.start.test.dialect.TestUtils; +import ai.chat2db.server.tools.base.wrapper.result.ActionResult; +import ai.chat2db.server.tools.base.wrapper.result.DataResult; +import ai.chat2db.server.tools.base.wrapper.result.PageResult; +import ai.chat2db.server.tools.common.model.Context; +import ai.chat2db.server.tools.common.model.LoginUser; +import ai.chat2db.server.tools.common.util.ContextUtils; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; + +/** + * @author Juechen + * @version : TaskServiceTest.java + */ +public class TaskServiceTest extends TestApplication { + + @Autowired + private TaskService taskService; + + @Autowired + private List dialectPropertiesList; + + @Test + public void testCreate() { + + userLoginIdentity(true, 9L); + for (DialectProperties dialectProperties : dialectPropertiesList) { + Long dataSourceId = TestUtils.nextLong(); + Long consoleId = TestUtils.nextLong(); + TestUtils.buildContext(dialectProperties, dataSourceId, consoleId); + + if (dialectProperties.getDbType().equalsIgnoreCase("MYSQL")) { + TaskCreateParam param = new TaskCreateParam(); + param.setDataSourceId(dataSourceId); + param.setDatabaseName(dialectProperties.getDatabaseName()); + param.setSchemaName(""); + param.setTableName("access_token"); + param.setUserId(9L); + // INIT -> DOWNLOAD_DATA, UPLOAD_TABLE_DATA, DOWNLOAD_TABLE_STRUCTURE, UPLOAD_TABLE_STRUCTURE + param.setTaskType("DOWNLOAD_DATA"); + param.setTaskName("juechen"); + + DataResult result = taskService.create(param); + DataResult taskDataResult = taskService.get(result.getData()); + System.out.println(taskDataResult.getData()); + Assertions.assertTrue(result.success(), result.errorMessage()); + } + } + + } + + @Test + public void testPage() { + userLoginIdentity(true, 12L); + + for (DialectProperties dialectProperties : dialectPropertiesList) { + Long dataSourceId = TestUtils.nextLong(); + Long consoleId = TestUtils.nextLong(); + TestUtils.buildContext(dialectProperties, dataSourceId, consoleId); + + if (dialectProperties.getDbType().equalsIgnoreCase("MYSQL")) { + TaskPageParam param = new TaskPageParam(); + param.setPageNo(1); + param.setPageSize(10); + param.setUserId(9L); + + PageResult result = taskService.page(param); + System.out.println(result.getData()); + Assertions.assertTrue(result.success(), result.errorMessage()); + } + } + } + + @Test + public void testUpdateStatus() { + userLoginIdentity(true, 5L); + + for (DialectProperties dialectProperties : dialectPropertiesList) { + Long dataSourceId = TestUtils.nextLong(); + Long consoleId = TestUtils.nextLong(); + TestUtils.buildContext(dialectProperties, dataSourceId, consoleId); + + if (dialectProperties.getDbType().equalsIgnoreCase("MYSQL")) { + TaskUpdateParam param = new TaskUpdateParam(); + param.setId(9L); + // DOWNLOAD_DATA, UPLOAD_TABLE_DATA, DOWNLOAD_TABLE_STRUCTURE, UPLOAD_TABLE_STRUCTURE + param.setTaskStatus("DOWNLOAD_TABLE_STRUCTURE"); + param.setContent(new byte[0]); + param.setDownloadUrl("success!"); + + ActionResult result = taskService.updateStatus(param); + DataResult taskDataResult = taskService.get(param.getId()); + System.out.println(taskDataResult.getData()); + Assertions.assertTrue(result.success(), result.errorMessage()); + } + } + } + + /** + * Save the current user identity (administrator or normal user) and user ID to the context and database session for subsequent use. + * + * @param isAdmin + * @param userId + */ + private static void userLoginIdentity(boolean isAdmin, Long userId) { + Context context = Context.builder().loginUser( + LoginUser.builder().admin(isAdmin).id(userId).build() + ).build(); + ContextUtils.setContext(context); + Dbutils.setSession(); + } + +} diff --git a/chat2db-server/chat2db-server-start/src/test/java/ai/chat2db/server/start/test/core/TeamServiceTest.java b/chat2db-server/chat2db-server-start/src/test/java/ai/chat2db/server/start/test/core/TeamServiceTest.java new file mode 100644 index 000000000..030d29a2c --- /dev/null +++ b/chat2db-server/chat2db-server-start/src/test/java/ai/chat2db/server/start/test/core/TeamServiceTest.java @@ -0,0 +1,100 @@ +package ai.chat2db.server.start.test.core; + +import ai.chat2db.server.domain.api.model.Team; +import ai.chat2db.server.domain.api.param.team.TeamCreateParam; +import ai.chat2db.server.domain.api.param.team.TeamPageQueryParam; +import ai.chat2db.server.domain.api.param.team.TeamSelector; +import ai.chat2db.server.domain.api.param.team.TeamUpdateParam; +import ai.chat2db.server.domain.core.impl.TeamServiceImpl; +import ai.chat2db.server.domain.repository.Dbutils; +import ai.chat2db.server.start.test.TestApplication; +import ai.chat2db.server.tools.base.wrapper.result.ActionResult; +import ai.chat2db.server.tools.base.wrapper.result.DataResult; +import ai.chat2db.server.tools.base.wrapper.result.ListResult; +import ai.chat2db.server.tools.base.wrapper.result.PageResult; +import ai.chat2db.server.tools.common.model.Context; +import ai.chat2db.server.tools.common.model.LoginUser; +import ai.chat2db.server.tools.common.util.ContextUtils; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.ArrayList; + +/** + * @author Juechen + * @version : TeamServiceTest.java + */ +public class TeamServiceTest extends TestApplication { + + @Autowired + private TeamServiceImpl teamService; + + @Test + public void testCreate() { + userLoginIdentity(false,8L); + TeamCreateParam param = new TeamCreateParam(); + param.setCode("57935"); + param.setStatus("VALID"); + param.setRoleCode("87129"); + param.setName("DEMO3"); + param.setDescription("this is just a test!"); + + DataResult result = teamService.create(param); + System.out.println("create team_id :" + result.getData()); + Assertions.assertTrue(result.getSuccess(), result.getErrorMessage()); + + ArrayList list = new ArrayList<>(); + list.add(result.getData()); + ListResult result1 = teamService.listQuery(list); + System.out.println("current team :" + result1.getData()); + Assertions.assertTrue(result1.getSuccess(), result1.getErrorMessage()); + + TeamPageQueryParam pageQueryParam = new TeamPageQueryParam(); + pageQueryParam.setPageNo(1); + pageQueryParam.setPageSize(10); + pageQueryParam.setSearchKey("MO"); + pageQueryParam.setEnableReturnCount(true); + pageQueryParam.setOrderByList(new ArrayList<>()); + TeamSelector selector = new TeamSelector(); + selector.setModifiedUser(false); + + PageResult result2 = teamService.pageQuery(pageQueryParam, selector); + for (Team team : result2.getData()) { + System.out.println("pageList :" + team + "/n"); + } + Assertions.assertTrue(result2.getSuccess(), result2.getErrorMessage()); + + TeamUpdateParam teamUpdateParam = new TeamUpdateParam(); + teamUpdateParam.setId(result.getData()); + teamUpdateParam.setStatus("INVALID"); + teamUpdateParam.setDescription("already update!"); + teamUpdateParam.setName("Juechen"); + + DataResult result3 = teamService.update(teamUpdateParam); + System.out.println("update team_id :" + result3.getData()); + Assertions.assertTrue(result3.getSuccess(), result3.getErrorMessage()); + ArrayList list2 = new ArrayList<>(); + list2.add(result.getData()); + ListResult result4 = teamService.listQuery(list); + System.out.println("current team :" + result4.getData()); + Assertions.assertTrue(result4.getSuccess(), result4.getErrorMessage()); + + ActionResult delete = teamService.delete(result3.getData()); + Assertions.assertTrue(delete.getSuccess(), delete.getErrorMessage()); + } + + /** + * Save the current user identity (administrator or normal user) and user ID to the context and database session for subsequent use. + * + * @param isAdmin + * @param userId + */ + private static void userLoginIdentity(boolean isAdmin, Long userId) { + Context context = Context.builder().loginUser( + LoginUser.builder().admin(isAdmin).id(userId).build() + ).build(); + ContextUtils.setContext(context); + Dbutils.setSession(); + } +} diff --git a/chat2db-server/chat2db-server-start/src/test/java/ai/chat2db/server/start/test/core/TeamUserServiceTest.java b/chat2db-server/chat2db-server-start/src/test/java/ai/chat2db/server/start/test/core/TeamUserServiceTest.java new file mode 100644 index 000000000..682018fed --- /dev/null +++ b/chat2db-server/chat2db-server-start/src/test/java/ai/chat2db/server/start/test/core/TeamUserServiceTest.java @@ -0,0 +1,81 @@ +package ai.chat2db.server.start.test.core; + +import ai.chat2db.server.domain.api.model.TeamUser; +import ai.chat2db.server.domain.api.param.team.user.TeamUserComprehensivePageQueryParam; +import ai.chat2db.server.domain.api.param.team.user.TeamUserCreatParam; +import ai.chat2db.server.domain.api.param.team.user.TeamUserPageQueryParam; +import ai.chat2db.server.domain.api.param.team.user.TeamUserSelector; +import ai.chat2db.server.domain.api.service.TeamUserService; +import ai.chat2db.server.domain.repository.Dbutils; +import ai.chat2db.server.start.test.TestApplication; +import ai.chat2db.server.tools.base.wrapper.result.ActionResult; +import ai.chat2db.server.tools.base.wrapper.result.DataResult; +import ai.chat2db.server.tools.base.wrapper.result.PageResult; +import ai.chat2db.server.tools.common.model.Context; +import ai.chat2db.server.tools.common.model.LoginUser; +import ai.chat2db.server.tools.common.util.ContextUtils; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * @author Juechen + * @version : TeamUserServiceTest.java + */ +public class TeamUserServiceTest extends TestApplication { + + @Autowired + private TeamUserService teamUserService; + + @Test + public void testPageQuery() { + userLoginIdentity(false,4L); + + TeamUserCreatParam teamUserCreatParam = new TeamUserCreatParam(); + teamUserCreatParam.setTeamId(1L); + teamUserCreatParam.setUserId(5L); + + DataResult longDataResult = teamUserService.create(teamUserCreatParam); + System.out.println("create id :" + longDataResult.getData()); + Assertions.assertTrue(longDataResult.getSuccess(),longDataResult.getErrorMessage()); + + TeamUserPageQueryParam param = new TeamUserPageQueryParam(); + param.setTeamId(teamUserCreatParam.getTeamId()); + param.setUserId(teamUserCreatParam.getUserId()); + TeamUserSelector selector = new TeamUserSelector(); + selector.setTeam(true); + selector.setUser(true); + + PageResult pageQuery = teamUserService.pageQuery(param, selector); + System.out.println("value :" + pageQuery.getData()); + Assertions.assertTrue(pageQuery.getSuccess(),pageQuery.getErrorMessage()); + + TeamUserComprehensivePageQueryParam pageQueryParam = new TeamUserComprehensivePageQueryParam(); + pageQueryParam.setPageNo(1); + pageQueryParam.setPageSize(10); + pageQueryParam.setUserId(teamUserCreatParam.getUserId()); + pageQueryParam.setTeamId(teamUserCreatParam.getTeamId()); + pageQueryParam.setTeamSearchKey("DE"); + PageResult comprehensivePageQuery = teamUserService.comprehensivePageQuery(pageQueryParam, selector); + System.out.println("total value :" + comprehensivePageQuery.getData()); + Assertions.assertTrue(comprehensivePageQuery.getSuccess(),comprehensivePageQuery.getErrorMessage()); + + ActionResult actionResult = teamUserService.delete(longDataResult.getData()); + Assertions.assertTrue(actionResult.getSuccess(),actionResult.getErrorMessage()); + + } + + /** + * Save the current user identity (administrator or normal user) and user ID to the context and database session for subsequent use. + * + * @param isAdmin + * @param userId + */ + private static void userLoginIdentity(boolean isAdmin, Long userId) { + Context context = Context.builder().loginUser( + LoginUser.builder().admin(isAdmin).id(userId).build() + ).build(); + ContextUtils.setContext(context); + Dbutils.setSession(); + } +} From 3037bc126a12dc6fe175fcdd65c673cba8556461 Mon Sep 17 00:00:00 2001 From: suyue <2016494681@qq.com> Date: Thu, 15 Aug 2024 11:18:15 +0800 Subject: [PATCH 23/40] unit test --- .../start/test/core/TriggerServiceTest.java | 82 ++++++++++++ .../start/test/core/UserServiceTest.java | 118 ++++++++++++++++++ .../start/test/core/ViewServiceTest.java | 83 ++++++++++++ 3 files changed, 283 insertions(+) create mode 100644 chat2db-server/chat2db-server-start/src/test/java/ai/chat2db/server/start/test/core/TriggerServiceTest.java create mode 100644 chat2db-server/chat2db-server-start/src/test/java/ai/chat2db/server/start/test/core/UserServiceTest.java create mode 100644 chat2db-server/chat2db-server-start/src/test/java/ai/chat2db/server/start/test/core/ViewServiceTest.java diff --git a/chat2db-server/chat2db-server-start/src/test/java/ai/chat2db/server/start/test/core/TriggerServiceTest.java b/chat2db-server/chat2db-server-start/src/test/java/ai/chat2db/server/start/test/core/TriggerServiceTest.java new file mode 100644 index 000000000..5406404d6 --- /dev/null +++ b/chat2db-server/chat2db-server-start/src/test/java/ai/chat2db/server/start/test/core/TriggerServiceTest.java @@ -0,0 +1,82 @@ +package ai.chat2db.server.start.test.core; + +import ai.chat2db.server.domain.api.service.TriggerService; +import ai.chat2db.server.domain.repository.Dbutils; +import ai.chat2db.server.start.test.TestApplication; +import ai.chat2db.server.start.test.dialect.DialectProperties; +import ai.chat2db.server.start.test.dialect.TestUtils; +import ai.chat2db.server.tools.base.wrapper.result.DataResult; +import ai.chat2db.server.tools.base.wrapper.result.ListResult; +import ai.chat2db.server.tools.common.model.Context; +import ai.chat2db.server.tools.common.model.LoginUser; +import ai.chat2db.server.tools.common.util.ContextUtils; +import ai.chat2db.spi.model.Trigger; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; + +/** + * @author Juechen + * @version : TriggerServiceTest.java + */ +public class TriggerServiceTest extends TestApplication { + + @Autowired + private TriggerService triggerService; + + @Autowired + private List dialectPropertiesList; + + @Test + public void testTriggers() { + userLoginIdentity(false,9L); + + for (DialectProperties dialectProperties : dialectPropertiesList) { + Long dataSourceId = TestUtils.nextLong(); + Long consoleId = TestUtils.nextLong(); + TestUtils.buildContext(dialectProperties, dataSourceId, consoleId); + + if (dialectProperties.getDbType().equalsIgnoreCase("mysql")) { + String databaseName = "ali_dbhub_test"; + ListResult triggers = triggerService.triggers(databaseName, ""); + for (Trigger trigger : triggers.getData()) { + DataResult detail = triggerService.detail(databaseName, "", trigger.getTriggerName()); + System.out.println(detail.getData()); + } + Assertions.assertTrue(triggers.getSuccess(), triggers.getErrorMessage()); + } else if (dialectProperties.getDbType().equalsIgnoreCase("postgresql")) { + String databaseName = "ali_dbhub_test"; + ListResult triggers = triggerService.triggers(databaseName, "test"); + for (Trigger trigger : triggers.getData()) { + DataResult detail = triggerService.detail(databaseName, "test", trigger.getTriggerName()); + System.out.println(detail.getData()); + } + Assertions.assertTrue(triggers.getSuccess(), triggers.getErrorMessage()); + } else if (dialectProperties.getDbType().equalsIgnoreCase("oracle")) { + String schemaName = "TEST_USER"; + ListResult triggers = triggerService.triggers("", schemaName); + for (Trigger trigger : triggers.getData()) { + DataResult detail = triggerService.detail("", schemaName, trigger.getTriggerName()); + System.out.println(detail.getData()); + } + Assertions.assertTrue(triggers.getSuccess(), triggers.getErrorMessage()); + } + } + } + + /** + * Save the current user identity (administrator or normal user) and user ID to the context and database session for subsequent use. + * + * @param isAdmin + * @param userId + */ + private static void userLoginIdentity(boolean isAdmin, Long userId) { + Context context = Context.builder().loginUser( + LoginUser.builder().admin(isAdmin).id(userId).build() + ).build(); + ContextUtils.setContext(context); + Dbutils.setSession(); + } +} diff --git a/chat2db-server/chat2db-server-start/src/test/java/ai/chat2db/server/start/test/core/UserServiceTest.java b/chat2db-server/chat2db-server-start/src/test/java/ai/chat2db/server/start/test/core/UserServiceTest.java new file mode 100644 index 000000000..b750d6b2a --- /dev/null +++ b/chat2db-server/chat2db-server-start/src/test/java/ai/chat2db/server/start/test/core/UserServiceTest.java @@ -0,0 +1,118 @@ +package ai.chat2db.server.start.test.core; + +import ai.chat2db.server.domain.api.model.User; +import ai.chat2db.server.domain.api.param.user.UserCreateParam; +import ai.chat2db.server.domain.api.param.user.UserPageQueryParam; +import ai.chat2db.server.domain.api.param.user.UserSelector; +import ai.chat2db.server.domain.api.param.user.UserUpdateParam; +import ai.chat2db.server.domain.api.service.UserService; +import ai.chat2db.server.domain.repository.Dbutils; +import ai.chat2db.server.start.test.TestApplication; +import ai.chat2db.server.tools.base.wrapper.result.ActionResult; +import ai.chat2db.server.tools.base.wrapper.result.DataResult; +import ai.chat2db.server.tools.base.wrapper.result.PageResult; +import ai.chat2db.server.tools.common.model.Context; +import ai.chat2db.server.tools.common.model.LoginUser; +import ai.chat2db.server.tools.common.util.ContextUtils; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +/** + * @author Juechen + * @version : UserServiceTest.java + */ +public class UserServiceTest extends TestApplication { + + @Autowired + private UserService userService; + + @Test + public void testAllMethods() { + userLoginIdentity(false,8L); + + UserCreateParam userCreateParam = new UserCreateParam(); + userCreateParam.setUserName("test_username08"); + userCreateParam.setEmail("123456789@gmail.com"); + userCreateParam.setPassword("123456"); + userCreateParam.setRoleCode("TEST"); + userCreateParam.setStatus("VALID"); + userCreateParam.setNickName("test_username686"); + DataResult dataResult = userService.create(userCreateParam); + System.out.println("create id:" + dataResult.getData()); + Assertions.assertTrue(dataResult.getSuccess(),dataResult.getErrorMessage()); + + DataResult query = userService.query(dataResult.getData()); + System.out.println("Specify id:" + query.getData()); + Assertions.assertTrue(query.getSuccess(),query.getErrorMessage()); + + DataResult user_name = userService.query("_desktop_default_user_name"); + System.out.println("Specify user_name: " + user_name.getData()); + Assertions.assertTrue(user_name.getSuccess(),user_name.getErrorMessage()); + + UserPageQueryParam param = new UserPageQueryParam(); + param.setPageNo(1); + param.setPageSize(8); + param.setEnableReturnCount(false); + param.setSearchKey(""); + UserSelector selector = new UserSelector(); + selector.setModifiedUser(false); + + PageResult result = userService.pageQuery(param, selector); + for (User user : result.getData()) { + System.out.println("list:" + user); + } + Assertions.assertTrue(result.getSuccess(),result.getErrorMessage()); + + // if id is 1, an BusinessException will be thrown + ActionResult actionResult = userService.delete(dataResult.getData()); + Assertions.assertTrue(actionResult.getSuccess(),actionResult.getErrorMessage()); + + PageResult pageQuery = userService.pageQuery(param, selector); + for (User user : pageQuery.getData()) { + System.out.println("After deletion list:" + user); + } + Assertions.assertTrue(pageQuery.getSuccess(),pageQuery.getErrorMessage()); + + } + + @Test + public void testUpdate() { + userLoginIdentity(false,8L); + + UserUpdateParam userUpdateParam = new UserUpdateParam(); + // If the id is 1, a "user.canNotOperateSystemAccount" exception will be thrown. + // userUpdateParam.setId(1L); + userUpdateParam.setId(3L); + userUpdateParam.setRoleCode("TEST05"); + userUpdateParam.setStatus("INVALID"); + userUpdateParam.setEmail("385962@gmail.com"); + userUpdateParam.setPassword("385962"); + + DataResult query = userService.query(userUpdateParam.getId()); + System.out.println("Original data :" + query.getData()); + Assertions.assertTrue(query.getSuccess(),query.getErrorMessage()); + + DataResult update = userService.update(userUpdateParam); + System.out.println("update id :" + update.getData()); + Assertions.assertTrue(update.getSuccess(),update.getErrorMessage()); + + DataResult result = userService.query(userUpdateParam.getId()); + System.out.println("update data :" + result.getData()); + Assertions.assertTrue(result.getSuccess(),result.getErrorMessage()); + } + + /** + * Save the current user identity (administrator or normal user) and user ID to the context and database session for subsequent use. + * + * @param isAdmin + * @param userId + */ + private static void userLoginIdentity(boolean isAdmin, Long userId) { + Context context = Context.builder().loginUser( + LoginUser.builder().admin(isAdmin).id(userId).build() + ).build(); + ContextUtils.setContext(context); + Dbutils.setSession(); + } +} diff --git a/chat2db-server/chat2db-server-start/src/test/java/ai/chat2db/server/start/test/core/ViewServiceTest.java b/chat2db-server/chat2db-server-start/src/test/java/ai/chat2db/server/start/test/core/ViewServiceTest.java new file mode 100644 index 000000000..c7cb9bbeb --- /dev/null +++ b/chat2db-server/chat2db-server-start/src/test/java/ai/chat2db/server/start/test/core/ViewServiceTest.java @@ -0,0 +1,83 @@ +package ai.chat2db.server.start.test.core; + +import ai.chat2db.server.domain.api.service.ViewService; +import ai.chat2db.server.domain.repository.Dbutils; +import ai.chat2db.server.start.test.TestApplication; +import ai.chat2db.server.start.test.dialect.DialectProperties; +import ai.chat2db.server.start.test.dialect.TestUtils; +import ai.chat2db.server.tools.base.wrapper.result.DataResult; +import ai.chat2db.server.tools.base.wrapper.result.ListResult; +import ai.chat2db.server.tools.common.model.Context; +import ai.chat2db.server.tools.common.model.LoginUser; +import ai.chat2db.server.tools.common.util.ContextUtils; +import ai.chat2db.spi.model.Table; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; +import org.springframework.beans.factory.annotation.Autowired; + +import java.util.List; + +/** + * @author Juechen + * @version : ViewServiceTest.java + */ +public class ViewServiceTest extends TestApplication { + + @Autowired + private ViewService viewService; + + @Autowired + private List dialectPropertiesList; + + @Test + public void testViews() { + userLoginIdentity(false, 9L); + + for (DialectProperties dialectProperties : dialectPropertiesList) { + Long dataSourceId = TestUtils.nextLong(); + Long consoleId = TestUtils.nextLong(); + TestUtils.buildContext(dialectProperties, dataSourceId, consoleId); + + if (dialectProperties.getDbType().equalsIgnoreCase("mysql")) { + String databaseName = "ali_dbhub_test"; + ListResult
views = viewService.views(databaseName, null); + for (Table table : views.getData()) { + DataResult
detail = viewService.detail(databaseName, null, table.getName()); + System.out.println("mysql:" + detail.getData()); + } + Assertions.assertTrue(views.getSuccess(),views.getErrorMessage()); + } else if (dialectProperties.getDbType().equalsIgnoreCase("postgresql")) { + String databaseName = "ali_dbhub_test"; + String schemaName = "test"; + ListResult
views = viewService.views(databaseName, schemaName); + for (Table table : views.getData()) { + DataResult
detail = viewService.detail(databaseName, schemaName, table.getName()); + System.out.println("postgresql:" + detail.getData()); + } + Assertions.assertTrue(views.getSuccess(),views.getErrorMessage()); + } else if (dialectProperties.getDbType().equalsIgnoreCase("oracle")) { + String schemaName = "TEST_USER"; + ListResult
views = viewService.views("", schemaName); + for (Table table : views.getData()) { + DataResult
detail = viewService.detail("", schemaName, table.getName()); + System.out.println("oracle:" + detail.getData()); + } + Assertions.assertTrue(views.getSuccess(),views.getErrorMessage()); + } + } + } + + /** + * Save the current user identity (administrator or normal user) and user ID to the context and database session for subsequent use. + * + * @param isAdmin + * @param userId + */ + private static void userLoginIdentity(boolean isAdmin, Long userId) { + Context context = Context.builder().loginUser( + LoginUser.builder().admin(isAdmin).id(userId).build() + ).build(); + ContextUtils.setContext(context); + Dbutils.setSession(); + } +} From ae199e407461dc60d2645116c875188af931489c Mon Sep 17 00:00:00 2001 From: suyue <2016494681@qq.com> Date: Fri, 16 Aug 2024 19:21:07 +0800 Subject: [PATCH 24/40] export current page CSV --- .../server/web/api/controller/rdb/RdbDmlExportController.java | 2 +- .../web/api/controller/rdb/request/DataExportRequest.java | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/rdb/RdbDmlExportController.java b/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/rdb/RdbDmlExportController.java index 0f554a2cc..35be10799 100644 --- a/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/rdb/RdbDmlExportController.java +++ b/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/rdb/RdbDmlExportController.java @@ -84,7 +84,7 @@ public void export(@Valid @RequestBody DataExportRequest request, HttpServletRes ExportTypeEnum exportType = EasyEnumUtils.getEnum(ExportTypeEnum.class, request.getExportType()); String sql; if (exportSize == ExportSizeEnum.CURRENT_PAGE) { - sql = request.getSql(); + sql = request.getOriginalSql() + " LIMIT " + request.getPageSize() + " OFFSET " + (request.getPageNo() - 1) * request.getPageSize(); } else { sql = request.getOriginalSql(); } diff --git a/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/rdb/request/DataExportRequest.java b/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/rdb/request/DataExportRequest.java index c4f02e7d1..747040ab6 100644 --- a/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/rdb/request/DataExportRequest.java +++ b/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/rdb/request/DataExportRequest.java @@ -23,6 +23,9 @@ public class DataExportRequest extends DataSourceBaseRequest { */ private String originalSql; + private Integer pageNo; + private Integer pageSize; + /** * export type * From c0eac9cbf7c77d0673c80d9f32c3a3e476f8e59e Mon Sep 17 00:00:00 2001 From: suyue <2016494681@qq.com> Date: Sat, 17 Aug 2024 11:18:42 +0800 Subject: [PATCH 25/40] export insertSQL --- .../web/api/controller/rdb/RdbDmlExportController.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/rdb/RdbDmlExportController.java b/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/rdb/RdbDmlExportController.java index 35be10799..a9014f254 100644 --- a/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/rdb/RdbDmlExportController.java +++ b/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/rdb/RdbDmlExportController.java @@ -5,6 +5,7 @@ import java.net.URLEncoder; import java.nio.charset.StandardCharsets; import java.time.LocalDateTime; +import java.util.ArrayList; import java.util.List; import ai.chat2db.spi.SqlBuilder; @@ -154,12 +155,20 @@ private void doExportInsert(String sql, HttpServletResponse response, String fil SqlBuilder sqlBuilder = Chat2DBContext.getMetaData().getSqlBuilder(); try (PrintWriter printWriter = response.getWriter()) { List headerColumns = Lists.newArrayList(); + List headers = new ArrayList<>(); InsertWrapper insertWrapper = new InsertWrapper(); SQLExecutor.getInstance().execute(Chat2DBContext.getConnection(), sql, headerList -> { headerList.forEach(sqlIdentifierExpr -> headerColumns.add(sqlIdentifierExpr.getName())); } , dataList -> { + for (String header : headerColumns) { + SQLIdentifierExpr expr = new SQLIdentifierExpr(header); + expr.setName(header); + headers.add(expr); + } + insertWrapper.setHeaderList(headers); + SQLInsertStatement sqlInsertStatement = new SQLInsertStatement(); sqlInsertStatement.setDbType(dbType); sqlInsertStatement.setTableSource(new SQLExprTableSource(tableName)); From 97cf17ffe21fcbc1cbdd3303ae470973c5953e46 Mon Sep 17 00:00:00 2001 From: tmlx1990 Date: Wed, 25 Sep 2024 20:22:48 +0800 Subject: [PATCH 26/40] =?UTF-8?q?=E4=BF=AE=E5=A4=8DPostgreSQL=E4=B8=ADDECI?= =?UTF-8?q?MAL=E3=80=81NUMERIC=E6=B2=A1=E6=9C=89=E5=B0=8F=E6=95=B0?= =?UTF-8?q?=E4=BD=8D=E9=97=AE=E9=A2=98=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plugin/postgresql/type/PostgreSQLColumnTypeEnum.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chat2db-server/chat2db-plugins/chat2db-postgresql/src/main/java/ai/chat2db/plugin/postgresql/type/PostgreSQLColumnTypeEnum.java b/chat2db-server/chat2db-plugins/chat2db-postgresql/src/main/java/ai/chat2db/plugin/postgresql/type/PostgreSQLColumnTypeEnum.java index c0b6a6213..8ee10ab2d 100644 --- a/chat2db-server/chat2db-plugins/chat2db-postgresql/src/main/java/ai/chat2db/plugin/postgresql/type/PostgreSQLColumnTypeEnum.java +++ b/chat2db-server/chat2db-plugins/chat2db-postgresql/src/main/java/ai/chat2db/plugin/postgresql/type/PostgreSQLColumnTypeEnum.java @@ -22,7 +22,7 @@ public enum PostgreSQLColumnTypeEnum implements ColumnBuilder { CIDR("CIDR", false, false, true, false, false, false, true, true, false, false), CIRCLE("CIRCLE", false, false, true, false, false, false, true, true, false, false), DATE("DATE", false, false, true, false, false, false, true, true, false, false), - DECIMAL("DECIMAL", true, false, true, false, false, false, true, true, false, false), + DECIMAL("DECIMAL", true, true, true, false, false, false, true, true, false, false), FLOAT4("FLOAT4", false, false, true, false, false, false, true, true, false, false), FLOAT8("FLOAT8", false, false, true, false, false, false, true, true, false, false), INET("INET", false, false, true, false, false, false, true, true, false, false), @@ -36,7 +36,7 @@ public enum PostgreSQLColumnTypeEnum implements ColumnBuilder { LSEG("LSEG", false, false, true, false, false, false, true, true, false, false), MACADDR("MACADDR", false, false, true, false, false, false, true, true, false, false), MONEY("MONEY", false, false, true, false, false, false, true, true, false, false), - NUMERIC("NUMERIC", true, false, true, false, false, false, true, true, false, false), + NUMERIC("NUMERIC", true, true, true, false, false, false, true, true, false, false), PATH("PATH", false, false, true, false, false, false, true, true, false, false), POINT("POINT", false, false, true, false, false, false, true, true, false, false), POLYGON("POLYGON", false, false, true, false, false, false, true, true, false, false), From 30a07b2da48d80bfe60592ef31c90472c85efe8d Mon Sep 17 00:00:00 2001 From: lzy <963565242@qq.com> Date: Thu, 17 Oct 2024 16:46:19 +0800 Subject: [PATCH 27/40] =?UTF-8?q?dbeaver=E7=9A=84=E5=AF=BC=E5=85=A5?= =?UTF-8?q?=E9=97=AE=E9=A2=98=E4=BF=AE=E5=A4=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ncx/service/impl/ConverterServiceImpl.java | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ncx/service/impl/ConverterServiceImpl.java b/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ncx/service/impl/ConverterServiceImpl.java index 5d6aa03c2..c039036cb 100644 --- a/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ncx/service/impl/ConverterServiceImpl.java +++ b/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ncx/service/impl/ConverterServiceImpl.java @@ -231,12 +231,14 @@ public UploadVO dbpUploadFile(File file) { dataSourceDO.setSsh(JSON.toJSONString(sshInfo)); if (null != credentialsJson) { JSONObject userInfo = credentialsJson.getJSONObject(key); - JSONObject userPassword = userInfo.getJSONObject(connection); - dataSourceDO.setUserName(userPassword.getString("user")); - DesUtil desUtil = new DesUtil(DesUtil.DES_KEY); - String password = userPassword.getString("password"); - String encryptStr = desUtil.encrypt(Optional.ofNullable(password).orElse(""), "CBC"); - dataSourceDO.setPassword(encryptStr); + if (null != userInfo) { + JSONObject userPassword = userInfo.getJSONObject(connection); + dataSourceDO.setUserName(userPassword.getString("user")); + DesUtil desUtil = new DesUtil(DesUtil.DES_KEY); + String password = userPassword.getString("password"); + String encryptStr = desUtil.encrypt(Optional.ofNullable(password).orElse(""), "CBC"); + dataSourceDO.setPassword(encryptStr); + } } dataSourceDO.setType(dataBaseType.name()); getDataSourceMapper().insert(dataSourceDO); From ec8c8e67d0d52e2e07789fa26945e451aded889d Mon Sep 17 00:00:00 2001 From: Jove Zhong Date: Tue, 22 Oct 2024 21:18:21 -0700 Subject: [PATCH 28/40] refine wording for en-us locale --- chat2db-client/src/i18n/en-us/common.ts | 16 ++++++++-------- chat2db-client/src/i18n/en-us/setting.ts | 2 +- chat2db-client/src/i18n/en-us/workspace.ts | 8 ++++---- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/chat2db-client/src/i18n/en-us/common.ts b/chat2db-client/src/i18n/en-us/common.ts index 5eef2d3e0..6340034f9 100644 --- a/chat2db-client/src/i18n/en-us/common.ts +++ b/chat2db-client/src/i18n/en-us/common.ts @@ -25,7 +25,7 @@ export default { 'common.button.open': 'Open', 'common.button.refresh': 'Refresh', 'common.button.execute': 'Run', - "common.button.import": 'Import SQL', + 'common.button.import': 'Import SQL', 'common.button.format': 'Format', 'common.message.successfulConfig': 'Successful configuration', 'common.text.successful': 'successful', @@ -55,8 +55,8 @@ export default { 'common.button.exportPdf': 'Export to Pdf', 'common.text.successfulExecution': 'Successful Execution', 'common.text.result': 'Result', - 'common.text.timeConsuming': 'Time Consuming', - 'common.text.searchRow': 'Search Row', + 'common.text.timeConsuming': 'Time Consumed', + 'common.text.searchRow': 'Query Result', 'common.text.noData': 'No Data', 'common.text.remindMeLater': 'Remind Me Later', 'common.text.goToUpdate': 'Go To Update', @@ -92,16 +92,16 @@ export default { 'common.button.cancelRequest': 'Cancel Request', 'common.button.executionError': 'Execution Error', 'common.text.affectedRows': 'Affected rows: {1}', - 'common.text.selectFile' : 'Select File', - 'common.text.noTableFoundUp' : 'No tables in this database', + 'common.text.selectFile': 'Select File', + 'common.text.noTableFoundUp': 'No tables in this database', 'common.text.noTableFoundDown': 'Switch databases at the top', 'common.title.preview': 'Preview', 'common.title.errorMessage': 'Error message', 'common.label.comment': 'Comment', 'common.label.name': 'Name', 'common.title.create': 'Create', - 'common.title.executiveLogging': 'Executive logging', - 'common.text.executionTime': 'Affected in {1} ms', + 'common.title.executiveLogging': 'Runtime logs', + 'common.text.executionTime': 'Done with {1} ms', 'common.button.copyRowAs': 'Copy the row as', 'common.button.insertSql': 'Insert SQL', 'common.button.updateSql': 'Update SQL', @@ -120,4 +120,4 @@ export default { 'common.label.LocalFile': 'LocalFile', 'common.text.rename': 'Rename', 'common.title.info': 'Info', -}; +}; diff --git a/chat2db-client/src/i18n/en-us/setting.ts b/chat2db-client/src/i18n/en-us/setting.ts index afeabc384..01479b18e 100644 --- a/chat2db-client/src/i18n/en-us/setting.ts +++ b/chat2db-client/src/i18n/en-us/setting.ts @@ -48,7 +48,7 @@ export default { 'setting.text.isLatestVersion': 'This is the latest version', 'setting.button.changeLog': 'Changelog', 'setting.title.updateRule': 'Update rule', - 'setting.text.autoUpdate': 'The new version automatically downloads and installs updates', + 'setting.text.autoUpdate': 'The new version will be automatically downloaded and installed', 'setting.text.manualUpdate': 'Only alert me when a new version is released', 'setting.button.iSee': 'I see', 'setting.text.newEditionIsReady': diff --git a/chat2db-client/src/i18n/en-us/workspace.ts b/chat2db-client/src/i18n/en-us/workspace.ts index d81ca0556..8f4bdcff8 100644 --- a/chat2db-client/src/i18n/en-us/workspace.ts +++ b/chat2db-client/src/i18n/en-us/workspace.ts @@ -20,10 +20,10 @@ export default { 'The table name you entered is not the same as the table name you want to delete, please confirm again', 'workspace.table.total': 'Total', 'workspace.table.total.tip': 'Load total number of rows', - 'workspace.table.export.all.csv': 'Export result set csv', - 'workspace.table.export.cur.csv': 'Export result of current page set csv', - 'workspace.table.export.all.insert': 'Export result set insert sql', - 'workspace.table.export.cur.insert': 'Export result of current page set insert sql', + 'workspace.table.export.all.csv': 'Export results as a CSV', + 'workspace.table.export.cur.csv': 'Export results on the current page as a CSV', + 'workspace.table.export.all.insert': 'Export results as INSERT SQL', + 'workspace.table.export.cur.insert': 'Export results on the current page as INSERT SQL', 'workspace.tree.view': 'View', 'workspace.tree.trigger': 'Trigger', 'workspace.tree.function': 'Function', From 778812e8a58ac58c1e644d82c50600bfdcf8f687 Mon Sep 17 00:00:00 2001 From: Jove Zhong Date: Tue, 22 Oct 2024 21:45:45 -0700 Subject: [PATCH 29/40] initial version of timeplus plugin --- .../ConnectionEdit/config/dataSource.ts | 519 ++++++------ chat2db-client/src/constants/common.ts | 13 +- chat2db-client/src/constants/database.ts | 11 +- chat2db-client/src/utils/database.ts | 7 +- .../chat2db-plugins/chat2db-timeplus/pom.xml | 34 + .../plugin/timeplus/TimeplusDBManage.java | 196 +++++ .../plugin/timeplus/TimeplusMetaData.java | 401 ++++++++++ .../plugin/timeplus/TimeplusPlugin.java | 29 + .../timeplus/builder/TimeplusSqlBuilder.java | 215 +++++ .../ai/chat2db/plugin/timeplus/timeplus.json | 18 + .../timeplus/type/TimeplusColumnTypeEnum.java | 752 ++++++++++++++++++ .../timeplus/type/TimeplusEngineTypeEnum.java | 419 ++++++++++ .../timeplus/type/TimeplusIndexTypeEnum.java | 129 +++ .../META-INF/services/ai.chat2db.spi.Plugin | 1 + chat2db-server/chat2db-plugins/pom.xml | 3 +- 15 files changed, 2487 insertions(+), 260 deletions(-) create mode 100644 chat2db-server/chat2db-plugins/chat2db-timeplus/pom.xml create mode 100644 chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/TimeplusDBManage.java create mode 100644 chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/TimeplusMetaData.java create mode 100644 chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/TimeplusPlugin.java create mode 100644 chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/builder/TimeplusSqlBuilder.java create mode 100644 chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/timeplus.json create mode 100644 chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/type/TimeplusColumnTypeEnum.java create mode 100644 chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/type/TimeplusEngineTypeEnum.java create mode 100644 chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/type/TimeplusIndexTypeEnum.java create mode 100644 chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/resources/META-INF/services/ai.chat2db.spi.Plugin diff --git a/chat2db-client/src/components/ConnectionEdit/config/dataSource.ts b/chat2db-client/src/components/ConnectionEdit/config/dataSource.ts index 72d71ba8c..240f867b7 100644 --- a/chat2db-client/src/components/ConnectionEdit/config/dataSource.ts +++ b/chat2db-client/src/components/ConnectionEdit/config/dataSource.ts @@ -22,7 +22,6 @@ export const sshConfig: IConnectionConfig['ssh'] = { value: true, }, ], - }, { defaultValue: '', @@ -33,7 +32,7 @@ export const sshConfig: IConnectionConfig['ssh'] = { required: false, styles: { width: '70%', - } + }, }, { defaultValue: '22', @@ -46,8 +45,8 @@ export const sshConfig: IConnectionConfig['ssh'] = { width: '30%', labelWidthEN: '40px', labelWidthCN: '70px', - labelAlign: 'right' - } + labelAlign: 'right', + }, }, { defaultValue: '', @@ -58,7 +57,7 @@ export const sshConfig: IConnectionConfig['ssh'] = { required: false, styles: { width: '70%', - } + }, }, { defaultValue: '', @@ -73,8 +72,8 @@ export const sshConfig: IConnectionConfig['ssh'] = { width: '30%', labelWidthEN: '70px', labelWidthCN: '70px', - labelAlign: 'right' - } + labelAlign: 'right', + }, }, { defaultValue: 'password', @@ -125,13 +124,12 @@ export const sshConfig: IConnectionConfig['ssh'] = { ], styles: { width: '50%', - } + }, }, + ], +}; - ] -} - -const envItem = { +const envItem = { defaultValue: '', inputType: InputType.SELECT, labelNameCN: '环境', @@ -141,8 +139,8 @@ const envItem = { selects: [], styles: { width: '50%', - } -} + }, +}; export const dataSourceFormConfigs: IConnectionConfig[] = [ // MYSQL @@ -167,7 +165,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '70%', - } + }, }, { defaultValue: '3306', @@ -181,8 +179,8 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ width: '30%', labelWidthEN: '40px', labelWidthCN: '40px', - labelAlign: 'right' - } + labelAlign: 'right', + }, }, { defaultValue: AuthenticationType.USERANDPASSWORD, @@ -218,12 +216,11 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ label: 'NONE', value: AuthenticationType.NONE, items: [], - }, ], styles: { width: '50%', - } + }, }, { defaultValue: '', @@ -248,17 +245,17 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ ssh: sshConfig, extendInfo: [ { - "key": "zeroDateTimeBehavior", - "value": "convertToNull" + key: 'zeroDateTimeBehavior', + value: 'convertToNull', }, { - "key": "useInformationSchema", - "value": "true" + key: 'useInformationSchema', + value: 'true', }, { - "key": "tinyInt1isBit", - "value": "false" - } + key: 'tinyInt1isBit', + value: 'false', + }, ], type: DatabaseTypeCode.MYSQL, }, @@ -285,8 +282,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '70%', - - } + }, }, { defaultValue: '5432', @@ -300,8 +296,8 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ width: '30%', labelWidthEN: '40px', labelWidthCN: '40px', - labelAlign: 'right' - } + labelAlign: 'right', + }, }, { defaultValue: AuthenticationType.USERANDPASSWORD, @@ -320,7 +316,6 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ labelNameEN: 'User', name: 'user', required: true, - }, { defaultValue: '', @@ -329,24 +324,20 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ labelNameEN: 'Password', name: 'password', required: true, - }, ], label: 'User&Password', value: AuthenticationType.USERANDPASSWORD, }, { - label: 'NONE', value: AuthenticationType.NONE, items: [], - }, ], styles: { width: '50%', - - } + }, }, { defaultValue: 'postgres', @@ -355,7 +346,6 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ labelNameEN: 'Database', name: 'database', required: false, - }, { defaultValue: 'jdbc:postgresql://localhost:5432', @@ -364,7 +354,6 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ labelNameEN: 'URL', name: 'url', required: true, - }, ], pattern: /jdbc:postgresql:\/\/(.*):(\d+)(\/(\w+))?/, @@ -395,8 +384,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '70%', - - } + }, }, { defaultValue: '1521', @@ -410,8 +398,8 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ width: '30%', labelWidthEN: '40px', labelWidthCN: '40px', - labelAlign: 'right' - } + labelAlign: 'right', + }, }, { defaultValue: 'sid', @@ -434,39 +422,41 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '70%', - } + }, }, ], onChange: (data: IConnectionConfig) => { data.baseInfo.pattern = /jdbc:oracle:(.*):@(.*):(\d+):(.*)/; data.baseInfo.template = 'jdbc:oracle:{driver}:@{host}:{port}:{sid}'; - return data - } + return data; + }, }, { label: 'Service', value: 'service', - items: [{ - defaultValue: 'XE', - inputType: InputType.INPUT, - labelNameCN: '服务名', - labelNameEN: 'Service name', - name: 'serviceName', - required: true, - styles: { - width: '70%', + items: [ + { + defaultValue: 'XE', + inputType: InputType.INPUT, + labelNameCN: '服务名', + labelNameEN: 'Service name', + name: 'serviceName', + required: true, + styles: { + width: '70%', + }, }, - }], + ], onChange: (data: IConnectionConfig) => { data.baseInfo.pattern = /jdbc:oracle:(.*):@\/\/(.*):(\d+)\/(.*)/; data.baseInfo.template = 'jdbc:oracle:{driver}:@//{host}:{port}/{serviceName}'; - return data - } + return data; + }, }, ], styles: { width: '50%', - } + }, }, { defaultValue: 'thin', @@ -486,7 +476,6 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ label: 'oci', }, { - value: 'oci8', label: 'oci8', }, @@ -495,8 +484,8 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ width: '30%', labelWidthEN: '70px', labelWidthCN: '40px', - labelAlign: 'right' - } + labelAlign: 'right', + }, }, { defaultValue: AuthenticationType.USERANDPASSWORD, @@ -515,7 +504,6 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ labelNameEN: 'User', name: 'user', required: true, - }, { defaultValue: '', @@ -524,24 +512,20 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ labelNameEN: 'Password', name: 'password', required: true, - }, ], label: 'User&Password', value: AuthenticationType.USERANDPASSWORD, }, { - label: 'NONE', value: AuthenticationType.NONE, items: [], - }, ], styles: { width: '50%', - - } + }, }, { defaultValue: 'jdbc:oracle:thin:@localhost:1521:XE', @@ -580,7 +564,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '70%', - } + }, }, { defaultValue: '9092', @@ -594,8 +578,8 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ width: '30%', labelWidthEN: '40px', labelWidthCN: '40px', - labelAlign: 'right' - } + labelAlign: 'right', + }, }, { defaultValue: 'TCP', @@ -612,8 +596,8 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ onChange: (data: IConnectionConfig) => { data.baseInfo.pattern = /jdbc:h2:tcp:\/\/(.*):(\d+)(\/(\w+))?/; data.baseInfo.template = 'jdbc:h2:tcp://{host}:{port}/{database}'; - return data - } + return data; + }, }, { label: i18n('common.label.LocalFile'), @@ -631,13 +615,13 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ onChange: (data: IConnectionConfig) => { data.baseInfo.pattern = /jdbc:h2:(.*)?/; data.baseInfo.template = 'jdbc:h2:{file}'; - return data - } + return data; + }, }, ], styles: { width: '70%', - } + }, }, { defaultValue: AuthenticationType.USERANDPASSWORD, @@ -656,7 +640,6 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ labelNameEN: 'User', name: 'user', required: true, - }, { defaultValue: '', @@ -665,7 +648,6 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ labelNameEN: 'Password', name: 'password', required: true, - }, ], @@ -673,7 +655,6 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ value: AuthenticationType.USERANDPASSWORD, }, { - label: 'NONE', value: AuthenticationType.NONE, items: [], @@ -681,8 +662,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ ], styles: { width: '50%', - - } + }, }, { defaultValue: '', @@ -699,7 +679,6 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ labelNameEN: 'URL', name: 'url', required: true, - }, ], pattern: /jdbc:h2:tcp:\/\/(.*):(\d+)(\/(\w+))?/, @@ -712,20 +691,20 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ type: DatabaseTypeCode.SQLSERVER, extendInfo: [ { - "key": "encrypt", - "value": "false" + key: 'encrypt', + value: 'false', }, { - "key": "trustServerCertificate", - "value": "true" + key: 'trustServerCertificate', + value: 'true', }, { - "key": "integratedSecurity", - "value": "false" + key: 'integratedSecurity', + value: 'false', }, { - "key": "Trusted_Connection", - "value": "yes" + key: 'Trusted_Connection', + value: 'yes', }, ], baseInfo: { @@ -748,7 +727,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '70%', - } + }, }, { defaultValue: '1433', @@ -762,8 +741,8 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ width: '30%', labelWidthEN: '40px', labelWidthCN: '40px', - labelAlign: 'right' - } + labelAlign: 'right', + }, }, { defaultValue: '', @@ -790,7 +769,6 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ labelNameEN: 'User', name: 'user', required: true, - }, { defaultValue: '', @@ -799,7 +777,6 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ labelNameEN: 'Password', name: 'password', required: true, - }, ], @@ -807,17 +784,14 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ value: AuthenticationType.USERANDPASSWORD, }, { - label: 'NONE', value: AuthenticationType.NONE, items: [], - }, ], styles: { width: '50%', - - } + }, }, { defaultValue: '', @@ -853,7 +827,6 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ labelNameEN: 'Name', name: 'alias', required: true, - }, envItem, { @@ -871,7 +844,6 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ labelNameEN: 'URL', name: 'url', required: true, - }, ], pattern: /jdbc:sqlite:(.*)?/, @@ -891,7 +863,6 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ labelNameEN: 'Name', name: 'alias', required: true, - }, envItem, { @@ -903,8 +874,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '70%', - - } + }, }, { defaultValue: '3306', @@ -918,8 +888,8 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ width: '30%', labelWidthEN: '40px', labelWidthCN: '40px', - labelAlign: 'right' - } + labelAlign: 'right', + }, }, { defaultValue: AuthenticationType.USERANDPASSWORD, @@ -938,7 +908,6 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ labelNameEN: 'User', name: 'user', required: true, - }, { defaultValue: '', @@ -947,7 +916,6 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ labelNameEN: 'Password', name: 'password', required: true, - }, ], @@ -955,17 +923,14 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ value: AuthenticationType.USERANDPASSWORD, }, { - label: 'NONE', value: AuthenticationType.NONE, items: [], - }, ], styles: { width: '50%', - - } + }, }, { defaultValue: '', @@ -974,7 +939,6 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ labelNameEN: 'Database', name: 'database', required: false, - }, { defaultValue: 'jdbc:mariadb://localhost:3306', @@ -983,7 +947,6 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ labelNameEN: 'URL', name: 'url', required: true, - }, ], pattern: /jdbc:mariadb:\/\/(.*):(\d+)(\/(\w+))?/, @@ -1003,7 +966,6 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ labelNameEN: 'Name', name: 'alias', required: true, - }, envItem, { @@ -1015,8 +977,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '70%', - - } + }, }, { defaultValue: '8123', @@ -1030,8 +991,8 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ width: '30%', labelWidthEN: '40px', labelWidthCN: '40px', - labelAlign: 'right' - } + labelAlign: 'right', + }, }, { defaultValue: AuthenticationType.USERANDPASSWORD, @@ -1050,7 +1011,6 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ labelNameEN: 'User', name: 'user', required: true, - }, { defaultValue: '', @@ -1059,7 +1019,6 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ labelNameEN: 'Password', name: 'password', required: true, - }, ], @@ -1067,17 +1026,14 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ value: AuthenticationType.USERANDPASSWORD, }, { - label: 'NONE', value: AuthenticationType.NONE, items: [], - }, ], styles: { width: '50%', - - } + }, }, { defaultValue: '', @@ -1086,7 +1042,6 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ labelNameEN: 'Database', name: 'database', required: false, - }, { defaultValue: 'jdbc:clickhouse://localhost:8123', @@ -1095,12 +1050,11 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ labelNameEN: 'URL', name: 'url', required: true, - }, ], pattern: /jdbc:clickhouse:\/\/(.*):(\d+)(\/(\w+))?/, template: 'jdbc:clickhouse://{host}:{port}/{database}', - excludes: [OperationColumn.ViewDDL, OperationColumn.CreateTable,OperationColumn.EditTable] + excludes: [OperationColumn.ViewDDL, OperationColumn.CreateTable, OperationColumn.EditTable], //排除掉导出ddl 和 创建表功能 支持的功能见 ./enum.ts => OperationColumn }, ssh: sshConfig, @@ -1116,7 +1070,6 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ labelNameEN: 'Name', name: 'alias', required: true, - }, envItem, { @@ -1128,8 +1081,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '70%', - - } + }, }, { defaultValue: '5236', @@ -1143,8 +1095,8 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ width: '30%', labelWidthEN: '40px', labelWidthCN: '40px', - labelAlign: 'right' - } + labelAlign: 'right', + }, }, { defaultValue: AuthenticationType.USERANDPASSWORD, @@ -1163,7 +1115,6 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ labelNameEN: 'User', name: 'user', required: true, - }, { defaultValue: '', @@ -1185,8 +1136,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ ], styles: { width: '50%', - - } + }, }, { defaultValue: '', @@ -1195,7 +1145,6 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ labelNameEN: 'Database', name: 'database', required: false, - }, { defaultValue: 'jdbc:dm://localhost:5236', @@ -1204,22 +1153,20 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ labelNameEN: 'URL', name: 'url', required: true, - }, ], pattern: /jdbc:dm:\/\/(.*):(\d+)(\/(\w+))?/, template: 'jdbc:dm://{host}:{port}/{database}', // excludes: [OperationColumn.EditTable] - }, ssh: sshConfig, extendInfo: [ { - "key": "zeroDateTimeBehavior", - "value": "convertToNull" + key: 'zeroDateTimeBehavior', + value: 'convertToNull', }, ], - type: DatabaseTypeCode.DM + type: DatabaseTypeCode.DM, }, //DB2 { @@ -1234,7 +1181,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '100%', - } + }, }, envItem, { @@ -1246,7 +1193,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '70%', - } + }, }, { defaultValue: '50000', @@ -1260,8 +1207,8 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ width: '30%', labelWidthEN: '40px', labelWidthCN: '40px', - labelAlign: 'right' - } + labelAlign: 'right', + }, }, { defaultValue: AuthenticationType.USERANDPASSWORD, @@ -1282,7 +1229,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '100%', - } + }, }, { defaultValue: '', @@ -1293,7 +1240,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '100%', - } + }, }, ], label: 'User&Password', @@ -1303,12 +1250,11 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ label: 'NONE', value: AuthenticationType.NONE, items: [], - }, ], styles: { width: '50%', - } + }, }, { defaultValue: '', @@ -1319,7 +1265,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: false, styles: { width: '100%', - } + }, }, { defaultValue: 'jdbc:db2://localhost:50000', @@ -1330,20 +1276,16 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '100%', - } + }, }, - ], pattern: /jdbc:db2:\/\/(.*):(\d+)(\/(\w+))?/, template: 'jdbc:db2://{host}:{port}/{database}', // excludes: [OperationColumn.EditTable] - }, ssh: sshConfig, - extendInfo: [ - - ], - type: DatabaseTypeCode.DB2 + extendInfo: [], + type: DatabaseTypeCode.DB2, }, //presto { @@ -1358,7 +1300,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '100%', - } + }, }, envItem, { @@ -1370,7 +1312,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '70%', - } + }, }, { defaultValue: '8080', @@ -1384,8 +1326,8 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ width: '30%', labelWidthEN: '40px', labelWidthCN: '40px', - labelAlign: 'right' - } + labelAlign: 'right', + }, }, { defaultValue: AuthenticationType.USERANDPASSWORD, @@ -1406,7 +1348,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '100%', - } + }, }, { defaultValue: '', @@ -1417,7 +1359,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '100%', - } + }, }, ], label: 'User&Password', @@ -1427,12 +1369,11 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ label: 'NONE', value: AuthenticationType.NONE, items: [], - }, ], styles: { width: '50%', - } + }, }, { defaultValue: '', @@ -1443,7 +1384,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: false, styles: { width: '100%', - } + }, }, { defaultValue: 'jdbc:presto://localhost:8080', @@ -1454,20 +1395,16 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '100%', - } + }, }, - ], pattern: /jdbc:presto:\/\/(.*):(\d+)(\/(\w+))?/, template: 'jdbc:presto://{host}:{port}/{database}', // excludes: [OperationColumn.EditTable] - }, ssh: sshConfig, - extendInfo: [ - - ], - type: DatabaseTypeCode.PRESTO + extendInfo: [], + type: DatabaseTypeCode.PRESTO, }, //oceanbase { @@ -1482,7 +1419,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '100%', - } + }, }, envItem, { @@ -1494,7 +1431,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '70%', - } + }, }, { defaultValue: '2883', @@ -1508,8 +1445,8 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ width: '30%', labelWidthEN: '40px', labelWidthCN: '40px', - labelAlign: 'right' - } + labelAlign: 'right', + }, }, { defaultValue: AuthenticationType.USERANDPASSWORD, @@ -1530,7 +1467,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '100%', - } + }, }, { defaultValue: '', @@ -1541,7 +1478,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '100%', - } + }, }, ], label: 'User&Password', @@ -1551,12 +1488,11 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ label: 'NONE', value: AuthenticationType.NONE, items: [], - }, ], styles: { width: '50%', - } + }, }, { defaultValue: '', @@ -1567,7 +1503,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: false, styles: { width: '100%', - } + }, }, { defaultValue: 'jdbc:oceanbase://localhost:2883', @@ -1578,20 +1514,16 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '100%', - } + }, }, - ], pattern: /jdbc:oceanbase:\/\/(.*):(\d+)(\/(\w+))?/, template: 'jdbc:oceanbase://{host}:{port}/{database}', // excludes: [OperationColumn.EditTable] - }, ssh: sshConfig, - extendInfo: [ - - ], - type: DatabaseTypeCode.OCEANBASE + extendInfo: [], + type: DatabaseTypeCode.OCEANBASE, }, //redis { @@ -1606,7 +1538,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '100%', - } + }, }, envItem, { @@ -1618,7 +1550,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '70%', - } + }, }, { defaultValue: '6379', @@ -1632,8 +1564,8 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ width: '30%', labelWidthEN: '40px', labelWidthCN: '40px', - labelAlign: 'right' - } + labelAlign: 'right', + }, }, { defaultValue: AuthenticationType.USERANDPASSWORD, @@ -1654,7 +1586,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '100%', - } + }, }, { defaultValue: '', @@ -1665,7 +1597,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '100%', - } + }, }, ], label: 'User&Password', @@ -1675,12 +1607,11 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ label: 'NONE', value: AuthenticationType.NONE, items: [], - }, ], styles: { width: '50%', - } + }, }, { defaultValue: '', @@ -1691,7 +1622,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: false, styles: { width: '100%', - } + }, }, { defaultValue: 'jdbc:redis://localhost:6379', @@ -1702,18 +1633,15 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '100%', - } + }, }, - ], pattern: /jdbc:redis:\/\/(.*):(\d+)(\/(\w+))?/, template: 'jdbc:redis://{host}:{port}/{database}', }, ssh: sshConfig, - extendInfo: [ - - ], - type: DatabaseTypeCode.REDIS + extendInfo: [], + type: DatabaseTypeCode.REDIS, }, //hive { @@ -1728,7 +1656,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '100%', - } + }, }, envItem, { @@ -1740,7 +1668,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '70%', - } + }, }, { defaultValue: '10000', @@ -1754,8 +1682,8 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ width: '30%', labelWidthEN: '40px', labelWidthCN: '40px', - labelAlign: 'right' - } + labelAlign: 'right', + }, }, { defaultValue: AuthenticationType.USERANDPASSWORD, @@ -1776,7 +1704,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '100%', - } + }, }, { defaultValue: '', @@ -1787,7 +1715,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '100%', - } + }, }, ], label: 'User&Password', @@ -1797,12 +1725,11 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ label: 'NONE', value: AuthenticationType.NONE, items: [], - }, ], styles: { width: '50%', - } + }, }, { defaultValue: '', @@ -1813,7 +1740,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: false, styles: { width: '100%', - } + }, }, { defaultValue: 'jdbc:hive2://localhost:10000', @@ -1824,20 +1751,16 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '100%', - } + }, }, - ], pattern: /jdbc:hive2:\/\/(.*):(\d+)(\/(\w+))?/, template: 'jdbc:hive2://{host}:{port}/{database}', // excludes: [OperationColumn.EditTable] - }, ssh: sshConfig, - extendInfo: [ - - ], - type: DatabaseTypeCode.HIVE + extendInfo: [], + type: DatabaseTypeCode.HIVE, }, //KINGBASE { @@ -1852,7 +1775,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '100%', - } + }, }, envItem, { @@ -1864,7 +1787,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '70%', - } + }, }, { defaultValue: '54321', @@ -1878,8 +1801,8 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ width: '30%', labelWidthEN: '40px', labelWidthCN: '40px', - labelAlign: 'right' - } + labelAlign: 'right', + }, }, { defaultValue: AuthenticationType.USERANDPASSWORD, @@ -1900,7 +1823,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '100%', - } + }, }, { defaultValue: '', @@ -1911,7 +1834,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '100%', - } + }, }, ], label: 'User&Password', @@ -1921,12 +1844,11 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ label: 'NONE', value: AuthenticationType.NONE, items: [], - }, ], styles: { width: '50%', - } + }, }, { defaultValue: '', @@ -1937,7 +1859,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: false, styles: { width: '100%', - } + }, }, { defaultValue: 'jdbc:kingbase8://127.0.0.1:54321', @@ -1948,20 +1870,16 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '100%', - } + }, }, - ], pattern: /jdbc:kingbase8:\/\/(.*):(\d+)(\/(\w+))?/, template: 'jdbc:kingbase8://{host}:{port}/{database}', // excludes: [OperationColumn.EditTable] - }, ssh: sshConfig, - extendInfo: [ - - ], - type: DatabaseTypeCode.KINGBASE + extendInfo: [], + type: DatabaseTypeCode.KINGBASE, }, //MONGODB { @@ -1976,7 +1894,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '100%', - } + }, }, envItem, { @@ -1988,7 +1906,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '70%', - } + }, }, { defaultValue: '27017', @@ -2002,8 +1920,8 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ width: '30%', labelWidthEN: '40px', labelWidthCN: '40px', - labelAlign: 'right' - } + labelAlign: 'right', + }, }, { defaultValue: AuthenticationType.USERANDPASSWORD, @@ -2024,7 +1942,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '100%', - } + }, }, { defaultValue: '', @@ -2035,7 +1953,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '100%', - } + }, }, ], label: 'User&Password', @@ -2045,12 +1963,11 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ label: 'NONE', value: AuthenticationType.NONE, items: [], - }, ], styles: { width: '50%', - } + }, }, { defaultValue: '', @@ -2061,7 +1978,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: false, styles: { width: '100%', - } + }, }, { defaultValue: 'mongodb://localhost:27017', @@ -2072,16 +1989,120 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: true, styles: { width: '100%', - } + }, }, - ], pattern: /mongodb:\/\/(.*):(\d+)(\/(\w+))?/, template: 'mongodb://{host}:{port}/{database}', - excludes: [OperationColumn.ViewDDL, OperationColumn.CreateTable,OperationColumn.EditTable] + excludes: [OperationColumn.ViewDDL, OperationColumn.CreateTable, OperationColumn.EditTable], }, ssh: sshConfig, extendInfo: [], - type: DatabaseTypeCode.MONGODB + type: DatabaseTypeCode.MONGODB, + }, + // TIMEPLUS + { + type: DatabaseTypeCode.TIMEPLUS, + baseInfo: { + items: [ + { + defaultValue: 'timeplus', + inputType: InputType.INPUT, + labelNameCN: '名称', + labelNameEN: 'Name', + name: 'alias', + required: true, + }, + envItem, + { + defaultValue: 'localhost', + inputType: InputType.INPUT, + labelNameCN: '主机', + labelNameEN: 'Host', + name: 'host', + required: true, + styles: { + width: '70%', + }, + }, + { + defaultValue: '8463', + inputType: InputType.INPUT, + labelNameCN: '端口', + labelNameEN: 'Port', + name: 'port', + labelTextAlign: 'right', + required: true, + styles: { + width: '30%', + labelWidthEN: '40px', + labelWidthCN: '40px', + labelAlign: 'right', + }, + }, + { + defaultValue: AuthenticationType.USERANDPASSWORD, + inputType: InputType.SELECT, + labelNameCN: '身份验证', + labelNameEN: 'Authentication', + name: 'authenticationType', + required: true, + selects: [ + { + items: [ + { + defaultValue: 'default', + inputType: InputType.INPUT, + labelNameCN: '用户名', + labelNameEN: 'User', + name: 'user', + required: true, + }, + { + defaultValue: '', + inputType: InputType.PASSWORD, + labelNameCN: '密码', + labelNameEN: 'Password', + name: 'password', + required: true, + }, + ], + + label: 'User&Password', + value: AuthenticationType.USERANDPASSWORD, + }, + { + label: 'NONE', + value: AuthenticationType.NONE, + items: [], + }, + ], + styles: { + width: '50%', + }, + }, + { + defaultValue: '', + inputType: InputType.INPUT, + labelNameCN: '数据库', + labelNameEN: 'Database', + name: 'database', + required: false, + }, + { + defaultValue: 'jdbc:timeplus://localhost:8463', + inputType: InputType.INPUT, + labelNameCN: 'URL', + labelNameEN: 'URL', + name: 'url', + required: true, + }, + ], + pattern: /jdbc:timeplus:\/\/(.*):(\d+)(\/(\w+))?/, + template: 'jdbc:timeplus://{host}:{port}/{database}', + excludes: [OperationColumn.ViewDDL, OperationColumn.CreateTable, OperationColumn.EditTable], + //排除掉导出ddl 和 创建表功能 支持的功能见 ./enum.ts => OperationColumn + }, + ssh: sshConfig, }, ]; diff --git a/chat2db-client/src/constants/common.ts b/chat2db-client/src/constants/common.ts index b6f2339be..44824008d 100644 --- a/chat2db-client/src/constants/common.ts +++ b/chat2db-client/src/constants/common.ts @@ -10,11 +10,12 @@ export enum DatabaseTypeCode { SQLITE = 'SQLITE', MARIADB = 'MARIADB', CLICKHOUSE = 'CLICKHOUSE', - DM = "DM", - OCEANBASE = "OCEANBASE", - PRESTO = "PRESTO", - HIVE = "HIVE", - KINGBASE = "KINGBASE", + DM = 'DM', + OCEANBASE = 'OCEANBASE', + PRESTO = 'PRESTO', + HIVE = 'HIVE', + KINGBASE = 'KINGBASE', + TIMEPLUS = 'TIMEPLUS', } export enum ConsoleStatus { @@ -30,7 +31,7 @@ export enum OSType { export enum ConnectionKind { Private = 'PRIVATE', - Shared = 'SHARED' + Shared = 'SHARED', } // 通用的增删改查枚举 diff --git a/chat2db-client/src/constants/database.ts b/chat2db-client/src/constants/database.ts index ba7c3c75c..e586cb883 100644 --- a/chat2db-client/src/constants/database.ts +++ b/chat2db-client/src/constants/database.ts @@ -3,7 +3,7 @@ import redisLogo from '@/assets/img/databaseImg/redis.png'; import h2Logo from '@/assets/img/databaseImg/h2.png'; import moreDBLogo from '@/assets/img/databaseImg/other.png'; import { IDatabase } from '@/typings'; -import { DatabaseTypeCode } from '@/constants' +import { DatabaseTypeCode } from '@/constants'; export enum ConnectionEnvType { DAILY = 'DAILY', @@ -94,7 +94,7 @@ export const databaseMap: { name: 'OceanBase', img: moreDBLogo, code: DatabaseTypeCode.OCEANBASE, - // port: 2883, + // port: 2883, icon: '\ue982', }, [DatabaseTypeCode.HIVE]: { @@ -118,6 +118,13 @@ export const databaseMap: { // port: 27017, icon: '\uec21', }, + [DatabaseTypeCode.TIMEPLUS]: { + name: 'Timeplus', + img: moreDBLogo, + code: DatabaseTypeCode.TIMEPLUS, + // port: 8123, + icon: '\ue8f4', + }, // [DatabaseTypeCode.REDIS]: { // name: 'Redis', // img: moreDBLogo, diff --git a/chat2db-client/src/utils/database.ts b/chat2db-client/src/utils/database.ts index b28d3bf28..06a3a835c 100644 --- a/chat2db-client/src/utils/database.ts +++ b/chat2db-client/src/utils/database.ts @@ -45,7 +45,6 @@ export function handleDatabaseAndSchema(databaseAndSchema: IWorkspaceModelType[' * @returns */ export function compatibleDataBaseName(databaseName: string, databaseType: DatabaseTypeCode) { - //"" oracele sqlite postgrsql h2 dm // ` MYSQL clickhouse MariaDB // [ sqlserver @@ -63,7 +62,11 @@ export function compatibleDataBaseName(databaseName: string, databaseType: Datab return `"${databaseName}"`; } else if ([DatabaseTypeCode.SQLSERVER].includes(databaseType)) { return `[${databaseName}]`; - } else if ([DatabaseTypeCode.MYSQL, DatabaseTypeCode.CLICKHOUSE, DatabaseTypeCode.MARIADB].includes(databaseType)) { + } else if ( + [DatabaseTypeCode.MYSQL, DatabaseTypeCode.CLICKHOUSE, DatabaseTypeCode.TIMEPLUS, DatabaseTypeCode.MARIADB].includes( + databaseType, + ) + ) { return `\`${databaseName}\``; } else { return `${databaseName}`; diff --git a/chat2db-server/chat2db-plugins/chat2db-timeplus/pom.xml b/chat2db-server/chat2db-plugins/chat2db-timeplus/pom.xml new file mode 100644 index 000000000..27b6834cf --- /dev/null +++ b/chat2db-server/chat2db-plugins/chat2db-timeplus/pom.xml @@ -0,0 +1,34 @@ + + + 4.0.0 + + ai.chat2db + chat2db-plugins + ${revision} + ../pom.xml + + + + + ai.chat2db + chat2db-spi + + + chat2db-timeplus + + + + src/main/java + + + **/*.json + + + + src/main/resources + + + + diff --git a/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/TimeplusDBManage.java b/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/TimeplusDBManage.java new file mode 100644 index 000000000..31df440b2 --- /dev/null +++ b/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/TimeplusDBManage.java @@ -0,0 +1,196 @@ +package ai.chat2db.plugin.timeplus; + +import ai.chat2db.spi.DBManage; +import ai.chat2db.spi.jdbc.DefaultDBManage; +import ai.chat2db.spi.model.AsyncContext; +import ai.chat2db.spi.sql.ConnectInfo; +import ai.chat2db.spi.sql.SQLExecutor; +import java.sql.*; +import java.util.Objects; +import org.apache.commons.lang3.StringUtils; + +public class TimeplusDBManage extends DefaultDBManage implements DBManage { + + @Override + public void exportDatabase( + Connection connection, + String databaseName, + String schemaName, + AsyncContext asyncContext + ) throws SQLException { + exportTablesOrViewsOrDictionaries( + connection, + databaseName, + schemaName, + asyncContext + ); + exportFunctions(connection, asyncContext); + } + + private void exportFunctions( + Connection connection, + AsyncContext asyncContext + ) throws SQLException { + String sql = + "SELECT name,create_query from system.functions where origin='SQLUserDefined'"; + try ( + ResultSet resultSet = connection.createStatement().executeQuery(sql) + ) { + while (resultSet.next()) { + StringBuilder sqlBuilder = new StringBuilder(); + sqlBuilder + .append("DROP FUNCTION IF EXISTS ") + .append(resultSet.getString("name")) + .append(";") + .append("\n") + .append(resultSet.getString("create_query")) + .append(";") + .append("\n"); + asyncContext.write(sqlBuilder.toString()); + } + } + } + + private void exportTablesOrViewsOrDictionaries( + Connection connection, + String databaseName, + String schemaName, + AsyncContext asyncContext + ) throws SQLException { + String sql = String.format( + "SELECT create_table_query, has_own_data,engine,name from system.`tables` WHERE `database`='%s'", + databaseName + ); + try ( + Statement statement = connection.createStatement(); + ResultSet resultSet = statement.executeQuery(sql) + ) { + while (resultSet.next()) { + String ddl = resultSet.getString("create_table_query"); + boolean dataFlag = resultSet.getInt("has_own_data") == 1; + String tableType = resultSet.getString("engine"); + String tableOrViewName = resultSet.getString("name"); + if (Objects.equals("View", tableType)) { + StringBuilder sqlBuilder = new StringBuilder(); + sqlBuilder + .append("DROP VIEW IF EXISTS ") + .append(databaseName) + .append(".") + .append(tableOrViewName) + .append(";") + .append("\n") + .append(ddl) + .append(";") + .append("\n"); + asyncContext.write(sqlBuilder.toString()); + } else if (Objects.equals("Dictionary", tableType)) { + StringBuilder sqlBuilder = new StringBuilder(); + sqlBuilder + .append("DROP DICTIONARY IF EXISTS ") + .append(databaseName) + .append(".") + .append(tableOrViewName) + .append(";") + .append("\n") + .append(ddl) + .append(";") + .append("\n"); + asyncContext.write(sqlBuilder.toString()); + } else { + StringBuilder sqlBuilder = new StringBuilder(); + sqlBuilder + .append("DROP STREAM IF EXISTS ") + .append(databaseName) + .append(".") + .append(tableOrViewName) + .append(";") + .append("\n") + .append(ddl) + .append(";") + .append("\n"); + asyncContext.write(sqlBuilder.toString()); + if (asyncContext.isContainsData() && dataFlag) { + exportTableData( + connection, + databaseName, + schemaName, + tableOrViewName, + asyncContext + ); + } + } + } + } + } + + @Override + public Connection getConnection(ConnectInfo connectInfo) { + String url = setDatabaseInJdbcUrl(connectInfo); + connectInfo.setUrl(url); + + return super.getConnection(connectInfo); + } + + private String setDatabaseInJdbcUrl(ConnectInfo connectInfo) { + String databaseName; + String url = connectInfo.getUrl(); + if ( + StringUtils.isBlank( + (databaseName = connectInfo.getDatabaseName()) + ) && + StringUtils.isBlank((databaseName = connectInfo.getSchemaName())) + ) { + return url; + } + + String connectAddress = + connectInfo.getHost() + ":" + connectInfo.getPort(); + String[] addressSplit = url.split(connectAddress); + String connectParams = addressSplit[1]; + if (connectParams.startsWith("/")) { + // Remove / from connection parameters + connectParams = connectParams.substring(1); + } + // Add database name + return ( + addressSplit[0] + + connectAddress + + "/" + + databaseName + + connectParams + ); + } + + @Override + public void dropTable( + Connection connection, + String databaseName, + String schemaName, + String tableName + ) { + String sql = "DROP STREAM IF EXISTS " + databaseName + "." + tableName; + SQLExecutor.getInstance().execute(connection, sql, resultSet -> null); + } + + @Override + public void copyTable( + Connection connection, + String databaseName, + String schemaName, + String tableName, + String newTableName, + boolean copyData + ) throws SQLException { + String sql = "CREATE STREAM " + newTableName + " AS " + tableName + ""; + SQLExecutor.getInstance().execute(connection, sql, resultSet -> null); + if (copyData) { + sql = "INSERT INTO " + + newTableName + + " SELECT * FROM table(" + + tableName + + ")"; + SQLExecutor.getInstance() + .execute(connection, sql, resultSet -> null); + } + } +} diff --git a/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/TimeplusMetaData.java b/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/TimeplusMetaData.java new file mode 100644 index 000000000..4bacb029e --- /dev/null +++ b/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/TimeplusMetaData.java @@ -0,0 +1,401 @@ +package ai.chat2db.plugin.timeplus; + +import static ai.chat2db.spi.util.SortUtils.sortDatabase; + +import ai.chat2db.plugin.timeplus.builder.TimeplusSqlBuilder; +import ai.chat2db.plugin.timeplus.type.TimeplusColumnTypeEnum; +import ai.chat2db.plugin.timeplus.type.TimeplusEngineTypeEnum; +import ai.chat2db.plugin.timeplus.type.TimeplusIndexTypeEnum; +import ai.chat2db.spi.MetaData; +import ai.chat2db.spi.SqlBuilder; +import ai.chat2db.spi.jdbc.DefaultMetaService; +import ai.chat2db.spi.model.*; +import ai.chat2db.spi.sql.SQLExecutor; +import jakarta.validation.constraints.NotEmpty; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.stream.Collectors; +import org.apache.commons.lang3.StringUtils; + +public class TimeplusMetaData extends DefaultMetaService implements MetaData { + + private static String ROUTINES_SQL = + "SELECT SPECIFIC_NAME, ROUTINE_COMMENT, ROUTINE_DEFINITION FROM information_schema.routines WHERE " + + "routine_type = '%s' AND ROUTINE_SCHEMA ='%s' AND " + + "routine_name = '%s';"; + private static String TRIGGER_SQL = + "SELECT TRIGGER_NAME,EVENT_MANIPULATION, ACTION_STATEMENT FROM INFORMATION_SCHEMA.TRIGGERS where " + + "TRIGGER_SCHEMA = '%s' AND TRIGGER_NAME = '%s';"; + private static String TRIGGER_SQL_LIST = + "SELECT TRIGGER_NAME FROM INFORMATION_SCHEMA.TRIGGERS where TRIGGER_SCHEMA = '%s';"; + private static String SELECT_TABLE_COLUMNS = + "select * from `system`.columns where table ='%s' and database='%s';"; + private static String VIEW_SQL = + "SELECT create_table_query from system.`tables` WHERE `database`='%s' and name='%s'"; + private List systemDatabases = Arrays.asList( + "information_schema", + "system" + ); + public static final String FUNCTION_SQL = + "SELECT name,create_query as ddl from system.functions where origin='SQLUserDefined'"; + + public static String format(String tableName) { + return "`" + tableName + "`"; + } + + @Override + public List functions( + Connection connection, + String databaseName, + String schemaName + ) { + return SQLExecutor.getInstance() + .execute(connection, FUNCTION_SQL, resultSet -> { + List functions = new ArrayList<>(); + while (resultSet.next()) { + Function function = new Function(); + function.setFunctionName(resultSet.getString("name")); + functions.add(function); + } + return functions; + }); + } + + @Override + public List databases(Connection connection) { + List list = SQLExecutor.getInstance() + .execute( + connection, + "SELECT name FROM system.databases;", + resultSet -> { + List databases = new ArrayList<>(); + try { + while (resultSet.next()) { + String dbName = resultSet.getString("name"); + Database database = new Database(); + database.setName(dbName); + databases.add(database); + } + } catch (SQLException e) { + throw new RuntimeException(e); + } + return databases; + } + ); + return sortDatabase(list, systemDatabases, connection); + } + + @Override + public String tableDDL( + Connection connection, + @NotEmpty String databaseName, + String schemaName, + @NotEmpty String tableName + ) { + String sql = + "SHOW CREATE STREAM " + + format(schemaName) + + "." + + format(tableName); + return SQLExecutor.getInstance() + .execute(connection, sql, resultSet -> { + if (resultSet.next()) { + return resultSet.getString("Create STREAM"); + } + return null; + }); + } + + @Override + public Function function( + Connection connection, + @NotEmpty String databaseName, + String schemaName, + String functionName + ) { + return SQLExecutor.getInstance() + .execute(connection, FUNCTION_SQL, resultSet -> { + Function function = new Function(); + function.setDatabaseName(databaseName); + function.setSchemaName(schemaName); + function.setFunctionName(functionName); + if (resultSet.next()) { + /* function.setSpecificName(resultSet.getString("SPECIFIC_NAME")); + function.setRemarks(resultSet.getString("ROUTINE_COMMENT"));*/ + function.setFunctionBody(resultSet.getString("ddl")); + } + return function; + }); + } + + @Override + public List triggers( + Connection connection, + String databaseName, + String schemaName + ) { + List triggers = new ArrayList<>(); + String sql = String.format(TRIGGER_SQL_LIST, schemaName); + return SQLExecutor.getInstance() + .execute(connection, sql, resultSet -> { + while (resultSet.next()) { + Trigger trigger = new Trigger(); + trigger.setTriggerName(resultSet.getString("TRIGGER_NAME")); + trigger.setSchemaName(schemaName); + trigger.setDatabaseName(databaseName); + triggers.add(trigger); + } + return triggers; + }); + } + + @Override + public Trigger trigger( + Connection connection, + @NotEmpty String databaseName, + String schemaName, + String triggerName + ) { + String sql = String.format(TRIGGER_SQL, databaseName, triggerName); + return SQLExecutor.getInstance() + .execute(connection, sql, resultSet -> { + Trigger trigger = new Trigger(); + trigger.setDatabaseName(databaseName); + trigger.setSchemaName(schemaName); + trigger.setTriggerName(triggerName); + if (resultSet.next()) { + trigger.setTriggerBody( + resultSet.getString("ACTION_STATEMENT") + ); + } + return trigger; + }); + } + + @Override + public Procedure procedure( + Connection connection, + @NotEmpty String databaseName, + String schemaName, + String procedureName + ) { + String sql = String.format( + ROUTINES_SQL, + "PROCEDURE", + schemaName, + procedureName + ); + return SQLExecutor.getInstance() + .execute(connection, sql, resultSet -> { + Procedure procedure = new Procedure(); + procedure.setDatabaseName(databaseName); + procedure.setSchemaName(schemaName); + procedure.setProcedureName(procedureName); + if (resultSet.next()) { + procedure.setSpecificName( + resultSet.getString("SPECIFIC_NAME") + ); + procedure.setRemarks( + resultSet.getString("ROUTINE_COMMENT") + ); + procedure.setProcedureBody( + resultSet.getString("ROUTINE_DEFINITION") + ); + } + return procedure; + }); + } + + @Override + public List columns( + Connection connection, + String databaseName, + String schemaName, + String tableName + ) { + String sql = String.format( + SELECT_TABLE_COLUMNS, + tableName, + databaseName + ); + List tableColumns = new ArrayList<>(); + + return SQLExecutor.getInstance() + .execute(connection, sql, resultSet -> { + while (resultSet.next()) { + TableColumn column = new TableColumn(); + column.setDatabaseName(databaseName); + column.setTableName(tableName); + column.setOldName(resultSet.getString("name")); + column.setName(resultSet.getString("name")); + String dataType = resultSet.getString("type"); + if (dataType.startsWith("nullable(")) { + dataType = dataType.substring(9, dataType.length() - 1); + column.setNullable(1); + } + column.setColumnType(dataType); + column.setDefaultValue( + resultSet.getString("default_expression") + ); + // column.setAutoIncrement(resultSet.getString("EXTRA").contains("auto_increment")); + column.setComment(resultSet.getString("comment")); + column.setOrdinalPosition(resultSet.getInt("position")); + column.setDecimalDigits(resultSet.getInt("numeric_scale")); + /*column.setCharSetName(resultSet.getString("CHARACTER_SET_NAME")); + column.setCollationName(resultSet.getString("COLLATION_NAME"));*/ + setColumnSize(column, dataType); + tableColumns.add(column); + } + return tableColumns; + }); + } + + private void setColumnSize(TableColumn column, String columnType) { + try { + if (columnType.contains("(")) { + String size = columnType.substring( + columnType.indexOf("(") + 1, + columnType.indexOf(")") + ); + if ( + "SET".equalsIgnoreCase(column.getColumnType()) || + "ENUM".equalsIgnoreCase(column.getColumnType()) + ) { + column.setValue(size); + } else { + if (size.contains(",")) { + String[] sizes = size.split(","); + if (StringUtils.isNotBlank(sizes[0])) { + column.setColumnSize(Integer.parseInt(sizes[0])); + } + if (StringUtils.isNotBlank(sizes[1])) { + column.setDecimalDigits(Integer.parseInt(sizes[1])); + } + } else { + column.setColumnSize(Integer.parseInt(size)); + } + } + } + } catch (Exception e) {} + } + + @Override + public Table view( + Connection connection, + String databaseName, + String schemaName, + String viewName + ) { + String sql = String.format(VIEW_SQL, databaseName, viewName); + return SQLExecutor.getInstance() + .execute(connection, sql, resultSet -> { + Table table = new Table(); + table.setDatabaseName(databaseName); + table.setSchemaName(schemaName); + table.setName(viewName); + if (resultSet.next()) { + table.setDdl(resultSet.getString("create_table_query")); + } + return table; + }); + } + + @Override + public List indexes( + Connection connection, + String databaseName, + String schemaName, + String tableName + ) { + StringBuilder queryBuf = new StringBuilder("SHOW INDEX FROM "); + queryBuf.append("`").append(schemaName).append("`"); + queryBuf.append(" FROM "); + queryBuf.append("`").append(databaseName).append("`"); + return SQLExecutor.getInstance() + .execute(connection, queryBuf.toString(), resultSet -> { + LinkedHashMap map = new LinkedHashMap(); + while (resultSet.next()) { + String keyName = resultSet.getString("Key_name"); + + TableIndex index = new TableIndex(); + index.setDatabaseName(databaseName); + index.setSchemaName(schemaName); + index.setTableName(tableName); + index.setName(keyName); + index.setUnique(!resultSet.getBoolean("Non_unique")); + index.setType(resultSet.getString("Index_type")); + // index.setComment(resultSet.getString("Index_comment")); + List tableIndexColumns = + new ArrayList<>(); + tableIndexColumns.addAll(getTableIndexColumn(resultSet)); + index.setColumnList(tableIndexColumns); + if ("PRIMARY".equalsIgnoreCase(keyName)) { + index.setType(TimeplusIndexTypeEnum.PRIMARY.getName()); + } + map.put(keyName, index); + } + return map.values().stream().collect(Collectors.toList()); + }); + } + + private List getTableIndexColumn(ResultSet resultSet) + throws SQLException { + List tableIndexColumns = new ArrayList<>(); + String name = StringUtils.isBlank(resultSet.getString("column_name")) + ? resultSet.getString("expression") + : resultSet.getString("column_name"); + if (StringUtils.isNotBlank(name)) { + String[] split = name.split(","); + for (String columName : split) { + TableIndexColumn tableIndexColumn = new TableIndexColumn(); + tableIndexColumn.setColumnName(columName); + tableIndexColumn.setOrdinalPosition( + resultSet.getShort("seq_in_index") + ); + tableIndexColumn.setCollation(resultSet.getString("collation")); + tableIndexColumn.setCardinality( + resultSet.getLong("cardinality") + ); + tableIndexColumn.setSubPart(resultSet.getLong("sub_part")); + tableIndexColumns.add(tableIndexColumn); + } + } + return tableIndexColumns; + } + + @Override + public SqlBuilder getSqlBuilder() { + return new TimeplusSqlBuilder(); + } + + @Override + public TableMeta getTableMeta( + String databaseName, + String schemaName, + String tableName + ) { + return TableMeta.builder() + .columnTypes(TimeplusColumnTypeEnum.getTypes()) + .engineTypes(TimeplusEngineTypeEnum.getTypes()) + .indexTypes(TimeplusIndexTypeEnum.getIndexTypes()) + .build(); + } + + @Override + public String getMetaDataName(String... names) { + return Arrays.stream(names) + .filter(name -> StringUtils.isNotBlank(name)) + .map(name -> "`" + name + "`") + .collect(Collectors.joining(".")); + } + + @Override + public List getSystemDatabases() { + return systemDatabases; + } +} diff --git a/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/TimeplusPlugin.java b/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/TimeplusPlugin.java new file mode 100644 index 000000000..3d519b73d --- /dev/null +++ b/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/TimeplusPlugin.java @@ -0,0 +1,29 @@ +package ai.chat2db.plugin.timeplus; + +import ai.chat2db.spi.DBManage; +import ai.chat2db.spi.MetaData; +import ai.chat2db.spi.Plugin; +import ai.chat2db.spi.config.DBConfig; +import ai.chat2db.spi.util.FileUtils; + +public class TimeplusPlugin implements Plugin { + + @Override + public DBConfig getDBConfig() { + return FileUtils.readJsonValue( + this.getClass(), + "timeplus.json", + DBConfig.class + ); + } + + @Override + public MetaData getMetaData() { + return new TimeplusMetaData(); + } + + @Override + public DBManage getDBManage() { + return new TimeplusDBManage(); + } +} diff --git a/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/builder/TimeplusSqlBuilder.java b/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/builder/TimeplusSqlBuilder.java new file mode 100644 index 000000000..33f35da67 --- /dev/null +++ b/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/builder/TimeplusSqlBuilder.java @@ -0,0 +1,215 @@ +package ai.chat2db.plugin.timeplus.builder; + +import ai.chat2db.plugin.timeplus.type.TimeplusColumnTypeEnum; +import ai.chat2db.plugin.timeplus.type.TimeplusIndexTypeEnum; +import ai.chat2db.spi.SqlBuilder; +import ai.chat2db.spi.jdbc.DefaultSqlBuilder; +import ai.chat2db.spi.model.Database; +import ai.chat2db.spi.model.Table; +import ai.chat2db.spi.model.TableColumn; +import ai.chat2db.spi.model.TableIndex; +import org.apache.commons.lang3.StringUtils; + +public class TimeplusSqlBuilder extends DefaultSqlBuilder { + + @Override + public String buildCreateTableSql(Table table) { + StringBuilder script = new StringBuilder(); + script.append("CREATE STREAM "); + if (StringUtils.isNotBlank(table.getDatabaseName())) { + script + .append("`") + .append(table.getDatabaseName()) + .append("`") + .append("."); + } + script + .append("`") + .append(table.getName()) + .append("`") + .append(" (") + .append("\n"); + + // append column + for (TableColumn column : table.getColumnList()) { + if ( + StringUtils.isBlank(column.getName()) || + StringUtils.isBlank(column.getColumnType()) + ) { + continue; + } + TimeplusColumnTypeEnum typeEnum = TimeplusColumnTypeEnum.getByType( + column.getColumnType() + ); + if (typeEnum != null) { + continue; + } + script + .append("\t") + .append(typeEnum.buildCreateColumnSql(column)) + .append(",\n"); + } + + // append index + for (TableIndex tableIndex : table.getIndexList()) { + if ( + StringUtils.isBlank(tableIndex.getName()) || + StringUtils.isBlank(tableIndex.getType()) + ) { + continue; + } + TimeplusIndexTypeEnum mysqlIndexTypeEnum = + TimeplusIndexTypeEnum.getByType(tableIndex.getType()); + if (!TimeplusIndexTypeEnum.PRIMARY.equals(mysqlIndexTypeEnum)) { + script + .append("\t") + .append("") + .append(mysqlIndexTypeEnum.buildIndexScript(tableIndex)) + .append(",\n"); + } + } + + script = new StringBuilder(script.substring(0, script.length() - 2)); + script.append("\n)"); + + if (StringUtils.isNotBlank(table.getEngine())) { + script.append(" ENGINE=").append(table.getEngine()).append("\n"); + } + // append primary key + for (TableIndex tableIndex : table.getIndexList()) { + if ( + StringUtils.isBlank(tableIndex.getName()) || + StringUtils.isBlank(tableIndex.getType()) + ) { + continue; + } + TimeplusIndexTypeEnum mysqlIndexTypeEnum = + TimeplusIndexTypeEnum.getByType(tableIndex.getType()); + if (TimeplusIndexTypeEnum.PRIMARY.equals(mysqlIndexTypeEnum)) { + script + .append("\t") + .append("") + .append(mysqlIndexTypeEnum.buildIndexScript(tableIndex)) + .append("\n"); + } + } + + if (StringUtils.isNotBlank(table.getComment())) { + script.append(" COMMENT '").append(table.getComment()).append("'"); + } + + script.append(";"); + + return script.toString(); + } + + @Override + public String buildModifyTaleSql(Table oldTable, Table newTable) { + StringBuilder script = new StringBuilder(); + script.append("ALTER STREAM "); + if (StringUtils.isNotBlank(oldTable.getDatabaseName())) { + script + .append("`") + .append(oldTable.getDatabaseName()) + .append("`") + .append("."); + } + script.append("`").append(oldTable.getName()).append("`").append("\n"); + + if ( + !StringUtils.equalsIgnoreCase( + oldTable.getComment(), + newTable.getComment() + ) + ) { + script + .append("\t") + .append("MODIFY COMMENT") + .append("'") + .append(newTable.getComment()) + .append("'") + .append(",\n"); + } + + // append modify column + for (TableColumn tableColumn : newTable.getColumnList()) { + if ( + StringUtils.isNotBlank(tableColumn.getEditStatus()) && + StringUtils.isNotBlank(tableColumn.getColumnType()) && + StringUtils.isNotBlank(tableColumn.getName()) + ) { + TimeplusColumnTypeEnum typeEnum = + TimeplusColumnTypeEnum.getByType( + tableColumn.getColumnType() + ); + if (typeEnum == null) { + continue; + } + script + .append("\t") + .append(typeEnum.buildModifyColumn(tableColumn)) + .append(",\n"); + } + } + + // append modify index + for (TableIndex tableIndex : newTable.getIndexList()) { + if ( + StringUtils.isNotBlank(tableIndex.getEditStatus()) && + StringUtils.isNotBlank(tableIndex.getType()) + ) { + TimeplusIndexTypeEnum clickHouseIndexTypeEnum = + TimeplusIndexTypeEnum.getByType(tableIndex.getType()); + if (clickHouseIndexTypeEnum == null) { + continue; + } + script + .append("\t") + .append( + clickHouseIndexTypeEnum.buildModifyIndex(tableIndex) + ) + .append(",\n"); + } + } + + if (script.length() > 2) { + script = new StringBuilder( + script.substring(0, script.length() - 2) + ); + script.append(";"); + } + + return script.toString(); + } + + @Override + public String pageLimit(String sql, int offset, int pageNo, int pageSize) { + StringBuilder sqlBuilder = new StringBuilder(sql.length() + 14); + sqlBuilder.append(sql); + if (offset == 0) { + sqlBuilder.append("\n LIMIT "); + sqlBuilder.append(pageSize); + } else { + sqlBuilder.append("\n LIMIT "); + sqlBuilder.append(offset); + sqlBuilder.append(","); + sqlBuilder.append(pageSize); + } + return sqlBuilder.toString(); + } + + @Override + public String buildCreateDatabaseSql(Database database) { + StringBuilder sqlBuilder = new StringBuilder(); + sqlBuilder.append("CREATE DATABASE `" + database.getName() + "`"); + if (StringUtils.isNotBlank(database.getComment())) { + sqlBuilder + .append(";ALTER DATABASE ") + .append(database.getName()) + .append(" COMMENT '") + .append(database.getComment()) + .append("';"); + } + return sqlBuilder.toString(); + } +} diff --git a/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/timeplus.json b/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/timeplus.json new file mode 100644 index 000000000..89f703739 --- /dev/null +++ b/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/timeplus.json @@ -0,0 +1,18 @@ +{ + "dbType": "TIMEPLUS", + "supportDatabase": false, + "supportSchema": true, + "driverConfigList": [ + { + "url": "jdbc:timeplus://localhost:8463", + "defaultDriver": true, + "custom": false, + "downloadJdbcDriverUrls": [ + "https://timeplus.io/downloads/timeplus-native-jdbc-shaded-2.0.5.jar" + ], + "jdbcDriver": "timeplus-native-jdbc-shaded-2.0.5.jar", + "jdbcDriverClass": "com.timeplus.jdbc.TimeplusDriver" + } + ], + "name": "Timeplus" +} diff --git a/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/type/TimeplusColumnTypeEnum.java b/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/type/TimeplusColumnTypeEnum.java new file mode 100644 index 000000000..0a9c6fafb --- /dev/null +++ b/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/type/TimeplusColumnTypeEnum.java @@ -0,0 +1,752 @@ +package ai.chat2db.plugin.timeplus.type; + +import ai.chat2db.spi.ColumnBuilder; +import ai.chat2db.spi.enums.EditStatus; +import ai.chat2db.spi.model.ColumnType; +import ai.chat2db.spi.model.TableColumn; +import ai.chat2db.spi.util.SqlUtils; +import com.google.common.collect.Maps; +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import org.apache.commons.lang3.StringUtils; + +public enum TimeplusColumnTypeEnum implements ColumnBuilder { + String( + "string", + false, + false, + true, + false, + false, + false, + true, + true, + false, + false + ), + Int8( + "int8", + false, + false, + true, + false, + false, + false, + true, + true, + false, + false + ), + Int16( + "int16", + false, + false, + true, + false, + false, + false, + true, + true, + false, + false + ), + Int32( + "int32", + false, + false, + true, + false, + false, + false, + true, + true, + false, + false + ), + Int64( + "int64", + false, + false, + true, + false, + false, + false, + true, + true, + false, + false + ), + Int128( + "int128", + false, + false, + true, + false, + false, + false, + true, + true, + false, + false + ), + Int256( + "int256", + false, + false, + true, + false, + false, + false, + true, + true, + false, + false + ), + UInt8( + "uint8", + false, + false, + true, + false, + false, + false, + true, + true, + false, + false + ), + UInt16( + "uint16", + false, + false, + true, + false, + false, + false, + true, + true, + false, + false + ), + UInt32( + "uint32", + false, + false, + true, + false, + false, + false, + true, + true, + false, + false + ), + UInt64( + "uint64", + false, + false, + true, + false, + false, + false, + true, + true, + false, + false + ), + UInt128( + "uint128", + false, + false, + true, + false, + false, + false, + true, + true, + false, + false + ), + UInt256( + "uint256", + false, + false, + true, + false, + false, + false, + true, + true, + false, + false + ), + Float32( + "float32", + false, + false, + true, + false, + false, + false, + true, + true, + false, + false + ), + Float64( + "float64", + false, + false, + true, + false, + false, + false, + true, + true, + false, + false + ), + Decimal( + "decimal", + true, + true, + true, + false, + false, + false, + true, + true, + false, + false + ), + Boolean( + "bool", + false, + false, + true, + false, + false, + false, + true, + true, + false, + false + ), + FixedString( + "fixed_string", + false, + false, + true, + false, + false, + false, + true, + true, + false, + false + ), + UUID( + "uuid", + false, + false, + true, + false, + false, + false, + true, + true, + false, + false + ), + Date( + "date", + false, + false, + true, + false, + false, + false, + true, + true, + false, + false + ), + DATE32( + "date32", + false, + false, + true, + false, + false, + false, + true, + true, + false, + false + ), + DateTime( + "datetime", + false, + false, + true, + false, + false, + false, + true, + true, + false, + false + ), + DateTime64( + "datetime64", + false, + false, + true, + false, + false, + false, + true, + true, + false, + false + ), + Enum8( + "enum8", + false, + false, + true, + false, + false, + false, + true, + true, + false, + false + ), + Enum16( + "enum16", + false, + false, + true, + false, + false, + false, + true, + true, + false, + false + ), + Array( + "array", + false, + false, + false, + false, + false, + false, + true, + true, + false, + false + ), + JSON( + "json", + false, + false, + true, + false, + false, + false, + true, + true, + false, + false + ), + Nested( + "nested", + false, + false, + true, + false, + false, + false, + true, + true, + false, + false + ), + Map("map", true, true, true, false, false, false, true, true, false, false), + IPv4( + "ipv4", + false, + false, + true, + false, + false, + false, + true, + true, + false, + false + ), + IPv6( + "ipv6", + false, + false, + true, + false, + false, + false, + true, + true, + false, + false + ), + Point( + "point", + false, + false, + true, + false, + false, + false, + true, + true, + false, + false + ), + Ring( + "ring", + false, + false, + true, + false, + false, + false, + true, + true, + false, + false + ), + Polygon( + "polygon", + false, + false, + true, + false, + false, + false, + true, + true, + false, + false + ), + MultiPolygon( + "multi_polygon", + false, + false, + true, + false, + false, + false, + true, + true, + false, + false + ), + AggregateFunction( + "aggregate_function", + true, + true, + true, + false, + false, + false, + true, + true, + false, + false + ), + SimpleAggregateFunction( + "simple_aggregate_function", + true, + true, + true, + false, + false, + false, + true, + true, + false, + false + ); + + private static Map COLUMN_TYPE_MAP = + Maps.newHashMap(); + + static { + for (TimeplusColumnTypeEnum value : TimeplusColumnTypeEnum.values()) { + COLUMN_TYPE_MAP.put(value.getColumnType().getTypeName(), value); + } + } + + private ColumnType columnType; + + TimeplusColumnTypeEnum( + String dataTypeName, + boolean supportLength, + boolean supportScale, + boolean supportNullable, + boolean supportAutoIncrement, + boolean supportCharset, + boolean supportCollation, + boolean supportComments, + boolean supportDefaultValue, + boolean supportExtent, + boolean supportValue + ) { + this.columnType = new ColumnType( + dataTypeName, + supportLength, + supportScale, + supportNullable, + supportAutoIncrement, + supportCharset, + supportCollation, + supportComments, + supportDefaultValue, + supportExtent, + supportValue, + false + ); + } + + public static TimeplusColumnTypeEnum getByType(String dataType) { + return COLUMN_TYPE_MAP.get( + SqlUtils.removeDigits(dataType.toUpperCase()) + ); + } + + public static List getTypes() { + return Arrays.stream(TimeplusColumnTypeEnum.values()) + .map(columnTypeEnum -> columnTypeEnum.getColumnType()) + .toList(); + } + + public ColumnType getColumnType() { + return columnType; + } + + @Override + public String buildCreateColumnSql(TableColumn column) { + TimeplusColumnTypeEnum type = COLUMN_TYPE_MAP.get( + column.getColumnType() + ); + if (type == null) { + return ""; + } + StringBuilder script = new StringBuilder(); + + script.append("`").append(column.getName()).append("`").append(" "); + + script.append(buildNullableAndDataType(column, type)).append(" "); + + script.append(buildDefaultValue(column, type)).append(" "); + + script.append(buildComment(column, type)).append(" "); + + return script.toString(); + } + + @Override + public String buildModifyColumn(TableColumn tableColumn) { + if (EditStatus.DELETE.name().equals(tableColumn.getEditStatus())) { + return StringUtils.join( + "DROP COLUMN `", + tableColumn.getName() + "`" + ); + } + if (EditStatus.ADD.name().equals(tableColumn.getEditStatus())) { + return StringUtils.join( + "ADD COLUMN ", + buildCreateColumnSql(tableColumn) + ); + } + if (EditStatus.MODIFY.name().equals(tableColumn.getEditStatus())) { + String modifyColumn = ""; + if ( + !StringUtils.equalsIgnoreCase( + tableColumn.getOldName(), + tableColumn.getName() + ) + ) { + modifyColumn = StringUtils.join( + "RENAME COLUMN `", + tableColumn.getOldName(), + "` TO `", + tableColumn.getName(), + "`, ", + buildCreateColumnSql(tableColumn) + ); + } + return StringUtils.join( + modifyColumn, + "MODIFY COLUMN ", + buildCreateColumnSql(tableColumn) + ); + } + return ""; + } + + private String buildComment( + TableColumn column, + TimeplusColumnTypeEnum type + ) { + if ( + !type.columnType.isSupportComments() || + StringUtils.isEmpty(column.getComment()) + ) { + return ""; + } + return StringUtils.join("COMMENT '", column.getComment(), "'"); + } + + private String buildDefaultValue( + TableColumn column, + TimeplusColumnTypeEnum type + ) { + if ( + !type.getColumnType().isSupportDefaultValue() || + StringUtils.isEmpty(column.getDefaultValue()) + ) { + return ""; + } + + if ("EMPTY_STRING".equalsIgnoreCase(column.getDefaultValue().trim())) { + return StringUtils.join("DEFAULT ''"); + } + + if ("NULL".equalsIgnoreCase(column.getDefaultValue().trim())) { + return StringUtils.join("DEFAULT NULL"); + } + + if (Arrays.asList(Enum8, Enum16).contains(type)) { + return StringUtils.join("DEFAULT '", column.getDefaultValue(), "'"); + } + + if (Arrays.asList(Date).contains(type)) { + return StringUtils.join("DEFAULT '", column.getDefaultValue(), "'"); + } + + if (Arrays.asList(DateTime).contains(type)) { + if ( + "CURRENT_TIMESTAMP".equalsIgnoreCase( + column.getDefaultValue().trim() + ) + ) { + return StringUtils.join("DEFAULT ", column.getDefaultValue()); + } + return StringUtils.join("DEFAULT '", column.getDefaultValue(), "'"); + } + + return StringUtils.join("DEFAULT ", column.getDefaultValue()); + } + + private String buildNullableAndDataType( + TableColumn column, + TimeplusColumnTypeEnum type + ) { + StringBuilder script = new StringBuilder(); + script.append(buildDataType(column, type)); + + if (!type.getColumnType().isSupportNullable()) { + return script.toString(); + } + if (column.getNullable() != null && 1 == column.getNullable()) { + return "Nullable(" + script.append(")").toString(); + } else { + return script.toString(); + } + } + + private String buildDataType( + TableColumn column, + TimeplusColumnTypeEnum type + ) { + String columnType = type.columnType.getTypeName(); + if (Arrays.asList(FixedString).contains(type)) { + return StringUtils.join( + columnType, + "(", + column.getColumnSize(), + ")" + ); + } + + if (Arrays.asList(Decimal).contains(type)) { + if ( + column.getColumnSize() == null || + column.getDecimalDigits() == null + ) { + return columnType; + } + if ( + column.getColumnSize() != null && + column.getDecimalDigits() == null + ) { + return StringUtils.join( + columnType, + "(", + column.getColumnSize() + ")" + ); + } + if ( + column.getColumnSize() != null && + column.getDecimalDigits() != null + ) { + return StringUtils.join( + columnType, + "(", + column.getColumnSize() + + "," + + column.getDecimalDigits() + + ")" + ); + } + } + + return columnType; + } + + public String buildColumn(TableColumn column) { + TimeplusColumnTypeEnum type = COLUMN_TYPE_MAP.get( + column.getColumnType() + ); + if (type == null) { + return ""; + } + StringBuilder script = new StringBuilder(); + + script.append("`").append(column.getName()).append("`").append(" "); + script.append(buildDataType(column, type)).append(" "); + if (StringUtils.isNoneBlank(column.getComment())) { + script + .append("COMMENT") + .append(" ") + .append("'") + .append(column.getComment()) + .append("'") + .append(" "); + } + return script.toString(); + } + + private String unsignedDataType(String dataTypeName, String middle) { + String[] split = dataTypeName.split(" "); + if (split.length == 2) { + return StringUtils.join(split[0], middle, split[1]); + } + return StringUtils.join(dataTypeName, middle); + } +} diff --git a/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/type/TimeplusEngineTypeEnum.java b/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/type/TimeplusEngineTypeEnum.java new file mode 100644 index 000000000..b58b41657 --- /dev/null +++ b/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/type/TimeplusEngineTypeEnum.java @@ -0,0 +1,419 @@ +package ai.chat2db.plugin.timeplus.type; + +import ai.chat2db.spi.model.EngineType; +import com.google.common.collect.Maps; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +public enum TimeplusEngineTypeEnum { + AzureBlobStorage( + "AzureBlobStorage", + false, + true, + false, + false, + true, + false, + false, + false + ), + KeeperMap( + "KeeperMap", + false, + true, + false, + false, + false, + true, + false, + false + ), + SQLite("SQLite", false, false, false, false, false, false, false, false), + ExternalDistributed( + "ExternalDistributed", + false, + false, + false, + false, + false, + false, + false, + false + ), + PostgreSQL( + "PostgreSQL", + false, + false, + false, + false, + false, + false, + false, + false + ), + NATS("NATS", false, false, false, false, true, false, false, false), + RabbitMQ("RabbitMQ", false, false, false, false, true, false, false, false), + Kafka("Kafka", false, false, false, false, true, false, false, false), + MongoDB("MongoDB", false, false, false, false, false, false, false, false), + FileLog("FileLog", false, false, false, false, true, false, false, false), + Dictionary( + "Dictionary", + false, + false, + false, + false, + false, + false, + false, + false + ), + MySQL("MySQL", false, false, false, false, true, false, false, false), + S3Queue("S3Queue", false, false, false, false, true, false, false, false), + HDFS("HDFS", false, true, false, false, false, false, false, false), + MaterializedPostgreSQL( + "MaterializedPostgreSQL", + false, + true, + false, + false, + true, + false, + false, + false + ), + S3("S3", false, true, false, false, true, false, false, false), + FuzzJSON( + "FuzzJSON", + false, + false, + false, + false, + false, + false, + false, + false + ), + OSS("OSS", false, true, false, false, true, false, false, false), + WindowView( + "WindowView", + false, + false, + false, + false, + false, + false, + false, + false + ), + Distributed( + "Distributed", + false, + false, + false, + false, + true, + true, + false, + false + ), + ReplicatedSummingMergeTree( + "ReplicatedSummingMergeTree", + true, + true, + true, + true, + true, + true, + true, + true + ), + ExecutablePool( + "ExecutablePool", + false, + false, + false, + false, + true, + false, + false, + false + ), + COSN("COSN", false, true, false, false, true, false, false, false), + Iceberg("Iceberg", false, false, false, false, false, false, false, false), + MaterializedView( + "MaterializedView", + false, + false, + false, + false, + false, + false, + false, + false + ), + View("View", false, false, false, false, false, false, false, false), + JDBC("JDBC", false, false, false, false, false, false, false, false), + Join("Join", false, false, false, false, true, false, false, false), + Executable( + "Executable", + false, + false, + false, + false, + true, + false, + false, + false + ), + Set("Set", false, false, false, false, true, false, false, false), + Redis("Redis", false, true, false, false, false, true, false, false), + GenerateRandom( + "GenerateRandom", + false, + false, + false, + false, + false, + false, + false, + false + ), + LiveView( + "LiveView", + false, + false, + false, + false, + false, + false, + false, + false + ), + MergeTree("MergeTree", true, true, true, false, true, true, true, false), + ReplicatedReplacingMergeTree( + "ReplicatedReplacingMergeTree", + true, + true, + true, + true, + true, + true, + true, + true + ), + Memory("Memory", false, false, false, false, true, true, false, false), + Buffer("Buffer", false, false, false, false, false, true, false, false), + URL("URL", false, false, false, false, true, false, false, false), + ReplicatedVersionedCollapsingMergeTree( + "ReplicatedVersionedCollapsingMergeTree", + true, + true, + true, + true, + true, + true, + true, + true + ), + VersionedCollapsingMergeTree( + "VersionedCollapsingMergeTree", + true, + true, + true, + false, + true, + true, + true, + false + ), + Hive("Hive", false, true, false, false, true, false, false, false), + ReplacingMergeTree( + "ReplacingMergeTree", + true, + true, + true, + false, + true, + true, + true, + false + ), + ReplicatedAggregatingMergeTree( + "ReplicatedAggregatingMergeTree", + true, + true, + true, + true, + true, + true, + true, + true + ), + ReplicatedMergeTree( + "ReplicatedMergeTree", + true, + true, + true, + true, + true, + true, + true, + true + ), + DeltaLake( + "DeltaLake", + false, + false, + false, + false, + false, + false, + false, + false + ), + EmbeddedRocksDB( + "EmbeddedRocksDB", + true, + true, + false, + false, + false, + true, + false, + false + ), + ReplicatedCollapsingMergeTree( + "ReplicatedCollapsingMergeTree", + true, + true, + true, + true, + true, + true, + true, + true + ), + File("File", false, false, false, false, true, false, false, false), + TinyLog("TinyLog", false, false, false, false, true, false, false, false), + ReplicatedGraphiteMergeTree( + "ReplicatedGraphiteMergeTree", + true, + true, + true, + true, + true, + true, + true, + true + ), + SummingMergeTree( + "SummingMergeTree", + true, + true, + true, + false, + true, + true, + true, + false + ), + Hudi("Hudi", false, false, false, false, false, false, false, false), + GraphiteMergeTree( + "GraphiteMergeTree", + true, + true, + true, + false, + true, + true, + true, + false + ), + CollapsingMergeTree( + "CollapsingMergeTree", + true, + true, + true, + false, + true, + true, + true, + false + ), + Merge("Merge", false, false, false, false, false, false, false, false), + AggregatingMergeTree( + "AggregatingMergeTree", + true, + true, + true, + false, + true, + true, + true, + false + ), + ODBC("ODBC", false, false, false, false, false, false, false, false), + Null("Null", false, false, false, false, false, true, false, false), + StripeLog( + "StripeLog", + false, + false, + false, + false, + true, + false, + false, + false + ), + Log("Log", false, false, false, false, true, false, false, false); + + private static Map ENGINE_TYPE_MAP = + Maps.newHashMap(); + + static { + for (TimeplusEngineTypeEnum value : TimeplusEngineTypeEnum.values()) { + ENGINE_TYPE_MAP.put(value.getEngineType().getName(), value); + } + } + + private EngineType engineType; + + TimeplusEngineTypeEnum( + String name, + boolean supportTTL, + boolean supportSortOrder, + boolean supportSkippingIndices, + boolean supportDeduplication, + boolean supportSettings, + boolean supportParallelInsert, + boolean supportProjections, + boolean supportReplication + ) { + this.engineType = new EngineType( + name, + supportTTL, + supportSortOrder, + supportSkippingIndices, + supportDeduplication, + supportSettings, + supportParallelInsert, + supportProjections, + supportReplication + ); + } + + public static TimeplusEngineTypeEnum getByType(String dataType) { + return ENGINE_TYPE_MAP.get(dataType.toUpperCase()); + } + + public static List getTypes() { + return Arrays.stream(TimeplusEngineTypeEnum.values()) + .map(engineTypeEnum -> engineTypeEnum.getEngineType()) + .toList(); + } + + public EngineType getEngineType() { + return engineType; + } +} diff --git a/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/type/TimeplusIndexTypeEnum.java b/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/type/TimeplusIndexTypeEnum.java new file mode 100644 index 000000000..299ba8db6 --- /dev/null +++ b/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/type/TimeplusIndexTypeEnum.java @@ -0,0 +1,129 @@ +package ai.chat2db.plugin.timeplus.type; + +import ai.chat2db.spi.enums.EditStatus; +import ai.chat2db.spi.model.IndexType; +import ai.chat2db.spi.model.TableIndex; +import ai.chat2db.spi.model.TableIndexColumn; +import java.util.Arrays; +import java.util.List; +import org.apache.commons.lang3.StringUtils; + +public enum TimeplusIndexTypeEnum { + PRIMARY("Primary", "PRIMARY KEY"), + MINMAX("MINMAX", "INDEX"), + SET("SET", "INDEX"), + BLOOM_FILTER("BLOOM_FILTER", "INDEX"), + TOKENBF_V1("TOKENBF_V1", "INDEX"), + NGRAMBF_V1("NGRAMBF_V1", "INDEX"), + INVERTED("INVERTED", "INDEX"), + HYPOTHESIS("HYPOTHESIS", "INDEX"), + ANNOY("ANNOY", "INDEX"), + USEARCH("USEARCH", "INDEX"); + + private String name; + private String keyword; + private IndexType indexType; + + TimeplusIndexTypeEnum(String name, String keyword) { + this.name = name; + this.keyword = keyword; + this.indexType = new IndexType(name); + } + + public static TimeplusIndexTypeEnum getByType(String type) { + for (TimeplusIndexTypeEnum value : TimeplusIndexTypeEnum.values()) { + if (value.name.equalsIgnoreCase(type)) { + return value; + } + } + return null; + } + + public static List getIndexTypes() { + return Arrays.asList(TimeplusIndexTypeEnum.values()) + .stream() + .map(TimeplusIndexTypeEnum::getIndexType) + .collect(java.util.stream.Collectors.toList()); + } + + public String getName() { + return name; + } + + public String getKeyword() { + return keyword; + } + + public IndexType getIndexType() { + return indexType; + } + + public void setIndexType(IndexType indexType) { + this.indexType = indexType; + } + + public String buildIndexScript(TableIndex tableIndex) { + StringBuilder script = new StringBuilder(); + + script.append(keyword).append(" "); + script.append(buildIndexName(tableIndex)).append(" "); + script.append(buildIndexColumn(tableIndex)).append(" "); + script.append(buildIndexType(tableIndex)).append(" "); + return script.toString(); + } + + private String buildIndexType(TableIndex tableIndex) { + if (this.equals(PRIMARY)) { + return ""; + } else { + return "TYPE " + name; + } + } + + private String buildIndexColumn(TableIndex tableIndex) { + StringBuilder script = new StringBuilder(); + script.append("("); + for (TableIndexColumn column : tableIndex.getColumnList()) { + if (StringUtils.isNotBlank(column.getColumnName())) { + script.append("`").append(column.getColumnName()).append("`"); + script.append(","); + } + } + script.deleteCharAt(script.length() - 1); + script.append(")"); + return script.toString(); + } + + private String buildIndexName(TableIndex tableIndex) { + if (this.equals(PRIMARY)) { + return ""; + } else { + return "`" + tableIndex.getName() + "`"; + } + } + + public String buildModifyIndex(TableIndex tableIndex) { + if (this.equals(PRIMARY)) { + return ""; + } + if (EditStatus.DELETE.name().equals(tableIndex.getEditStatus())) { + return StringUtils.join( + "DROP INDEX `", + tableIndex.getOldName(), + "`" + ); + } + if (EditStatus.MODIFY.name().equals(tableIndex.getEditStatus())) { + return StringUtils.join( + "DROP INDEX `", + tableIndex.getOldName(), + "`,\n ADD ", + buildIndexScript(tableIndex) + ); + } + if (EditStatus.ADD.name().equals(tableIndex.getEditStatus())) { + return StringUtils.join("ADD ", buildIndexScript(tableIndex)); + } + return ""; + } +} diff --git a/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/resources/META-INF/services/ai.chat2db.spi.Plugin b/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/resources/META-INF/services/ai.chat2db.spi.Plugin new file mode 100644 index 000000000..8e39eedfd --- /dev/null +++ b/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/resources/META-INF/services/ai.chat2db.spi.Plugin @@ -0,0 +1 @@ +ai.chat2db.plugin.timeplus.TimeplusPlugin diff --git a/chat2db-server/chat2db-plugins/pom.xml b/chat2db-server/chat2db-plugins/pom.xml index 17be8e0e8..a98b555cb 100644 --- a/chat2db-server/chat2db-plugins/pom.xml +++ b/chat2db-server/chat2db-plugins/pom.xml @@ -29,6 +29,7 @@ chat2db-presto chat2db-hive chat2db-kingbase + chat2db-timeplus - \ No newline at end of file + From 45e620bbe43c417a08b63291eb54c71ca2ec5dec Mon Sep 17 00:00:00 2001 From: Jove Zhong Date: Wed, 23 Oct 2024 07:47:37 -0700 Subject: [PATCH 30/40] add plugin to server-domain-core/pom.xml --- .../chat2db-server-domain/chat2db-server-domain-core/pom.xml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/chat2db-server/chat2db-server-domain/chat2db-server-domain-core/pom.xml b/chat2db-server/chat2db-server-domain/chat2db-server-domain-core/pom.xml index 4916c324b..39d5c2a2d 100644 --- a/chat2db-server/chat2db-server-domain/chat2db-server-domain-core/pom.xml +++ b/chat2db-server/chat2db-server-domain/chat2db-server-domain-core/pom.xml @@ -121,6 +121,11 @@ chat2db-sqlserver ${revision} + + ai.chat2db + chat2db-timeplus + ${revision} + commons-codec commons-codec From e3d99311385febd9b7dab756d0d47b454ab4235d Mon Sep 17 00:00:00 2001 From: Jove Zhong Date: Wed, 23 Oct 2024 23:20:36 -0700 Subject: [PATCH 31/40] update udf origin name --- .../main/java/ai/chat2db/plugin/timeplus/TimeplusDBManage.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/TimeplusDBManage.java b/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/TimeplusDBManage.java index 31df440b2..15dae5732 100644 --- a/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/TimeplusDBManage.java +++ b/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/TimeplusDBManage.java @@ -32,7 +32,7 @@ private void exportFunctions( AsyncContext asyncContext ) throws SQLException { String sql = - "SELECT name,create_query from system.functions where origin='SQLUserDefined'"; + "SELECT name,create_query from system.functions where origin='ExecutableUserDefined'"; try ( ResultSet resultSet = connection.createStatement().executeQuery(sql) ) { From a17f69cf25fcdb387af0d9bda9b0e417f3a878a0 Mon Sep 17 00:00:00 2001 From: Jove Zhong Date: Wed, 23 Oct 2024 23:21:05 -0700 Subject: [PATCH 32/40] empty list for routes and triggers --- .../plugin/timeplus/TimeplusMetaData.java | 34 ++++--------------- 1 file changed, 7 insertions(+), 27 deletions(-) diff --git a/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/TimeplusMetaData.java b/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/TimeplusMetaData.java index 4bacb029e..a56b3dbcb 100644 --- a/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/TimeplusMetaData.java +++ b/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/TimeplusMetaData.java @@ -24,15 +24,9 @@ public class TimeplusMetaData extends DefaultMetaService implements MetaData { - private static String ROUTINES_SQL = - "SELECT SPECIFIC_NAME, ROUTINE_COMMENT, ROUTINE_DEFINITION FROM information_schema.routines WHERE " + - "routine_type = '%s' AND ROUTINE_SCHEMA ='%s' AND " + - "routine_name = '%s';"; - private static String TRIGGER_SQL = - "SELECT TRIGGER_NAME,EVENT_MANIPULATION, ACTION_STATEMENT FROM INFORMATION_SCHEMA.TRIGGERS where " + - "TRIGGER_SCHEMA = '%s' AND TRIGGER_NAME = '%s';"; - private static String TRIGGER_SQL_LIST = - "SELECT TRIGGER_NAME FROM INFORMATION_SCHEMA.TRIGGERS where TRIGGER_SCHEMA = '%s';"; + private static String ROUTINES_SQL = ""; + private static String TRIGGER_SQL = ""; + private static String TRIGGER_SQL_LIST = ""; private static String SELECT_TABLE_COLUMNS = "select * from `system`.columns where table ='%s' and database='%s';"; private static String VIEW_SQL = @@ -42,7 +36,7 @@ public class TimeplusMetaData extends DefaultMetaService implements MetaData { "system" ); public static final String FUNCTION_SQL = - "SELECT name,create_query as ddl from system.functions where origin='SQLUserDefined'"; + "SELECT name,create_query as ddl from system.functions where origin='ExecutableUserDefined'"; public static String format(String tableName) { return "`" + tableName + "`"; @@ -98,14 +92,11 @@ public String tableDDL( @NotEmpty String tableName ) { String sql = - "SHOW CREATE STREAM " + - format(schemaName) + - "." + - format(tableName); + "SHOW CREATE " + format(schemaName) + "." + format(tableName); return SQLExecutor.getInstance() .execute(connection, sql, resultSet -> { if (resultSet.next()) { - return resultSet.getString("Create STREAM"); + return resultSet.getString("statement"); } return null; }); @@ -140,18 +131,7 @@ public List triggers( String schemaName ) { List triggers = new ArrayList<>(); - String sql = String.format(TRIGGER_SQL_LIST, schemaName); - return SQLExecutor.getInstance() - .execute(connection, sql, resultSet -> { - while (resultSet.next()) { - Trigger trigger = new Trigger(); - trigger.setTriggerName(resultSet.getString("TRIGGER_NAME")); - trigger.setSchemaName(schemaName); - trigger.setDatabaseName(databaseName); - triggers.add(trigger); - } - return triggers; - }); + return triggers; } @Override From cf6b7a0bc806f36753b9b7f784a6e9e607a6fd1c Mon Sep 17 00:00:00 2001 From: Jove Zhong Date: Thu, 24 Oct 2024 09:58:25 -0700 Subject: [PATCH 33/40] important fix: avoid duplicating the db name --- .../ai/chat2db/plugin/timeplus/TimeplusDBManage.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/TimeplusDBManage.java b/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/TimeplusDBManage.java index 15dae5732..c7653a24b 100644 --- a/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/TimeplusDBManage.java +++ b/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/TimeplusDBManage.java @@ -132,7 +132,7 @@ public Connection getConnection(ConnectInfo connectInfo) { } private String setDatabaseInJdbcUrl(ConnectInfo connectInfo) { - String databaseName; + String databaseName; //sometimes it's null, sometimes not. Need special handling String url = connectInfo.getUrl(); if ( StringUtils.isBlank( @@ -151,14 +151,17 @@ private String setDatabaseInJdbcUrl(ConnectInfo connectInfo) { // Remove / from connection parameters connectParams = connectParams.substring(1); } + if (connectParams.equals(databaseName)) { + return url; + } // Add database name - return ( + String rv = addressSplit[0] + connectAddress + "/" + databaseName + - connectParams - ); + connectParams; + return rv; } @Override From 1f9e86011b474cf69b24a5f63364f2cb41b5287c Mon Sep 17 00:00:00 2001 From: Jove Zhong Date: Thu, 24 Oct 2024 09:58:43 -0700 Subject: [PATCH 34/40] set supportDatabase to true and schema false --- .../src/main/java/ai/chat2db/plugin/timeplus/timeplus.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/timeplus.json b/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/timeplus.json index 89f703739..c51ea76a7 100644 --- a/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/timeplus.json +++ b/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/timeplus.json @@ -1,7 +1,7 @@ { "dbType": "TIMEPLUS", - "supportDatabase": false, - "supportSchema": true, + "supportDatabase": true, + "supportSchema": false, "driverConfigList": [ { "url": "jdbc:timeplus://localhost:8463", From fe01c131b09414272b71a19a98b8335c1fba5301 Mon Sep 17 00:00:00 2001 From: Jove Zhong Date: Thu, 24 Oct 2024 09:59:20 -0700 Subject: [PATCH 35/40] always use default as database name --- .../plugin/timeplus/TimeplusMetaData.java | 23 ++++++++++--------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/TimeplusMetaData.java b/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/TimeplusMetaData.java index a56b3dbcb..110421e78 100644 --- a/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/TimeplusMetaData.java +++ b/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/TimeplusMetaData.java @@ -198,18 +198,15 @@ public List columns( String schemaName, String tableName ) { - String sql = String.format( - SELECT_TABLE_COLUMNS, - tableName, - databaseName - ); + final String db = "default"; + String sql = String.format(SELECT_TABLE_COLUMNS, tableName, db); List tableColumns = new ArrayList<>(); return SQLExecutor.getInstance() .execute(connection, sql, resultSet -> { while (resultSet.next()) { TableColumn column = new TableColumn(); - column.setDatabaseName(databaseName); + column.setDatabaseName(db); column.setTableName(tableName); column.setOldName(resultSet.getString("name")); column.setName(resultSet.getString("name")); @@ -261,7 +258,9 @@ private void setColumnSize(TableColumn column, String columnType) { } } } - } catch (Exception e) {} + } catch (Exception e) { + e.printStackTrace(); + } } @Override @@ -271,11 +270,12 @@ public Table view( String schemaName, String viewName ) { - String sql = String.format(VIEW_SQL, databaseName, viewName); + final String db = "default"; + String sql = String.format(VIEW_SQL, db, viewName); return SQLExecutor.getInstance() .execute(connection, sql, resultSet -> { Table table = new Table(); - table.setDatabaseName(databaseName); + table.setDatabaseName(db); table.setSchemaName(schemaName); table.setName(viewName); if (resultSet.next()) { @@ -292,10 +292,11 @@ public List indexes( String schemaName, String tableName ) { + final String db = "default"; StringBuilder queryBuf = new StringBuilder("SHOW INDEX FROM "); queryBuf.append("`").append(schemaName).append("`"); queryBuf.append(" FROM "); - queryBuf.append("`").append(databaseName).append("`"); + queryBuf.append("`").append(db).append("`"); return SQLExecutor.getInstance() .execute(connection, queryBuf.toString(), resultSet -> { LinkedHashMap map = new LinkedHashMap(); @@ -303,7 +304,7 @@ public List indexes( String keyName = resultSet.getString("Key_name"); TableIndex index = new TableIndex(); - index.setDatabaseName(databaseName); + index.setDatabaseName(db); index.setSchemaName(schemaName); index.setTableName(tableName); index.setName(keyName); From 7b31f3d344568fa504bb93f3f9d12451189f2624 Mon Sep 17 00:00:00 2001 From: Jove Zhong Date: Thu, 24 Oct 2024 11:55:16 -0700 Subject: [PATCH 36/40] Update MetaData, timezone can be in the column type --- .../ai/chat2db/plugin/timeplus/TimeplusMetaData.java | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/TimeplusMetaData.java b/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/TimeplusMetaData.java index 110421e78..ab47986b0 100644 --- a/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/TimeplusMetaData.java +++ b/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/TimeplusMetaData.java @@ -238,7 +238,7 @@ private void setColumnSize(TableColumn column, String columnType) { String size = columnType.substring( columnType.indexOf("(") + 1, columnType.indexOf(")") - ); + ); //"size" can be a number or "3, 'UTC'" with timezone for datetime objects if ( "SET".equalsIgnoreCase(column.getColumnType()) || "ENUM".equalsIgnoreCase(column.getColumnType()) @@ -251,7 +251,12 @@ private void setColumnSize(TableColumn column, String columnType) { column.setColumnSize(Integer.parseInt(sizes[0])); } if (StringUtils.isNotBlank(sizes[1])) { - column.setDecimalDigits(Integer.parseInt(sizes[1])); + //can be " 'UTC'" + if (sizes[1].contains("'") == false) { + column.setDecimalDigits( + Integer.parseInt(sizes[1]) + ); + } } } else { column.setColumnSize(Integer.parseInt(size)); From 4490d2d9e315f471350975194bdfa6f11dd688b3 Mon Sep 17 00:00:00 2001 From: Jove Zhong Date: Thu, 24 Oct 2024 12:20:17 -0700 Subject: [PATCH 37/40] MetaData, return empty list for table index --- .../plugin/timeplus/TimeplusMetaData.java | 53 ++----------------- 1 file changed, 3 insertions(+), 50 deletions(-) diff --git a/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/TimeplusMetaData.java b/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/TimeplusMetaData.java index ab47986b0..e78c2e5f0 100644 --- a/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/TimeplusMetaData.java +++ b/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/TimeplusMetaData.java @@ -297,60 +297,13 @@ public List indexes( String schemaName, String tableName ) { - final String db = "default"; - StringBuilder queryBuf = new StringBuilder("SHOW INDEX FROM "); - queryBuf.append("`").append(schemaName).append("`"); - queryBuf.append(" FROM "); - queryBuf.append("`").append(db).append("`"); - return SQLExecutor.getInstance() - .execute(connection, queryBuf.toString(), resultSet -> { - LinkedHashMap map = new LinkedHashMap(); - while (resultSet.next()) { - String keyName = resultSet.getString("Key_name"); - - TableIndex index = new TableIndex(); - index.setDatabaseName(db); - index.setSchemaName(schemaName); - index.setTableName(tableName); - index.setName(keyName); - index.setUnique(!resultSet.getBoolean("Non_unique")); - index.setType(resultSet.getString("Index_type")); - // index.setComment(resultSet.getString("Index_comment")); - List tableIndexColumns = - new ArrayList<>(); - tableIndexColumns.addAll(getTableIndexColumn(resultSet)); - index.setColumnList(tableIndexColumns); - if ("PRIMARY".equalsIgnoreCase(keyName)) { - index.setType(TimeplusIndexTypeEnum.PRIMARY.getName()); - } - map.put(keyName, index); - } - return map.values().stream().collect(Collectors.toList()); - }); + List rv = new ArrayList<>(); + return rv; } private List getTableIndexColumn(ResultSet resultSet) throws SQLException { List tableIndexColumns = new ArrayList<>(); - String name = StringUtils.isBlank(resultSet.getString("column_name")) - ? resultSet.getString("expression") - : resultSet.getString("column_name"); - if (StringUtils.isNotBlank(name)) { - String[] split = name.split(","); - for (String columName : split) { - TableIndexColumn tableIndexColumn = new TableIndexColumn(); - tableIndexColumn.setColumnName(columName); - tableIndexColumn.setOrdinalPosition( - resultSet.getShort("seq_in_index") - ); - tableIndexColumn.setCollation(resultSet.getString("collation")); - tableIndexColumn.setCardinality( - resultSet.getLong("cardinality") - ); - tableIndexColumn.setSubPart(resultSet.getLong("sub_part")); - tableIndexColumns.add(tableIndexColumn); - } - } return tableIndexColumns; } @@ -368,7 +321,7 @@ public TableMeta getTableMeta( return TableMeta.builder() .columnTypes(TimeplusColumnTypeEnum.getTypes()) .engineTypes(TimeplusEngineTypeEnum.getTypes()) - .indexTypes(TimeplusIndexTypeEnum.getIndexTypes()) + //.indexTypes(TimeplusIndexTypeEnum.getIndexTypes()) .build(); } From 127638c144f85c3e0af55f4e8c4a25111f39dd17 Mon Sep 17 00:00:00 2001 From: Jove Zhong Date: Thu, 24 Oct 2024 19:18:45 -0700 Subject: [PATCH 38/40] workaround for default.default.name --- .../java/ai/chat2db/plugin/timeplus/TimeplusMetaData.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/TimeplusMetaData.java b/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/TimeplusMetaData.java index e78c2e5f0..4f28527d7 100644 --- a/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/TimeplusMetaData.java +++ b/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/TimeplusMetaData.java @@ -327,10 +327,13 @@ public TableMeta getTableMeta( @Override public String getMetaDataName(String... names) { - return Arrays.stream(names) + //avoid default.default.abc + String rv = Arrays.stream(names) .filter(name -> StringUtils.isNotBlank(name)) .map(name -> "`" + name + "`") .collect(Collectors.joining(".")); + rv = rv.replaceFirst("`default`.`default`", "`default`"); + return rv; } @Override From f56f5245f58b8e4aee5b88a80679a17900a0c188 Mon Sep 17 00:00:00 2001 From: Jove Zhong Date: Thu, 24 Oct 2024 19:27:01 -0700 Subject: [PATCH 39/40] use 7587 not 8463 by default to skip streaming --- .../src/components/ConnectionEdit/config/dataSource.ts | 5 ++--- .../src/main/java/ai/chat2db/plugin/timeplus/timeplus.json | 2 +- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/chat2db-client/src/components/ConnectionEdit/config/dataSource.ts b/chat2db-client/src/components/ConnectionEdit/config/dataSource.ts index 240f867b7..c95ca70ef 100644 --- a/chat2db-client/src/components/ConnectionEdit/config/dataSource.ts +++ b/chat2db-client/src/components/ConnectionEdit/config/dataSource.ts @@ -2026,7 +2026,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ }, }, { - defaultValue: '8463', + defaultValue: '7587', inputType: InputType.INPUT, labelNameCN: '端口', labelNameEN: 'Port', @@ -2090,7 +2090,7 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ required: false, }, { - defaultValue: 'jdbc:timeplus://localhost:8463', + defaultValue: 'jdbc:timeplus://localhost:7587', inputType: InputType.INPUT, labelNameCN: 'URL', labelNameEN: 'URL', @@ -2101,7 +2101,6 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ pattern: /jdbc:timeplus:\/\/(.*):(\d+)(\/(\w+))?/, template: 'jdbc:timeplus://{host}:{port}/{database}', excludes: [OperationColumn.ViewDDL, OperationColumn.CreateTable, OperationColumn.EditTable], - //排除掉导出ddl 和 创建表功能 支持的功能见 ./enum.ts => OperationColumn }, ssh: sshConfig, }, diff --git a/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/timeplus.json b/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/timeplus.json index c51ea76a7..aa2e14670 100644 --- a/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/timeplus.json +++ b/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/timeplus.json @@ -4,7 +4,7 @@ "supportSchema": false, "driverConfigList": [ { - "url": "jdbc:timeplus://localhost:8463", + "url": "jdbc:timeplus://localhost:7587", "defaultDriver": true, "custom": false, "downloadJdbcDriverUrls": [ From 738f1565bd803df0757a543ca76101740802e979 Mon Sep 17 00:00:00 2001 From: Jove Zhong Date: Thu, 24 Oct 2024 19:27:11 -0700 Subject: [PATCH 40/40] Update TimeplusEngineTypeEnum.java --- .../timeplus/type/TimeplusEngineTypeEnum.java | 234 ++---------------- 1 file changed, 14 insertions(+), 220 deletions(-) diff --git a/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/type/TimeplusEngineTypeEnum.java b/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/type/TimeplusEngineTypeEnum.java index b58b41657..5d3739b96 100644 --- a/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/type/TimeplusEngineTypeEnum.java +++ b/chat2db-server/chat2db-plugins/chat2db-timeplus/src/main/java/ai/chat2db/plugin/timeplus/type/TimeplusEngineTypeEnum.java @@ -7,118 +7,31 @@ import java.util.Map; public enum TimeplusEngineTypeEnum { - AzureBlobStorage( - "AzureBlobStorage", + Stream("Stream", true, true, true, false, true, true, true, true), + ExternalStream( + "ExternalStream", false, - true, - false, - false, - true, false, false, - false - ), - KeeperMap( - "KeeperMap", false, true, false, false, - false, - true, - false, false ), - SQLite("SQLite", false, false, false, false, false, false, false, false), - ExternalDistributed( - "ExternalDistributed", - false, - false, - false, - false, - false, - false, - false, - false - ), - PostgreSQL( - "PostgreSQL", - false, - false, - false, + ExternalTable( + "ExternalTable", false, false, false, false, - false - ), - NATS("NATS", false, false, false, false, true, false, false, false), - RabbitMQ("RabbitMQ", false, false, false, false, true, false, false, false), - Kafka("Kafka", false, false, false, false, true, false, false, false), - MongoDB("MongoDB", false, false, false, false, false, false, false, false), - FileLog("FileLog", false, false, false, false, true, false, false, false), - Dictionary( - "Dictionary", - false, - false, - false, - false, - false, - false, - false, - false - ), - MySQL("MySQL", false, false, false, false, true, false, false, false), - S3Queue("S3Queue", false, false, false, false, true, false, false, false), - HDFS("HDFS", false, true, false, false, false, false, false, false), - MaterializedPostgreSQL( - "MaterializedPostgreSQL", - false, - true, - false, - false, true, false, false, false ), - S3("S3", false, true, false, false, true, false, false, false), - FuzzJSON( - "FuzzJSON", - false, - false, - false, - false, - false, - false, - false, - false - ), - OSS("OSS", false, true, false, false, true, false, false, false), - WindowView( - "WindowView", - false, - false, - false, - false, - false, - false, - false, - false - ), - Distributed( - "Distributed", - false, - false, - false, - false, - true, - true, - false, - false - ), - ReplicatedSummingMergeTree( - "ReplicatedSummingMergeTree", + MutableStream( + "MutableStream", true, true, true, @@ -128,59 +41,21 @@ public enum TimeplusEngineTypeEnum { true, true ), - ExecutablePool( - "ExecutablePool", - false, - false, - false, - false, - true, - false, - false, - false - ), - COSN("COSN", false, true, false, false, true, false, false, false), - Iceberg("Iceberg", false, false, false, false, false, false, false, false), + View("View", false, false, false, false, false, false, false, false), MaterializedView( "MaterializedView", - false, - false, - false, - false, - false, - false, - false, - false - ), - View("View", false, false, false, false, false, false, false, false), - JDBC("JDBC", false, false, false, false, false, false, false, false), - Join("Join", false, false, false, false, true, false, false, false), - Executable( - "Executable", - false, - false, - false, - false, true, false, false, - false - ), - Set("Set", false, false, false, false, true, false, false, false), - Redis("Redis", false, true, false, false, false, true, false, false), - GenerateRandom( - "GenerateRandom", - false, - false, - false, - false, false, + true, false, false, false ), - LiveView( - "LiveView", + Random("Random", false, false, false, false, true, false, false, false), + Dictionary( + "Dictionary", false, false, false, @@ -190,6 +65,7 @@ public enum TimeplusEngineTypeEnum { false, false ), + S3("S3", false, true, false, false, true, false, false, false), MergeTree("MergeTree", true, true, true, false, true, true, true, false), ReplicatedReplacingMergeTree( "ReplicatedReplacingMergeTree", @@ -203,31 +79,6 @@ public enum TimeplusEngineTypeEnum { true ), Memory("Memory", false, false, false, false, true, true, false, false), - Buffer("Buffer", false, false, false, false, false, true, false, false), - URL("URL", false, false, false, false, true, false, false, false), - ReplicatedVersionedCollapsingMergeTree( - "ReplicatedVersionedCollapsingMergeTree", - true, - true, - true, - true, - true, - true, - true, - true - ), - VersionedCollapsingMergeTree( - "VersionedCollapsingMergeTree", - true, - true, - true, - false, - true, - true, - true, - false - ), - Hive("Hive", false, true, false, false, true, false, false, false), ReplacingMergeTree( "ReplacingMergeTree", true, @@ -261,28 +112,6 @@ public enum TimeplusEngineTypeEnum { true, true ), - DeltaLake( - "DeltaLake", - false, - false, - false, - false, - false, - false, - false, - false - ), - EmbeddedRocksDB( - "EmbeddedRocksDB", - true, - true, - false, - false, - false, - true, - false, - false - ), ReplicatedCollapsingMergeTree( "ReplicatedCollapsingMergeTree", true, @@ -295,18 +124,6 @@ public enum TimeplusEngineTypeEnum { true ), File("File", false, false, false, false, true, false, false, false), - TinyLog("TinyLog", false, false, false, false, true, false, false, false), - ReplicatedGraphiteMergeTree( - "ReplicatedGraphiteMergeTree", - true, - true, - true, - true, - true, - true, - true, - true - ), SummingMergeTree( "SummingMergeTree", true, @@ -318,18 +135,6 @@ public enum TimeplusEngineTypeEnum { true, false ), - Hudi("Hudi", false, false, false, false, false, false, false, false), - GraphiteMergeTree( - "GraphiteMergeTree", - true, - true, - true, - false, - true, - true, - true, - false - ), CollapsingMergeTree( "CollapsingMergeTree", true, @@ -353,19 +158,8 @@ public enum TimeplusEngineTypeEnum { true, false ), - ODBC("ODBC", false, false, false, false, false, false, false, false), Null("Null", false, false, false, false, false, true, false, false), - StripeLog( - "StripeLog", - false, - false, - false, - false, - true, - false, - false, - false - ), + Log("Log", false, false, false, false, true, false, false, false); private static Map ENGINE_TYPE_MAP =