From dbfda7eec6c46068afabe9b0cffb4107fbaae71e Mon Sep 17 00:00:00 2001 From: tmlx1990 Date: Tue, 16 Apr 2024 16:44:28 +0800 Subject: [PATCH 1/5] =?UTF-8?q?=E4=BF=AE=E5=A4=8DHive=E4=B8=8D=E8=83=BD?= =?UTF-8?q?=E6=9F=A5=E7=9C=8B=E5=BA=93=E7=9A=84=E9=97=AE=E9=A2=98=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ai/chat2db/plugin/hive/HiveMetaData.java | 2 +- .../plugin/hive/builder/HiveSqlBuilder.java | 148 +----------------- .../plugin/hive/type/HiveColumnTypeEnum.java | 2 +- 3 files changed, 4 insertions(+), 148 deletions(-) diff --git a/chat2db-server/chat2db-plugins/chat2db-hive/src/main/java/ai/chat2db/plugin/hive/HiveMetaData.java b/chat2db-server/chat2db-plugins/chat2db-hive/src/main/java/ai/chat2db/plugin/hive/HiveMetaData.java index 59e62955c..0579d4876 100644 --- a/chat2db-server/chat2db-plugins/chat2db-hive/src/main/java/ai/chat2db/plugin/hive/HiveMetaData.java +++ b/chat2db-server/chat2db-plugins/chat2db-hive/src/main/java/ai/chat2db/plugin/hive/HiveMetaData.java @@ -68,7 +68,7 @@ public String tableDDL(Connection connection, @NotEmpty String databaseName, Str @Override public String getMetaDataName(String... names) { - return Arrays.stream(names).filter(name -> StringUtils.isNotBlank(name)).map(name -> "`" + name + "`").collect(Collectors.joining(".")); + return Arrays.stream(names).skip(1).filter(name -> StringUtils.isNotBlank(name)).map(name -> "`" + name + "`").collect(Collectors.joining(".")); } @Override 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..fc690bcf8 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 @@ -2,21 +2,15 @@ import ai.chat2db.plugin.hive.type.HiveColumnTypeEnum; import ai.chat2db.plugin.hive.type.HiveIndexTypeEnum; -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 cn.hutool.core.util.ArrayUtil; import org.apache.commons.lang3.StringUtils; -import java.util.Arrays; -import java.util.HashMap; -import java.util.Map; - -public class HiveSqlBuilder extends DefaultSqlBuilder implements SqlBuilder { +public class HiveSqlBuilder extends DefaultSqlBuilder { @Override public String buildCreateTableSql(Table table) { StringBuilder script = new StringBuilder(); @@ -117,7 +111,7 @@ public String buildModifyTaleSql(Table oldTable, Table newTable) { } // append reorder column - script.append(buildGenerateReorderColumnSql(oldTable, newTable)); + // script.append(buildGenerateReorderColumnSql(oldTable, newTable)); if (script.length() > 2) { script = new StringBuilder(script.substring(0, script.length() - 2)); @@ -156,142 +150,4 @@ public String buildCreateDatabaseSql(Database database) { return sqlBuilder.toString(); } - public String buildGenerateReorderColumnSql(Table oldTable, Table newTable) { - StringBuilder sql = new StringBuilder(); - int n = 0; - // Create a map to store the index of each column in the old table's column list - Map oldColumnIndexMap = new HashMap<>(); - for (int i = 0; i < oldTable.getColumnList().size(); i++) { - oldColumnIndexMap.put(oldTable.getColumnList().get(i).getName(), i); - } - String[] oldColumnArray = oldTable.getColumnList().stream().map(TableColumn::getName).toArray(String[]::new); - String[] newColumnArray = newTable.getColumnList().stream().map(TableColumn::getName).toArray(String[]::new); - - buildSql(oldColumnArray, newColumnArray, sql, oldTable, newTable, n); - - return sql.toString(); - } - - private String[] buildSql(String[] originalArray, String[] targetArray, StringBuilder sql, Table oldTable, Table newTable, int n) { - // 先完成首位移动 - if (!originalArray[0].equals(targetArray[0])) { - int a = findIndex(originalArray, targetArray[0]); - TableColumn column = oldTable.getColumnList().stream().filter(col -> StringUtils.equals(col.getName(), originalArray[a])).findFirst().get(); - String[] newArray = moveElement(originalArray, a, 0); - System.out.println(ArrayUtil.toString(newArray)); - sql.append(" MODIFY COLUMN "); - HiveColumnTypeEnum typeEnum = HiveColumnTypeEnum.getByType(column.getColumnType()); - sql.append(typeEnum.buildColumn(column)); - sql.append(" FIRST;\n"); - n++; - if (Arrays.equals(newArray, targetArray)) { - return newArray; - } - String[] resultArray = buildSql(newArray, targetArray, sql, oldTable, newTable, n); - if (Arrays.equals(resultArray, targetArray)) { - return resultArray; - } - } - - // 在完成最后一位移动 - int max = originalArray.length - 1; - if (!originalArray[max].equals(targetArray[max])) { - int a = findIndex(originalArray, targetArray[max]); - //System.out.println("Move " + originalArray[a] + " after " + (a > 0 ? originalArray[max] : "start")); - TableColumn column = oldTable.getColumnList().stream().filter(col -> StringUtils.equals(col.getName(), originalArray[a])).findFirst().get(); - String[] newArray = moveElement(originalArray, a, max); - System.out.println(ArrayUtil.toString(newArray)); - if (n > 0) { - sql.append("ALTER TABLE "); - if (StringUtils.isNotBlank(oldTable.getDatabaseName())) { - sql.append("`").append(oldTable.getDatabaseName()).append("`").append("."); - } - sql.append("`").append(oldTable.getName()).append("`").append("\n"); - } - sql.append(" MODIFY COLUMN "); - HiveColumnTypeEnum typeEnum = HiveColumnTypeEnum.getByType(column.getColumnType()); - sql.append(typeEnum.buildColumn(column)); - sql.append(" "); - sql.append(" AFTER "); - sql.append(oldTable.getColumnList().get(max).getName()); - sql.append(";\n"); - n++; - if (Arrays.equals(newArray, targetArray)) { - return newArray; - } - String[] resultArray = buildSql(newArray, targetArray, sql, oldTable, newTable, n); - if (Arrays.equals(resultArray, targetArray)) { - return resultArray; - } - } - - - for (int i = 0; i < originalArray.length; i++) { - int a = findIndex(targetArray, originalArray[i]); - if (i != a && isMoveValid(originalArray, targetArray, i, a)) { - // oldTable.getColumnList中查找name为a - int finalI = i; - TableColumn column = oldTable.getColumnList().stream().filter(col -> StringUtils.equals(col.getName(), originalArray[finalI])).findFirst().get(); - if (n > 0) { - sql.append("ALTER TABLE "); - if (StringUtils.isNotBlank(oldTable.getDatabaseName())) { - sql.append("`").append(oldTable.getDatabaseName()).append("`").append("."); - } - sql.append("`").append(oldTable.getName()).append("`").append("\n"); - } - sql.append(" MODIFY COLUMN "); - HiveColumnTypeEnum typeEnum = HiveColumnTypeEnum.getByType(column.getColumnType()); - sql.append(typeEnum.buildColumn(column)); - sql.append(" "); - sql.append(" AFTER "); - if (i < a) { - sql.append(originalArray[a]); - } else { - sql.append(originalArray[a - 1]); - } - - sql.append(";\n"); - n++; - String[] newArray = moveElement(originalArray, i, a); - if (Arrays.equals(newArray, targetArray)) { - return newArray; - } - String[] resultArray = buildSql(newArray, targetArray, sql, oldTable, newTable, n); - if (Arrays.equals(resultArray, targetArray)) { - return resultArray; - } - } - } - return null; - } - - private static int findIndex(String[] array, String element) { - for (int i = 0; i < array.length; i++) { - if (array[i].equals(element)) { - return i; - } - } - return -1; - } - - private static boolean isMoveValid(String[] originalArray, String[] targetArray, int i, int a) { - System.out.println("i : " + i + " a:" + a); - return (i == 0 || a == 0 || !originalArray[i - 1].equals(targetArray[a - 1])) && - (i >= originalArray.length - 1 || a >= targetArray.length - 1 || !originalArray[i + 1].equals(targetArray[a + 1])); - } - - private static String[] moveElement(String[] originalArray, int from, int to) { - String[] newArray = new String[originalArray.length]; - System.arraycopy(originalArray, 0, newArray, 0, originalArray.length); - String temp = newArray[from]; - if (from < to) { - System.arraycopy(originalArray, from + 1, newArray, from, to - from); - } else { - System.arraycopy(originalArray, to, newArray, to + 1, from - to); - } - newArray[to] = temp; - System.out.println(ArrayUtil.toString(newArray)); - return newArray; - } - } diff --git a/chat2db-server/chat2db-plugins/chat2db-hive/src/main/java/ai/chat2db/plugin/hive/type/HiveColumnTypeEnum.java b/chat2db-server/chat2db-plugins/chat2db-hive/src/main/java/ai/chat2db/plugin/hive/type/HiveColumnTypeEnum.java index c5348b52b..2c19fd0ff 100644 --- a/chat2db-server/chat2db-plugins/chat2db-hive/src/main/java/ai/chat2db/plugin/hive/type/HiveColumnTypeEnum.java +++ b/chat2db-server/chat2db-plugins/chat2db-hive/src/main/java/ai/chat2db/plugin/hive/type/HiveColumnTypeEnum.java @@ -150,7 +150,7 @@ public String buildModifyColumn(TableColumn tableColumn) { if (!StringUtils.equalsIgnoreCase(tableColumn.getOldName(), tableColumn.getName())) { return StringUtils.join("CHANGE COLUMN `", tableColumn.getOldName(), "` ", buildCreateColumnSql(tableColumn)); } else { - return StringUtils.join("MODIFY COLUMN ", buildCreateColumnSql(tableColumn)); + return StringUtils.join("CHANGE `", tableColumn.getOldName(), "` ", buildCreateColumnSql(tableColumn)); } } return ""; From 56db9651f28346fb2971fb23c90ba472ce983269 Mon Sep 17 00:00:00 2001 From: tmlx1990 Date: Mon, 13 May 2024 01:08:02 +0800 Subject: [PATCH 2/5] =?UTF-8?q?xugudb=E5=9F=BA=E7=A1=80=E4=BB=A3=E7=A0=81?= =?UTF-8?q?=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ConnectionEdit/config/dataSource.ts | 121 +++++++ chat2db-client/src/constants/common.ts | 1 + chat2db-client/src/constants/database.ts | 7 + .../chat2db-plugins/chat2db-xugudb/pom.xml | 35 ++ .../chat2db/plugin/xugudb/XUGUDBManage.java | 160 +++++++++ .../chat2db/plugin/xugudb/XUGUDBMetaData.java | 254 +++++++++++++++ .../chat2db/plugin/xugudb/XUGUDBPlugin.java | 25 ++ .../xugudb/builder/XUGUDBSqlBuilder.java | 137 ++++++++ .../xugudb/type/XUGUDBColumnTypeEnum.java | 306 ++++++++++++++++++ .../xugudb/type/XUGUDBDefaultValueEnum.java | 27 ++ .../xugudb/type/XUGUDBIndexTypeEnum.java | 129 ++++++++ .../java/ai/chat2db/plugin/xugudb/xugudb.json | 18 ++ .../META-INF/services/ai.chat2db.spi.Plugin | 1 + chat2db-server/chat2db-plugins/pom.xml | 1 + .../chat2db-server-domain-core/pom.xml | 5 + 15 files changed, 1227 insertions(+) create mode 100644 chat2db-server/chat2db-plugins/chat2db-xugudb/pom.xml create mode 100644 chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/XUGUDBManage.java create mode 100644 chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/XUGUDBMetaData.java create mode 100644 chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/XUGUDBPlugin.java create mode 100644 chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/builder/XUGUDBSqlBuilder.java create mode 100644 chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/type/XUGUDBColumnTypeEnum.java create mode 100644 chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/type/XUGUDBDefaultValueEnum.java create mode 100644 chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/type/XUGUDBIndexTypeEnum.java create mode 100644 chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/xugudb.json create mode 100644 chat2db-server/chat2db-plugins/chat2db-xugudb/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 f14c86510..2b974edbf 100644 --- a/chat2db-client/src/components/ConnectionEdit/config/dataSource.ts +++ b/chat2db-client/src/components/ConnectionEdit/config/dataSource.ts @@ -2080,4 +2080,125 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [ extendInfo: [], type: DatabaseTypeCode.MONGODB }, + //MONGODB + { + baseInfo: { + items: [ + { + defaultValue: '@localhost', + inputType: InputType.INPUT, + labelNameCN: '名称', + labelNameEN: 'Name', + name: 'alias', + required: true, + styles: { + width: '100%', + } + }, + envItem, + { + defaultValue: 'localhost', + inputType: InputType.INPUT, + labelNameCN: '主机', + labelNameEN: 'Host', + name: 'host', + required: true, + styles: { + width: '70%', + } + }, + { + defaultValue: '5138', + 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: 'root', + inputType: InputType.INPUT, + labelNameCN: '用户名', + labelNameEN: 'User', + name: 'user', + required: true, + styles: { + width: '100%', + } + }, + { + defaultValue: '', + inputType: InputType.PASSWORD, + labelNameCN: '密码', + labelNameEN: 'Password', + name: 'password', + required: true, + styles: { + width: '100%', + } + }, + ], + 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, + styles: { + width: '100%', + } + }, + { + defaultValue: 'jdbc:xugu://localhost:5138', + inputType: InputType.INPUT, + labelNameCN: 'URL', + labelNameEN: 'URL', + name: 'url', + required: true, + styles: { + width: '100%', + } + }, + + ], + pattern: /jdbc:xugu:\/\/(.*):(\d+)(\/(\w+))?/, + template: 'jdbc:xugu://{host}:{port}/{database}', + //excludes: [OperationColumn.ViewDDL, OperationColumn.CreateTable,OperationColumn.EditTable] + }, + ssh: sshConfig, + extendInfo: [], + type: DatabaseTypeCode.XUGUDB + }, ]; diff --git a/chat2db-client/src/constants/common.ts b/chat2db-client/src/constants/common.ts index b6f2339be..26e4156e5 100644 --- a/chat2db-client/src/constants/common.ts +++ b/chat2db-client/src/constants/common.ts @@ -15,6 +15,7 @@ export enum DatabaseTypeCode { PRESTO = "PRESTO", HIVE = "HIVE", KINGBASE = "KINGBASE", + XUGUDB = "XUGUDB", } export enum ConsoleStatus { diff --git a/chat2db-client/src/constants/database.ts b/chat2db-client/src/constants/database.ts index ba7c3c75c..1ba66b063 100644 --- a/chat2db-client/src/constants/database.ts +++ b/chat2db-client/src/constants/database.ts @@ -118,6 +118,13 @@ export const databaseMap: { // port: 27017, icon: '\uec21', }, + [DatabaseTypeCode.XUGUDB]: { + name: 'XuguDB', + img: moreDBLogo, + code: DatabaseTypeCode.XUGUDB, + // port: 5138, + icon: '\uec21', + }, // [DatabaseTypeCode.REDIS]: { // name: 'Redis', // img: moreDBLogo, diff --git a/chat2db-server/chat2db-plugins/chat2db-xugudb/pom.xml b/chat2db-server/chat2db-plugins/chat2db-xugudb/pom.xml new file mode 100644 index 000000000..f02c6049b --- /dev/null +++ b/chat2db-server/chat2db-plugins/chat2db-xugudb/pom.xml @@ -0,0 +1,35 @@ + + + 4.0.0 + + ai.chat2db + chat2db-plugins + ${revision} + ../pom.xml + + + + + ai.chat2db + chat2db-spi + + + + chat2db-xugudb + + + + src/main/java + + + **/*.json + + + + src/main/resources + + + + \ No newline at end of file diff --git a/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/XUGUDBManage.java b/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/XUGUDBManage.java new file mode 100644 index 000000000..1934cdf69 --- /dev/null +++ b/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/XUGUDBManage.java @@ -0,0 +1,160 @@ +package ai.chat2db.plugin.xugudb; + +import java.sql.*; + +import ai.chat2db.spi.DBManage; +import ai.chat2db.spi.jdbc.DefaultDBManage; +import ai.chat2db.spi.sql.Chat2DBContext; +import ai.chat2db.spi.sql.ConnectInfo; +import ai.chat2db.spi.sql.SQLExecutor; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; + +public class XUGUDBManage extends DefaultDBManage implements DBManage { + private String format(String tableName) { + return "\"" + tableName + "\""; + } + private static String ROUTINES_SQL + = "SELECT OWNER, NAME, TEXT FROM ALL_SOURCE WHERE TYPE = '%s' AND OWNER = '%s' AND NAME = '%s' ORDER BY LINE"; + private static String TRIGGER_SQL_LIST = "SELECT OWNER, TRIGGER_NAME FROM ALL_TRIGGERS WHERE OWNER = '%s'"; + + private static String TRIGGER_SQL + = "SELECT OWNER, TRIGGER_NAME, TABLE_OWNER, TABLE_NAME, TRIGGERING_TYPE, TRIGGERING_EVENT, STATUS, TRIGGER_BODY " + + "FROM ALL_TRIGGERS WHERE OWNER = '%s' AND TRIGGER_NAME = '%s'"; + @Override + public String exportDatabase(Connection connection, String databaseName, String schemaName, boolean containData) throws SQLException { + StringBuilder sqlBuilder = new StringBuilder(); + exportTables(connection, sqlBuilder, schemaName, containData); + exportViews(connection, schemaName, sqlBuilder); + exportProcedures(connection, schemaName, sqlBuilder); + exportTriggers(connection,schemaName, sqlBuilder); + return sqlBuilder.toString(); + } + + private void exportTables(Connection connection, StringBuilder sqlBuilder, String schemaName, boolean containData) throws SQLException { + String sql =String.format("SELECT TABLE_NAME FROM ALL_TABLES where OWNER='%s' and TABLESPACE_NAME='MAIN'", schemaName); + try (ResultSet resultSet = connection.createStatement().executeQuery(sql)) { + while (resultSet.next()) { + String tableName = resultSet.getString("TABLE_NAME"); + exportTable(connection, tableName, schemaName, sqlBuilder, containData); + } + } + } + + + private void exportTable(Connection connection, String tableName, String schemaName, StringBuilder sqlBuilder, boolean containData) throws SQLException { + String sql = """ + SELECT + (SELECT comments FROM user_tab_comments WHERE table_name = '%s') AS comments, + (SELECT dbms_metadata.get_ddl('TABLE', '%s', '%s') FROM dual) AS ddl + FROM dual; + """; + try (Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery(String.format(sql, tableName, tableName, schemaName))) { + String formatSchemaName = format(schemaName); + String formatTableName = format(tableName); + if (resultSet.next()) { + sqlBuilder.append("DROP TABLE IF EXISTS ").append(formatSchemaName).append(".").append(formatTableName) + .append(";").append("\n") + .append(resultSet.getString("ddl")).append("\n"); + String comment = resultSet.getString("comments"); + if (StringUtils.isNotBlank(comment)) { + sqlBuilder.append("COMMENT ON TABLE ").append(formatSchemaName).append(".").append(formatTableName) + .append(" IS ").append("'").append(comment).append("';"); + } + exportTableColumnComment(connection, schemaName, tableName, sqlBuilder); + } + if (containData) { + exportTableData(connection, schemaName, tableName, sqlBuilder); + } + } + } + + private void exportTableColumnComment(Connection connection, String schemaName, String tableName, StringBuilder sqlBuilder) throws SQLException { + String sql =String.format("select COLNAME,COMMENT$ from SYS.SYSCOLUMNCOMMENTS\n" + + "where SCHNAME = '%s' and TVNAME = '%s'and TABLE_TYPE = 'TABLE';", schemaName,tableName); + try(ResultSet resultSet = connection.createStatement().executeQuery(sql)) { + while (resultSet.next()) { + String columnName = resultSet.getString("COLNAME"); + String comment = resultSet.getString("COMMENT$"); + sqlBuilder.append("COMMENT ON COLUMN ").append(format(schemaName)).append(".").append(format(tableName)) + .append(".").append(format(columnName)).append(" IS ").append("'").append(comment).append("';").append("\n"); + } + } + } + + + private void exportViews(Connection connection, String schemaName, StringBuilder sqlBuilder) throws SQLException { + try (ResultSet resultSet = connection.getMetaData().getTables(null, schemaName, null, new String[]{"VIEW"})) { + while (resultSet.next()) { + String viewName = resultSet.getString("TABLE_NAME"); + exportView(connection, viewName, schemaName, sqlBuilder); + } + } + } + + private void exportView(Connection connection, String viewName, String schemaName, StringBuilder sqlBuilder) throws SQLException { + String sql = String.format("SELECT DBMS_METADATA.GET_DDL('VIEW','%s','%s') as ddl FROM DUAL;", viewName, schemaName); + try (ResultSet resultSet = connection.createStatement().executeQuery(sql)) { + if (resultSet.next()) { + sqlBuilder.append(resultSet.getString("ddl")).append("\n"); + } + } + } + + private void exportProcedures(Connection connection, String schemaName, StringBuilder sqlBuilder) throws SQLException { + try (ResultSet resultSet = connection.getMetaData().getProcedures(null, schemaName, null)) { + while (resultSet.next()) { + String procedureName = resultSet.getString("PROCEDURE_NAME"); + exportProcedure(connection, schemaName,procedureName, sqlBuilder); + } + } + } + + private void exportProcedure(Connection connection, String schemaName, String procedureName, StringBuilder sqlBuilder) throws SQLException { + String sql = String.format(ROUTINES_SQL,"PROC", schemaName,procedureName); + try (Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery(sql)) { + if (resultSet.next()) { + sqlBuilder.append(resultSet.getString("TEXT")).append("\n"); + } + } + } + + private void exportTriggers(Connection connection, String schemaName, StringBuilder sqlBuilder) throws SQLException { + String sql =String.format(TRIGGER_SQL_LIST, schemaName); + try (ResultSet resultSet = connection.createStatement().executeQuery(sql)) { + while (resultSet.next()) { + String triggerName = resultSet.getString("TRIGGER_NAME"); + exportTrigger(connection,schemaName, triggerName, sqlBuilder); + } + } + } + + private void exportTrigger(Connection connection, String schemaName, String triggerName, StringBuilder sqlBuilder) throws SQLException { + String sql = String.format(TRIGGER_SQL, schemaName,triggerName); + try (ResultSet resultSet = connection.createStatement().executeQuery(sql)) { + if (resultSet.next()) { + sqlBuilder.append(resultSet.getString("TRIGGER_BODY")).append("\n"); + } + } + } + + @Override + public void connectDatabase(Connection connection, String database) { + ConnectInfo connectInfo = Chat2DBContext.getConnectInfo(); + if (ObjectUtils.anyNull(connectInfo) || StringUtils.isEmpty(connectInfo.getSchemaName())) { + return; + } + String schemaName = connectInfo.getSchemaName(); + try { + SQLExecutor.getInstance().execute(connection, "SET SCHEMA \"" + schemaName + "\""); + } catch (SQLException e) { + e.printStackTrace(); + } + } + + @Override + public void dropTable(Connection connection, String databaseName, String schemaName, String tableName) { + String sql = "DROP TABLE IF EXISTS " +tableName; + SQLExecutor.getInstance().execute(connection,sql, resultSet -> null); + } +} diff --git a/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/XUGUDBMetaData.java b/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/XUGUDBMetaData.java new file mode 100644 index 000000000..c76d8b81f --- /dev/null +++ b/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/XUGUDBMetaData.java @@ -0,0 +1,254 @@ +package ai.chat2db.plugin.xugudb; + +import ai.chat2db.plugin.xugudb.builder.XUGUDBSqlBuilder; +import ai.chat2db.plugin.xugudb.type.XUGUDBColumnTypeEnum; +import ai.chat2db.plugin.xugudb.type.XUGUDBDefaultValueEnum; +import ai.chat2db.plugin.xugudb.type.XUGUDBIndexTypeEnum; +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 ai.chat2db.spi.util.SortUtils; +import com.google.common.collect.Lists; +import jakarta.validation.constraints.NotEmpty; +import org.apache.commons.lang3.StringUtils; + +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.*; +import java.util.stream.Collectors; + +public class XUGUDBMetaData extends DefaultMetaService implements MetaData { + + private List systemSchemas = Arrays.asList("CTISYS", "SYS","SYSDBA","SYSSSO","SYSAUDITOR"); + + @Override + public List schemas(Connection connection, String databaseName) { + List schemas = SQLExecutor.getInstance().schemas(connection, databaseName, null); + return SortUtils.sortSchema(schemas, systemSchemas); + } + private String format(String tableName){ + return "\"" + tableName + "\""; + } + + public String tableDDL(Connection connection, String databaseName, String schemaName, String tableName) { + String sql = """ + SELECT + (SELECT comments FROM user_tab_comments WHERE table_name = '%s') AS comments, + (SELECT dbms_metadata.get_ddl('TABLE', '%s', '%s') FROM dual) AS ddl + FROM dual; + """; + StringBuilder ddlBuilder = new StringBuilder(); + String tableDDLSql = String.format(sql, tableName, tableName, schemaName); + SQLExecutor.getInstance().execute(connection, tableDDLSql, resultSet -> { + if (resultSet.next()) { + String ddl = resultSet.getString("ddl"); + String comment = resultSet.getString("comments"); + if (StringUtils.isNotBlank(comment)) { + ddlBuilder.append(ddl).append("\n").append("COMMENT ON TABLE ").append(format(schemaName)) + .append(".").append(format(tableName)).append(" IS ").append("'").append(comment).append("';"); + } + } + }); + String columnCommentsSql =String.format("select COLNAME,COMMENT$ from SYS.SYSCOLUMNCOMMENTS\n" + + "where SCHNAME = '%s' and TVNAME = '%s'and TABLE_TYPE = 'TABLE';", schemaName,tableName); + SQLExecutor.getInstance().execute(connection, columnCommentsSql, resultSet->{ + while (resultSet.next()) { + String columnName = resultSet.getString("COLNAME"); + String comment = resultSet.getString("COMMENT$"); + ddlBuilder.append("COMMENT ON COLUMN ").append(format(schemaName)).append(".").append(format(tableName)) + .append(".").append(format(columnName)).append(" IS ").append("'").append(comment).append("';").append("\n"); + } + }); + return ddlBuilder.toString(); + } + + private static String ROUTINES_SQL + = "SELECT OWNER, NAME, TEXT FROM ALL_SOURCE WHERE TYPE = '%s' AND OWNER = '%s' AND NAME = '%s' ORDER BY LINE"; + + @Override + public Function function(Connection connection, @NotEmpty String databaseName, String schemaName, + String functionName) { + + String sql = String.format(ROUTINES_SQL, "PROC",schemaName, functionName); + return SQLExecutor.getInstance().execute(connection, sql, resultSet -> { + StringBuilder sb = new StringBuilder(); + while (resultSet.next()) { + sb.append(resultSet.getString("TEXT") + "\n"); + } + Function function = new Function(); + function.setDatabaseName(databaseName); + function.setSchemaName(schemaName); + function.setFunctionName(functionName); + function.setFunctionBody(sb.toString()); + return function; + + }); + + } + + @Override + public Procedure procedure(Connection connection, @NotEmpty String databaseName, String schemaName, + String procedureName) { + String sql = String.format(ROUTINES_SQL, "PROC", schemaName,procedureName); + return SQLExecutor.getInstance().execute(connection, sql, resultSet -> { + StringBuilder sb = new StringBuilder(); + while (resultSet.next()) { + sb.append(resultSet.getString("TEXT") + "\n"); + } + Procedure procedure = new Procedure(); + procedure.setDatabaseName(databaseName); + procedure.setSchemaName(schemaName); + procedure.setProcedureName(procedureName); + procedure.setProcedureBody(sb.toString()); + return procedure; + }); + } + + private static String TRIGGER_SQL + = "SELECT OWNER, TRIGGER_NAME, TABLE_OWNER, TABLE_NAME, TRIGGERING_TYPE, TRIGGERING_EVENT, STATUS, TRIGGER_BODY " + + "FROM ALL_TRIGGERS WHERE OWNER = '%s' AND TRIGGER_NAME = '%s'"; + + private static String TRIGGER_SQL_LIST = "SELECT OWNER, TRIGGER_NAME FROM ALL_TRIGGERS WHERE OWNER = '%s'"; + + @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, schemaName, 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("TRIGGER_BODY")); + } + return trigger; + }); + } + + private static String VIEW_SQL + = "SELECT OWNER, VIEW_NAME, TEXT FROM ALL_VIEWS WHERE OWNER = '%s' AND VIEW_NAME = '%s'"; + + @Override + public Table view(Connection connection, String databaseName, String schemaName, String viewName) { + String sql = String.format(VIEW_SQL, schemaName, 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("TEXT")); + } + return table; + }); + } + + private static String INDEX_SQL = "SELECT i.TABLE_NAME, i.INDEX_TYPE, i.INDEX_NAME, i.UNIQUENESS ,c.COLUMN_NAME, c.COLUMN_POSITION, c.DESCEND, cons.CONSTRAINT_TYPE FROM ALL_INDEXES i JOIN ALL_IND_COLUMNS c ON i.INDEX_NAME = c.INDEX_NAME AND i.TABLE_NAME = c.TABLE_NAME AND i.TABLE_OWNER = c.TABLE_OWNER LEFT JOIN ALL_CONSTRAINTS cons ON i.INDEX_NAME = cons.INDEX_NAME AND i.TABLE_NAME = cons.TABLE_NAME AND i.TABLE_OWNER = cons.OWNER WHERE i.TABLE_OWNER = '%s' AND i.TABLE_NAME = '%s' ORDER BY i.INDEX_NAME, c.COLUMN_POSITION;"; + + @Override + public List indexes(Connection connection, String databaseName, String schemaName, String tableName) { + String sql = String.format(INDEX_SQL, schemaName, tableName); + return SQLExecutor.getInstance().execute(connection, sql, resultSet -> { + LinkedHashMap map = new LinkedHashMap(); + while (resultSet.next()) { + String keyName = resultSet.getString("INDEX_NAME"); + TableIndex tableIndex = map.get(keyName); + if (tableIndex != null) { + List columnList = tableIndex.getColumnList(); + columnList.add(getTableIndexColumn(resultSet)); + columnList = columnList.stream().sorted(Comparator.comparing(TableIndexColumn::getOrdinalPosition)) + .collect(Collectors.toList()); + tableIndex.setColumnList(columnList); + } else { + TableIndex index = new TableIndex(); + index.setDatabaseName(databaseName); + index.setSchemaName(schemaName); + index.setTableName(tableName); + index.setName(keyName); + index.setUnique("UNIQUE".equalsIgnoreCase(resultSet.getString("UNIQUENESS"))); +// index.setType(resultSet.getString("Index_type")); +// index.setComment(resultSet.getString("Index_comment")); + List tableIndexColumns = new ArrayList<>(); + tableIndexColumns.add(getTableIndexColumn(resultSet)); + index.setColumnList(tableIndexColumns); + if ("P".equalsIgnoreCase(resultSet.getString("CONSTRAINT_TYPE"))) { + index.setType(XUGUDBIndexTypeEnum.PRIMARY_KEY.getName()); + } else if (index.getUnique()) { + index.setType(XUGUDBIndexTypeEnum.UNIQUE.getName()); + } else if ("BITMAP".equalsIgnoreCase(resultSet.getString("INDEX_TYPE"))) { + index.setType(XUGUDBIndexTypeEnum.BITMAP.getName()); + } else { + index.setType(XUGUDBIndexTypeEnum.NORMAL.getName()); + } + map.put(keyName, index); + } + } + return map.values().stream().collect(Collectors.toList()); + }); + + } + + private TableIndexColumn getTableIndexColumn(ResultSet resultSet) throws SQLException { + TableIndexColumn tableIndexColumn = new TableIndexColumn(); + tableIndexColumn.setColumnName(resultSet.getString("COLUMN_NAME")); + tableIndexColumn.setOrdinalPosition(resultSet.getShort("COLUMN_POSITION")); +// tableIndexColumn.setCollation(resultSet.getString("Collation")); +// tableIndexColumn.setCardinality(resultSet.getLong("Cardinality")); +// tableIndexColumn.setSubPart(resultSet.getLong("Sub_part")); + String collation = resultSet.getString("DESCEND"); + if ("ASC".equalsIgnoreCase(collation)) { + tableIndexColumn.setAscOrDesc("ASC"); + } else if ("DESC".equalsIgnoreCase(collation)) { + tableIndexColumn.setAscOrDesc("DESC"); + } + return tableIndexColumn; + } + + @Override + public SqlBuilder getSqlBuilder() { + return new XUGUDBSqlBuilder(); + } + + @Override + public TableMeta getTableMeta(String databaseName, String schemaName, String tableName) { + return TableMeta.builder() + .columnTypes(XUGUDBColumnTypeEnum.getTypes()) + .charsets(Lists.newArrayList()) + .collations(Lists.newArrayList()) + .indexTypes(XUGUDBIndexTypeEnum.getIndexTypes()) + .defaultValues(XUGUDBDefaultValueEnum.getDefaultValues()) + .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 getSystemSchemas() { + return systemSchemas; + } +} diff --git a/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/XUGUDBPlugin.java b/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/XUGUDBPlugin.java new file mode 100644 index 000000000..d53807728 --- /dev/null +++ b/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/XUGUDBPlugin.java @@ -0,0 +1,25 @@ +package ai.chat2db.plugin.xugudb; + +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 XUGUDBPlugin implements Plugin { + @Override + public DBConfig getDBConfig() { + return FileUtils.readJsonValue(this.getClass(),"xugudb.json", DBConfig.class); + + } + + @Override + public MetaData getMetaData() { + return new XUGUDBMetaData(); + } + + @Override + public DBManage getDBManage() { + return new XUGUDBManage(); + } +} diff --git a/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/builder/XUGUDBSqlBuilder.java b/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/builder/XUGUDBSqlBuilder.java new file mode 100644 index 000000000..4b808b977 --- /dev/null +++ b/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/builder/XUGUDBSqlBuilder.java @@ -0,0 +1,137 @@ +package ai.chat2db.plugin.xugudb.builder; + +import ai.chat2db.plugin.xugudb.type.XUGUDBColumnTypeEnum; +import ai.chat2db.plugin.xugudb.type.XUGUDBIndexTypeEnum; +import ai.chat2db.spi.enums.EditStatus; +import ai.chat2db.spi.jdbc.DefaultSqlBuilder; +import ai.chat2db.spi.model.Schema; +import ai.chat2db.spi.model.Table; +import ai.chat2db.spi.model.TableColumn; +import ai.chat2db.spi.model.TableIndex; +import org.apache.commons.lang3.StringUtils; + +import java.util.Objects; + +public class XUGUDBSqlBuilder extends DefaultSqlBuilder { + + + @Override + public String buildCreateTableSql(Table table) { + StringBuilder script = new StringBuilder(); + + script.append("CREATE TABLE ").append("\"").append(table.getSchemaName()).append("\".\"").append(table.getName()).append("\" (").append("\n"); + + for (TableColumn column : table.getColumnList()) { + if (StringUtils.isBlank(column.getName()) || StringUtils.isBlank(column.getColumnType())) { + continue; + } + XUGUDBColumnTypeEnum typeEnum = XUGUDBColumnTypeEnum.getByType(column.getColumnType()); + script.append("\t").append(typeEnum.buildCreateColumnSql(column)).append(",\n"); + } + + script = new StringBuilder(script.substring(0, script.length() - 2)); + script.append("\n);"); + + for (TableIndex tableIndex : table.getIndexList()) { + if (StringUtils.isBlank(tableIndex.getName()) || StringUtils.isBlank(tableIndex.getType())) { + continue; + } + XUGUDBIndexTypeEnum indexTypeEnum = XUGUDBIndexTypeEnum.getByType(tableIndex.getType()); + script.append("\n").append("").append(indexTypeEnum.buildIndexScript(tableIndex)).append(";"); + } + + for (TableColumn column : table.getColumnList()) { + if (StringUtils.isBlank(column.getName()) || StringUtils.isBlank(column.getColumnType()) || StringUtils.isBlank(column.getComment())) { + continue; + } + script.append("\n").append(buildComment(column)).append(";"); + } + + if (StringUtils.isNotBlank(table.getComment())) { + script.append("\n").append(buildTableComment(table)).append(";"); + } + + + return script.toString(); + } + + private String buildTableComment(Table table) { + StringBuilder script = new StringBuilder(); + script.append("COMMENT ON TABLE ").append("\"").append(table.getSchemaName()).append("\".\"").append(table.getName()).append("\" IS '").append(table.getComment()).append("'"); + return script.toString(); + } + + private String buildComment(TableColumn column) { + StringBuilder script = new StringBuilder(); + script.append("COMMENT ON COLUMN ").append("\"").append(column.getSchemaName()).append("\".\"").append(column.getTableName()).append("\".\"").append(column.getName()).append("\" IS '").append(column.getComment()).append("'"); + return script.toString(); + } + + @Override + public String buildModifyTaleSql(Table oldTable, Table newTable) { + StringBuilder script = new StringBuilder(); + + if (!StringUtils.equalsIgnoreCase(oldTable.getName(), newTable.getName())) { + script.append("ALTER TABLE ").append("\"").append(oldTable.getSchemaName()).append("\".\"").append(oldTable.getName()).append("\""); + script.append(" ").append("RENAME TO ").append("\"").append(newTable.getName()).append("\"").append(";\n"); + } + if (!StringUtils.equalsIgnoreCase(oldTable.getComment(), newTable.getComment())) { + script.append("").append(buildTableComment(newTable)).append(";\n"); + } + + + // append modify column + for (TableColumn tableColumn : newTable.getColumnList()) { + String editStatus = tableColumn.getEditStatus(); + if (StringUtils.isNotBlank(editStatus)) { + XUGUDBColumnTypeEnum typeEnum = XUGUDBColumnTypeEnum.getByType(tableColumn.getColumnType()); + script.append("\t").append(typeEnum.buildModifyColumn(tableColumn)).append(";\n"); + if (StringUtils.isNotBlank(tableColumn.getComment())&&!Objects.equals(EditStatus.DELETE.toString(),editStatus)) { + script.append("\n").append(buildComment(tableColumn)).append(";\n"); + } + } + } + + // append modify index + for (TableIndex tableIndex : newTable.getIndexList()) { + if (StringUtils.isNotBlank(tableIndex.getEditStatus()) && StringUtils.isNotBlank(tableIndex.getType())) { + XUGUDBIndexTypeEnum mysqlIndexTypeEnum = XUGUDBIndexTypeEnum.getByType(tableIndex.getType()); + script.append("\t").append(mysqlIndexTypeEnum.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 sqlStr = new StringBuilder(sql.length() + 17); + sqlStr.append(sql); + if (offset == 0) { + sqlStr.append(" LIMIT "); + sqlStr.append(pageSize); + } else { + sqlStr.append(" LIMIT "); + sqlStr.append(pageSize); + sqlStr.append(" OFFSET "); + sqlStr.append(offset); + } + return sqlStr.toString(); + } + + @Override + public String buildCreateSchemaSql(Schema schema) { + StringBuilder sqlBuilder = new StringBuilder(); + sqlBuilder.append("CREATE SCHEMA \""+schema.getName()+"\""); + if(StringUtils.isNotBlank(schema.getOwner())){ + sqlBuilder.append(" AUTHORIZATION ").append(schema.getOwner()); + } + + return sqlBuilder.toString(); + } +} diff --git a/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/type/XUGUDBColumnTypeEnum.java b/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/type/XUGUDBColumnTypeEnum.java new file mode 100644 index 000000000..41f76f754 --- /dev/null +++ b/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/type/XUGUDBColumnTypeEnum.java @@ -0,0 +1,306 @@ +package ai.chat2db.plugin.xugudb.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 com.google.common.collect.Maps; +import org.apache.commons.lang3.StringUtils; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +public enum XUGUDBColumnTypeEnum implements ColumnBuilder { + + + BFILE("BFILE", false, false, true, false, false, false, true, true, false, false), + + BIGINT("BIGINT", false, false, true, false, false, false, true, true, false, false), + + + BINARY("BINARY", false, false, true, false, false, false, true, true, false, false), + + + BIT("BIT", false, false, true, false, false, false, true, true, false, false), + + + BLOB("BLOB", false, false, true, false, false, false, true, true, false, false), + + + CHAR("CHAR", true, false, true, false, false, false, true, true, false, true), + +// CHAR_VARYING("CHAR VARYING", true, false, true, false, false, false, true, true, false, true), +// +// CHARACTER("CHARACTER", true, false, true, false, false, false, true, true, false, true), +// +// CHARACTER_VARYING("CHARACTER VARYING", true, false, true, false, false, false, true, true, false, true), + + CLOB("CLOB", 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, true, true, false, false, false, true, true, false, false), + DEC("DEC", true, true, true, false, false, false, true, true, false, false), + + DOUBLE("DOUBLE", false, false, true, false, false, false, true, true, false, false), + + + FLOAT("FLOAT", true, false, true, false, false, false, true, true, false, false), + + INT("INT", false, false, true, true, false, false, true, true, false, false), + + // INTEGER("INTEGER", false, false, true, false, false, false, true, true, false, false), + + INTERVAL_DAY("INTERVAL DAY", false, false, true, false, false, false, true, true, false, false), + + INTERVAL_DAY_TO_HOUR("INTERVAL DAY TO HOUR", true, false, true, false, false, false, true, true, false, false), + + + INTERVAL_DAY_TO_MINUTE("INTERVAL DAY TO MINUTE", true, false, true, false, false, false, true, true, false, false), + + INTERVAL_DAY_TO_SECOND("INTERVAL DAY TO SECOND", true, false, true, false, false, false, true, true, false, false), + + INTERVAL_HOUR("INTERVAL HOUR", false, false, true, false, false, false, true, true, false, false), + + INTERVAL_HOUR_TO_MINUTE("INTERVAL HOUR TO MINUTE", true, false, true, false, false, false, true, true, false, false), + + INTERVAL_HOUR_TO_SECOND("INTERVAL HOUR TO SECOND", true, false, true, false, false, false, true, true, false, false), + + INTERVAL_MINUTE("INTERVAL MINUTE", false, false, true, false, false, false, true, true, false, false), + + INTERVAL_MINUTE_TO_SECOND("INTERVAL MINUTE TO SECOND", true, false, true, false, false, false, true, true, false, false), + + + INTERVAL_MONTH("INTERVAL MONTH", false, false, true, false, false, false, true, true, false, false), + + INTERVAL_SECOND("INTERVAL SECOND", false, false, true, false, false, false, true, true, false, false), + + + INTERVAL_YEAR("INTERVAL YEAR", false, false, true, false, false, false, true, true, false, false), + + + INTERVAL_YEAR_TO_MONTH("INTERVAL YEAR TO MONTH", true, false, true, false, false, false, true, true, false, false), + + LONGVARBINARY("LONGVARBINARY", false, false, true, false, false, false, true, true, false, false), + + + LONGVARCHAR("LONGVARCHAR", false, false, true, false, false, false, true, true, false, false), + TEXT("TEXT", false, false, true, false, false, false, true, true, false, false), + + + NUMBERIC("NUMBERIC", true, true, true, false, false, false, true, true, false, false), + + + NUMBER("NUMBER", true, true, true, false, false, false, true, true, false, false), + + REAL("REAL", false, false, true, false, false, false, true, true, false, false), + + + SMALLINT("SMALLINT", false, false, true, false, false, false, true, true, false, false), + + + TIME("TIME", false, false, true, false, false, false, true, true, false, false), + + + TIME_WITH_TIME_ZONE("TIME WITH TIME ZONE", false, false, true, false, false, false, true, true, false, false), + + + TIMESTAMP("TIMESTAMP", false, false, true, false, false, false, true, true, false, false), + + + TIMESTAMP_WITH_TIME_ZONE("TIMESTAMP WITH TIME ZONE", false, false, true, false, false, false, true, true, false, false), + + + TINYINT("TINYINT", false, false, true, false, false, false, true, true, false, false), + + + VARBINARY("VARBINARY", false, false, true, false, false, false, true, true, false, false), + + + VARCHAR("VARCHAR", true, false, true, false, false, false, true, true, false, true), + + + VARCHAR2("VARCHAR2", true, false, true, false, false, false, true, true, false, true), + + ; + private ColumnType columnType; + + public static XUGUDBColumnTypeEnum getByType(String dataType) { + return COLUMN_TYPE_MAP.get(dataType.toUpperCase()); + } + + private static Map COLUMN_TYPE_MAP = Maps.newHashMap(); + + static { + for (XUGUDBColumnTypeEnum value : XUGUDBColumnTypeEnum.values()) { + COLUMN_TYPE_MAP.put(value.getColumnType().getTypeName(), value); + } + } + + public ColumnType getColumnType() { + return columnType; + } + + + XUGUDBColumnTypeEnum(String dataTypeName, boolean supportLength, boolean supportScale, boolean supportNullable, boolean supportAutoIncrement, boolean supportCharset, boolean supportCollation, boolean supportComments, boolean supportDefaultValue, boolean supportExtent, boolean supportUnit) { + this.columnType = new ColumnType(dataTypeName, supportLength, supportScale, supportNullable, supportAutoIncrement, supportCharset, supportCollation, supportComments, supportDefaultValue, supportExtent, false, supportUnit); + } + + @Override + public String buildCreateColumnSql(TableColumn column) { + XUGUDBColumnTypeEnum type = COLUMN_TYPE_MAP.get(column.getColumnType().toUpperCase()); + if (type == null) { + return ""; + } + StringBuilder script = new StringBuilder(); + + script.append("\"").append(column.getName()).append("\"").append(" "); + + script.append(buildDataType(column, type)).append(" "); + + script.append(buildDefaultValue(column, type)).append(" "); + + script.append(buildAutoIncrement(column,type)).append(" "); + + script.append(buildNullable(column, type)).append(" "); + + return script.toString(); + } + + private String buildAutoIncrement(TableColumn column, XUGUDBColumnTypeEnum type) { + if(!type.getColumnType().isSupportAutoIncrement()){ + return ""; + } + if (column.getAutoIncrement() != null && column.getAutoIncrement() + && column.getSeed() != null && column.getSeed() > 0 && column.getIncrement() != null && column.getIncrement() > 0) { + return "IDENTITY(" + column.getSeed() + "," + column.getIncrement() + ")"; + } + if (column.getAutoIncrement() != null && column.getAutoIncrement()) { + return "IDENTITY(1,1)"; + } + return ""; + } + + private String buildNullable(TableColumn column, XUGUDBColumnTypeEnum type) { + if (!type.getColumnType().isSupportNullable()) { + return ""; + } + if (column.getNullable() != null && 1 == column.getNullable()) { + return "NULL"; + } else { + return "NOT NULL"; + } + } + + private String buildDefaultValue(TableColumn column, XUGUDBColumnTypeEnum 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"); + } + + return StringUtils.join("DEFAULT ", column.getDefaultValue()); + } + + private String buildDataType(TableColumn column, XUGUDBColumnTypeEnum type) { + String columnType = type.columnType.getTypeName(); + if (Arrays.asList(CHAR, VARCHAR, VARCHAR2, LONGVARCHAR,TEXT).contains(type)) { + StringBuilder script = new StringBuilder(); + script.append(columnType); + if (column.getColumnSize() != null && StringUtils.isEmpty(column.getUnit())) { + script.append("(").append(column.getColumnSize()).append(")"); + } else if (column.getColumnSize() != null && !StringUtils.isEmpty(column.getUnit())) { + script.append("(").append(column.getColumnSize()).append(" ").append(column.getUnit()).append(")"); + } + return script.toString(); + } + + if (Arrays.asList(DECIMAL,DEC, FLOAT, NUMBER, TIMESTAMP, NUMBERIC).contains(type)) { + StringBuilder script = new StringBuilder(); + script.append(columnType); + if (column.getColumnSize() != null && column.getDecimalDigits() == null) { + script.append("(").append(column.getColumnSize()).append(")"); + } else if (column.getColumnSize() != null && column.getDecimalDigits() != null) { + script.append("(").append(column.getColumnSize()).append(",").append(column.getDecimalDigits()).append(")"); + } + return script.toString(); + } + + if (Arrays.asList(TIMESTAMP_WITH_TIME_ZONE).contains(type)) { + StringBuilder script = new StringBuilder(); + if (column.getColumnSize() == null) { + script.append(columnType); + } else { + String[] split = columnType.split("TIMESTAMP"); + script.append("TIMESTAMP").append("(").append(column.getColumnSize()).append(")").append(split[1]); + } + return script.toString(); + } + + if (Arrays.asList(INTERVAL_DAY_TO_HOUR, + INTERVAL_DAY_TO_MINUTE, INTERVAL_DAY_TO_SECOND, + INTERVAL_HOUR_TO_MINUTE, + INTERVAL_HOUR_TO_SECOND, + INTERVAL_MINUTE_TO_SECOND, + INTERVAL_YEAR_TO_MONTH).contains(type)) { + StringBuilder script = new StringBuilder(); + if (column.getColumnSize() == null) { + script.append(columnType); + } else { + String[] split = columnType.split(" "); + if (split.length == 4) { + script.append(split[0]).append(" ").append(split[1]).append(" (").append(column.getColumnSize()).append(") ").append(split[2]).append(" ").append(split[3]); + } + } + return script.toString(); + } + + return columnType; + } + + + @Override + public String buildModifyColumn(TableColumn tableColumn) { + + if (EditStatus.DELETE.name().equals(tableColumn.getEditStatus())) { + StringBuilder script = new StringBuilder(); + script.append("ALTER TABLE ").append("\"").append(tableColumn.getSchemaName()).append("\".\"").append(tableColumn.getTableName()).append("\""); + script.append(" ").append("DROP COLUMN ").append("\"").append(tableColumn.getName()).append("\""); + return script.toString(); + } + if (EditStatus.ADD.name().equals(tableColumn.getEditStatus())) { + StringBuilder script = new StringBuilder(); + script.append("ALTER TABLE ").append("\"").append(tableColumn.getSchemaName()).append("\".\"").append(tableColumn.getTableName()).append("\""); + script.append(" ").append("ADD (").append(buildCreateColumnSql(tableColumn)).append(")"); + return script.toString(); + } + if (EditStatus.MODIFY.name().equals(tableColumn.getEditStatus())) { + StringBuilder script = new StringBuilder(); + script.append("ALTER TABLE ").append("\"").append(tableColumn.getSchemaName()).append("\".\"").append(tableColumn.getTableName()).append("\""); + script.append(" ").append("MODIFY (").append(buildCreateColumnSql(tableColumn)).append(") \n"); + + if (!StringUtils.equalsIgnoreCase(tableColumn.getOldName(), tableColumn.getName())) { + script.append(";"); + script.append("ALTER TABLE ").append("\"").append(tableColumn.getSchemaName()).append("\".\"").append(tableColumn.getTableName()).append("\""); + script.append(" ").append("RENAME COLUMN ").append("\"").append(tableColumn.getOldName()).append("\"").append(" TO ").append("\"").append(tableColumn.getName()).append("\""); + + } + return script.toString(); + + } + return ""; + } + + public static List getTypes() { + return Arrays.stream(XUGUDBColumnTypeEnum.values()).map(columnTypeEnum -> + columnTypeEnum.getColumnType() + ).toList(); + } +} diff --git a/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/type/XUGUDBDefaultValueEnum.java b/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/type/XUGUDBDefaultValueEnum.java new file mode 100644 index 000000000..e9833922d --- /dev/null +++ b/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/type/XUGUDBDefaultValueEnum.java @@ -0,0 +1,27 @@ +package ai.chat2db.plugin.xugudb.type; + +import ai.chat2db.spi.model.DefaultValue; + +import java.util.Arrays; +import java.util.List; + +public enum XUGUDBDefaultValueEnum { + EMPTY_STRING("EMPTY_STRING"), + NULL("NULL"), + ; + private DefaultValue defaultValue; + + XUGUDBDefaultValueEnum(String defaultValue) { + this.defaultValue = new DefaultValue(defaultValue); + } + + + public DefaultValue getDefaultValue() { + return defaultValue; + } + + public static List getDefaultValues() { + return Arrays.stream(XUGUDBDefaultValueEnum.values()).map(XUGUDBDefaultValueEnum::getDefaultValue).collect(java.util.stream.Collectors.toList()); + } + +} diff --git a/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/type/XUGUDBIndexTypeEnum.java b/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/type/XUGUDBIndexTypeEnum.java new file mode 100644 index 000000000..c2917dfc6 --- /dev/null +++ b/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/type/XUGUDBIndexTypeEnum.java @@ -0,0 +1,129 @@ +package ai.chat2db.plugin.xugudb.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 org.apache.commons.lang3.StringUtils; + +import java.util.Arrays; +import java.util.List; + +public enum XUGUDBIndexTypeEnum { + + PRIMARY_KEY("Primary", "PRIMARY KEY"), + + NORMAL("Normal", "INDEX"), + + UNIQUE("Unique", "UNIQUE INDEX"), + + BITMAP("BITMAP", "BITMAP INDEX"); + + + + public IndexType getIndexType() { + return indexType; + } + + public void setIndexType(IndexType indexType) { + this.indexType = indexType; + } + + private IndexType indexType; + + + public String getName() { + return name; + } + + private String name; + + + public String getKeyword() { + return keyword; + } + + private String keyword; + + XUGUDBIndexTypeEnum(String name, String keyword) { + this.name = name; + this.keyword = keyword; + this.indexType = new IndexType(name); + } + + + public static XUGUDBIndexTypeEnum getByType(String type) { + for (XUGUDBIndexTypeEnum value : XUGUDBIndexTypeEnum.values()) { + if (value.name.equalsIgnoreCase(type)) { + return value; + } + } + return null; + } + + public String buildIndexScript(TableIndex tableIndex) { + StringBuilder script = new StringBuilder(); + if (PRIMARY_KEY.equals(this)) { + script.append("ALTER TABLE \"").append(tableIndex.getSchemaName()).append("\".\"").append(tableIndex.getTableName()).append("\" ADD PRIMARY KEY ").append(buildIndexColumn(tableIndex)); + } else { + if (UNIQUE.equals(this)) { + script.append("CREATE UNIQUE INDEX "); + } else { + script.append("CREATE INDEX "); + } + script.append(buildIndexName(tableIndex)).append(" ON \"").append(tableIndex.getSchemaName()).append("\".\"").append(tableIndex.getTableName()).append("\" ").append(buildIndexColumn(tableIndex)); + } + return script.toString(); + } + + + 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("\""); + if (!StringUtils.isBlank(column.getAscOrDesc()) && !PRIMARY_KEY.equals(this)) { + script.append(" ").append(column.getAscOrDesc()); + } + script.append(","); + } + } + script.deleteCharAt(script.length() - 1); + script.append(")"); + return script.toString(); + } + + private String buildIndexName(TableIndex tableIndex) { + return "\"" + tableIndex.getSchemaName() + "\"." + "\"" + tableIndex.getName() + "\""; + } + + public String buildModifyIndex(TableIndex tableIndex) { + if (EditStatus.DELETE.name().equals(tableIndex.getEditStatus())) { + return buildDropIndex(tableIndex); + } + if (EditStatus.MODIFY.name().equals(tableIndex.getEditStatus())) { + return StringUtils.join(buildDropIndex(tableIndex), ";\n", buildIndexScript(tableIndex)); + } + if (EditStatus.ADD.name().equals(tableIndex.getEditStatus())) { + return StringUtils.join(buildIndexScript(tableIndex)); + } + return ""; + } + + private String buildDropIndex(TableIndex tableIndex) { + if (XUGUDBIndexTypeEnum.PRIMARY_KEY.getName().equals(tableIndex.getType())) { + String tableName = "\"" + tableIndex.getSchemaName() + "\"." + "\"" + tableIndex.getTableName() + "\""; + return StringUtils.join("ALTER TABLE ",tableName," DROP PRIMARY KEY"); + } + StringBuilder script = new StringBuilder(); + script.append("DROP INDEX "); + script.append(buildIndexName(tableIndex)); + + return script.toString(); + } + + public static List getIndexTypes() { + return Arrays.asList(XUGUDBIndexTypeEnum.values()).stream().map(XUGUDBIndexTypeEnum::getIndexType).collect(java.util.stream.Collectors.toList()); + } +} diff --git a/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/xugudb.json b/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/xugudb.json new file mode 100644 index 000000000..befbdecbc --- /dev/null +++ b/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/xugudb.json @@ -0,0 +1,18 @@ +{ + "dbType": "XUGUDB", + "supportDatabase": false, + "supportSchema": true, + "driverConfigList": [ + { + "url": "jdbc:xugu://localhost:5138/", + "defaultDriver": true, + "custom": false, + "downloadJdbcDriverUrls": [ + "https://cdn.chat2db-ai.com/lib/DmJdbcDriver18-8.1.2.141.jar" + ], + "jdbcDriver": "xugu-jdbc-12.1.12.jar", + "jdbcDriverClass": "com.xugu.cloudjdbc.Driver" + } + ], + "name": "XUGUDB" +} diff --git a/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/resources/META-INF/services/ai.chat2db.spi.Plugin b/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/resources/META-INF/services/ai.chat2db.spi.Plugin new file mode 100644 index 000000000..1fbe331d5 --- /dev/null +++ b/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/resources/META-INF/services/ai.chat2db.spi.Plugin @@ -0,0 +1 @@ +ai.chat2db.plugin.xugudb.XUGUDBPlugin \ No newline at end of file diff --git a/chat2db-server/chat2db-plugins/pom.xml b/chat2db-server/chat2db-plugins/pom.xml index 17be8e0e8..f0c4babb9 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-xugudb \ No newline at end of file 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 47a86c68a..64fc263f2 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,5 +121,10 @@ chat2db-sqlserver ${revision} + + ai.chat2db + chat2db-xugudb + ${revision} + From 728e6f1f0adb1d765cc58291ab2072f3e2044415 Mon Sep 17 00:00:00 2001 From: tmlx1990 Date: Tue, 14 May 2024 23:32:00 +0800 Subject: [PATCH 3/5] =?UTF-8?q?xugudb=E4=BF=AE=E6=94=B9=E6=94=AF=E6=8C=81?= =?UTF-8?q?=E7=9A=84=E6=95=B0=E6=8D=AE=E7=B1=BB=E5=9E=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../xugudb/type/XUGUDBColumnTypeEnum.java | 103 ++++++------------ 1 file changed, 33 insertions(+), 70 deletions(-) diff --git a/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/type/XUGUDBColumnTypeEnum.java b/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/type/XUGUDBColumnTypeEnum.java index 41f76f754..aa9ca6901 100644 --- a/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/type/XUGUDBColumnTypeEnum.java +++ b/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/type/XUGUDBColumnTypeEnum.java @@ -13,116 +13,79 @@ public enum XUGUDBColumnTypeEnum implements ColumnBuilder { - - BFILE("BFILE", false, false, true, false, false, false, true, true, false, false), + TINYINT("TINYINT", false, false, true, false, false, false, true, true, false, false), BIGINT("BIGINT", false, false, true, false, false, false, true, true, false, false), + SMALLINT("SMALLINT", false, false, true, false, false, false, true, true, false, false), - BINARY("BINARY", false, false, true, false, false, false, true, true, false, false), - - - BIT("BIT", false, false, true, false, false, false, true, true, false, false), + INTEGER("INTEGER", false, false, true, false, false, false, true, true, false, false), + NUMERIC("NUMERIC", true, true, true, false, false, false, true, true, false, false), - BLOB("BLOB", false, false, true, false, false, false, true, true, false, false), + FLOAT("FLOAT", true, false, true, false, false, false, true, true, false, false), + DOUBLE("DOUBLE", false, false, true, false, false, false, true, true, false, false), CHAR("CHAR", true, false, true, false, false, false, true, true, false, true), -// CHAR_VARYING("CHAR VARYING", true, false, true, false, false, false, true, true, false, true), -// -// CHARACTER("CHARACTER", true, false, true, false, false, false, true, true, false, true), -// -// CHARACTER_VARYING("CHARACTER VARYING", true, false, true, false, false, false, true, true, false, true), + NCHAR("NCHAR", true, false, true, false, false, false, true, true, false, true), - CLOB("CLOB", false, false, true, false, false, false, true, true, false, false), - - DATE("DATE", false, false, true, false, false, false, true, true, false, false), + VARCHAR("VARCHAR", true, false, true, false, false, false, true, true, false, true), - DECIMAL("DECIMAL", true, true, true, false, false, false, true, true, false, false), - DEC("DEC", true, true, true, false, false, false, true, true, false, false), + VARCHAR2("VARCHAR2", true, false, true, false, false, false, true, true, false, true), - DOUBLE("DOUBLE", false, false, true, false, false, false, true, true, false, false), + DATE("DATE", false, false, true, false, false, false, true, true, false, false), + TIME("TIME", false, false, true, false, false, false, true, true, false, false), - FLOAT("FLOAT", true, false, true, false, false, false, true, true, false, false), + TIME_WITH_TIME_ZONE("TIME WITH TIME ZONE", false, false, true, false, false, false, true, true, false, false), - INT("INT", false, false, true, true, false, false, true, true, false, false), + DATETIME("DATETIME", false, false, true, false, false, false, true, true, false, false), - // INTEGER("INTEGER", false, false, true, false, false, false, true, true, false, false), + DATETIME_WITH_TIME_ZONE("DATETIME WITH TIME ZONE", false, false, true, false, false, false, true, true, false, false), - INTERVAL_DAY("INTERVAL DAY", false, false, true, false, false, false, true, true, false, false), + TIMESTAMP("TIMESTAMP", false, false, true, false, false, false, true, true, false, false), - INTERVAL_DAY_TO_HOUR("INTERVAL DAY TO HOUR", true, false, true, false, false, false, true, true, false, false), + TIMESTAMP_WITH_TIME_ZONE("TIMESTAMP WITH TIME ZONE", false, false, true, false, false, false, true, true, false, false), + INTERVAL_YEAR("INTERVAL YEAR", false, false, true, false, false, false, true, true, false, false), - INTERVAL_DAY_TO_MINUTE("INTERVAL DAY TO MINUTE", true, false, true, false, false, false, true, true, false, false), + INTERVAL_MONTH("INTERVAL MONTH", false, false, true, false, false, false, true, true, false, false), - INTERVAL_DAY_TO_SECOND("INTERVAL DAY TO SECOND", true, false, true, false, false, false, true, true, false, false), + INTERVAL_DAY("INTERVAL DAY", false, false, true, false, false, false, true, true, false, false), INTERVAL_HOUR("INTERVAL HOUR", false, false, true, false, false, false, true, true, false, false), - INTERVAL_HOUR_TO_MINUTE("INTERVAL HOUR TO MINUTE", true, false, true, false, false, false, true, true, false, false), - - INTERVAL_HOUR_TO_SECOND("INTERVAL HOUR TO SECOND", true, false, true, false, false, false, true, true, false, false), - INTERVAL_MINUTE("INTERVAL MINUTE", false, false, true, false, false, false, true, true, false, false), - INTERVAL_MINUTE_TO_SECOND("INTERVAL MINUTE TO SECOND", true, false, true, false, false, false, true, true, false, false), - - - INTERVAL_MONTH("INTERVAL MONTH", false, false, true, false, false, false, true, true, false, false), - INTERVAL_SECOND("INTERVAL SECOND", false, false, true, false, false, false, true, true, false, false), - - INTERVAL_YEAR("INTERVAL YEAR", false, false, true, false, false, false, true, true, false, false), - - INTERVAL_YEAR_TO_MONTH("INTERVAL YEAR TO MONTH", true, false, true, false, false, false, true, true, false, false), - LONGVARBINARY("LONGVARBINARY", false, false, true, false, false, false, true, true, false, false), - - - LONGVARCHAR("LONGVARCHAR", false, false, true, false, false, false, true, true, false, false), - TEXT("TEXT", false, false, true, false, false, false, true, true, false, false), - - - NUMBERIC("NUMBERIC", true, true, true, false, false, false, true, true, false, false), - - - NUMBER("NUMBER", true, true, true, false, false, false, true, true, false, false), - - REAL("REAL", false, false, true, false, false, false, true, true, false, false), - - - SMALLINT("SMALLINT", false, false, true, false, false, false, true, true, false, false), - - - TIME("TIME", false, false, true, false, false, false, true, true, false, false), - - - TIME_WITH_TIME_ZONE("TIME WITH TIME ZONE", false, false, true, false, false, false, true, true, false, false), - - - TIMESTAMP("TIMESTAMP", false, false, true, false, false, false, true, true, false, false), + INTERVAL_DAY_TO_HOUR("INTERVAL DAY TO HOUR", true, false, true, false, false, false, true, true, false, false), + INTERVAL_DAY_TO_MINUTE("INTERVAL DAY TO MINUTE", true, false, true, false, false, false, true, true, false, false), - TIMESTAMP_WITH_TIME_ZONE("TIMESTAMP WITH TIME ZONE", false, false, true, false, false, false, true, true, false, false), + INTERVAL_DAY_TO_SECOND("INTERVAL DAY TO SECOND", true, false, true, false, false, false, true, true, false, false), + INTERVAL_HOUR_TO_MINUTE("INTERVAL HOUR TO MINUTE", true, false, true, false, false, false, true, true, false, false), - TINYINT("TINYINT", false, false, true, false, false, false, true, true, false, false), + INTERVAL_HOUR_TO_SECOND("INTERVAL HOUR TO SECOND", true, false, true, false, false, false, true, true, false, false), + INTERVAL_MINUTE_TO_SECOND("INTERVAL MINUTE TO SECOND", true, false, true, false, false, false, true, true, false, false), - VARBINARY("VARBINARY", false, false, true, false, false, false, true, true, false, false), + BLOB("BLOB", false, false, true, false, false, false, true, true, false, false), + CLOB("CLOB", false, false, true, false, false, false, true, true, false, false), - VARCHAR("VARCHAR", true, false, true, false, false, false, true, true, false, true), + BOOLEAN("BOOLEAN", false, false, true, false, false, false, true, true, false, false), + BINARY("BINARY", false, false, true, false, false, false, true, true, false, false), - VARCHAR2("VARCHAR2", true, false, true, false, false, false, true, true, false, true), + OBJECT("OBJECT", false, false, true, false, false, false, true, true, false, false), + VARRAY("VARRAY", false, false, true, false, false, false, true, true, false, false), ; private ColumnType columnType; @@ -211,7 +174,7 @@ private String buildDefaultValue(TableColumn column, XUGUDBColumnTypeEnum type) private String buildDataType(TableColumn column, XUGUDBColumnTypeEnum type) { String columnType = type.columnType.getTypeName(); - if (Arrays.asList(CHAR, VARCHAR, VARCHAR2, LONGVARCHAR,TEXT).contains(type)) { + if (Arrays.asList(CHAR, VARCHAR, VARCHAR2).contains(type)) { StringBuilder script = new StringBuilder(); script.append(columnType); if (column.getColumnSize() != null && StringUtils.isEmpty(column.getUnit())) { @@ -222,7 +185,7 @@ private String buildDataType(TableColumn column, XUGUDBColumnTypeEnum type) { return script.toString(); } - if (Arrays.asList(DECIMAL,DEC, FLOAT, NUMBER, TIMESTAMP, NUMBERIC).contains(type)) { + if (Arrays.asList(FLOAT, TIMESTAMP).contains(type)) { StringBuilder script = new StringBuilder(); script.append(columnType); if (column.getColumnSize() != null && column.getDecimalDigits() == null) { From 48c08208b7421a5d59bc3937a1285da6b5d77aff Mon Sep 17 00:00:00 2001 From: tmlx1990 Date: Fri, 7 Jun 2024 17:41:02 +0800 Subject: [PATCH 4/5] xugudb add table ddl --- .../chat2db/plugin/xugudb/XUGUDBManage.java | 9 +- .../chat2db/plugin/xugudb/XUGUDBMetaData.java | 136 ++++++++++++------ .../xugudb/type/XUGUDBIndexTypeEnum.java | 2 +- .../java/ai/chat2db/plugin/xugudb/xugudb.json | 4 +- 4 files changed, 99 insertions(+), 52 deletions(-) diff --git a/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/XUGUDBManage.java b/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/XUGUDBManage.java index 1934cdf69..6a2e973aa 100644 --- a/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/XUGUDBManage.java +++ b/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/XUGUDBManage.java @@ -21,6 +21,7 @@ private String format(String tableName) { private static String TRIGGER_SQL = "SELECT OWNER, TRIGGER_NAME, TABLE_OWNER, TABLE_NAME, TRIGGERING_TYPE, TRIGGERING_EVENT, STATUS, TRIGGER_BODY " + "FROM ALL_TRIGGERS WHERE OWNER = '%s' AND TRIGGER_NAME = '%s'"; + @Override public String exportDatabase(Connection connection, String databaseName, String schemaName, boolean containData) throws SQLException { StringBuilder sqlBuilder = new StringBuilder(); @@ -140,15 +141,13 @@ private void exportTrigger(Connection connection, String schemaName, String trig @Override public void connectDatabase(Connection connection, String database) { - ConnectInfo connectInfo = Chat2DBContext.getConnectInfo(); - if (ObjectUtils.anyNull(connectInfo) || StringUtils.isEmpty(connectInfo.getSchemaName())) { + if (org.springframework.util.StringUtils.isEmpty(database)) { return; } - String schemaName = connectInfo.getSchemaName(); try { - SQLExecutor.getInstance().execute(connection, "SET SCHEMA \"" + schemaName + "\""); + SQLExecutor.getInstance().execute(connection,"use " + database ); } catch (SQLException e) { - e.printStackTrace(); + throw new RuntimeException(e); } } diff --git a/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/XUGUDBMetaData.java b/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/XUGUDBMetaData.java index c76d8b81f..77d9b7f80 100644 --- a/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/XUGUDBMetaData.java +++ b/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/XUGUDBMetaData.java @@ -8,6 +8,7 @@ import ai.chat2db.spi.SqlBuilder; import ai.chat2db.spi.jdbc.DefaultMetaService; import ai.chat2db.spi.model.*; +import ai.chat2db.spi.sql.Chat2DBContext; import ai.chat2db.spi.sql.SQLExecutor; import ai.chat2db.spi.util.SortUtils; import com.google.common.collect.Lists; @@ -20,7 +21,15 @@ import java.util.*; import java.util.stream.Collectors; +import static ai.chat2db.spi.util.SortUtils.sortDatabase; + public class XUGUDBMetaData extends DefaultMetaService implements MetaData { + private List systemDatabases = Arrays.asList("information_schema", "performance_schema", "sys"); + @Override + public List databases(Connection connection) { + List databases = SQLExecutor.getInstance().databases(connection); + return sortDatabase(databases, systemDatabases, connection); + } private List systemSchemas = Arrays.asList("CTISYS", "SYS","SYSDBA","SYSSSO","SYSAUDITOR"); @@ -33,35 +42,21 @@ private String format(String tableName){ return "\"" + tableName + "\""; } + @Override public String tableDDL(Connection connection, String databaseName, String schemaName, String tableName) { String sql = """ SELECT - (SELECT comments FROM user_tab_comments WHERE table_name = '%s') AS comments, - (SELECT dbms_metadata.get_ddl('TABLE', '%s', '%s') FROM dual) AS ddl + (SELECT dbms_metadata.get_ddl('%s.%s') FROM dual) AS ddl FROM dual; """; StringBuilder ddlBuilder = new StringBuilder(); - String tableDDLSql = String.format(sql, tableName, tableName, schemaName); + String tableDDLSql = String.format(sql, schemaName, tableName); SQLExecutor.getInstance().execute(connection, tableDDLSql, resultSet -> { if (resultSet.next()) { String ddl = resultSet.getString("ddl"); - String comment = resultSet.getString("comments"); - if (StringUtils.isNotBlank(comment)) { - ddlBuilder.append(ddl).append("\n").append("COMMENT ON TABLE ").append(format(schemaName)) - .append(".").append(format(tableName)).append(" IS ").append("'").append(comment).append("';"); - } + ddlBuilder.append(ddl).append("\n"); } }); - String columnCommentsSql =String.format("select COLNAME,COMMENT$ from SYS.SYSCOLUMNCOMMENTS\n" + - "where SCHNAME = '%s' and TVNAME = '%s'and TABLE_TYPE = 'TABLE';", schemaName,tableName); - SQLExecutor.getInstance().execute(connection, columnCommentsSql, resultSet->{ - while (resultSet.next()) { - String columnName = resultSet.getString("COLNAME"); - String comment = resultSet.getString("COMMENT$"); - ddlBuilder.append("COMMENT ON COLUMN ").append(format(schemaName)).append(".").append(format(tableName)) - .append(".").append(format(columnName)).append(" IS ").append("'").append(comment).append("';").append("\n"); - } - }); return ddlBuilder.toString(); } @@ -146,6 +141,25 @@ public Trigger trigger(Connection connection, @NotEmpty String databaseName, Str }); } + private static String VIEW_SQL_LIST = "SELECT DB.DB_NAME, CH.SCHEMA_NAME, v.VIEW_NAME, v.DEFINE, v.OPTION,v.VALID, v.IS_SYS, v.COMMENTS FROM all_views v LEFT JOIN DBA_DATABASES DB ON v.DB_ID = DB.DB_ID LEFT JOIN DBA_SCHEMAS CH ON v.SCHEMA_ID = CH.SCHEMA_ID where DB.DB_NAME = '%s' and CH.SCHEMA_NAME = '%s'"; + @Override + public List views(Connection connection, String databaseName, String schemaName) { + String sql = String.format(VIEW_SQL_LIST, databaseName, schemaName); + List
tables = new ArrayList<>(); + return SQLExecutor.getInstance().execute(connection, sql, resultSet -> { + Table table = new Table(); + table.setDatabaseName(databaseName); + table.setSchemaName(schemaName); + while (resultSet.next()) { + table.setName(resultSet.getString("VIEW_NAME")); + table.setDdl(resultSet.getString("DEFINE")); + tables.add(table); + } + return tables; + }); + + } + private static String VIEW_SQL = "SELECT OWNER, VIEW_NAME, TEXT FROM ALL_VIEWS WHERE OWNER = '%s' AND VIEW_NAME = '%s'"; @@ -164,7 +178,9 @@ public Table view(Connection connection, String databaseName, String schemaName, }); } - private static String INDEX_SQL = "SELECT i.TABLE_NAME, i.INDEX_TYPE, i.INDEX_NAME, i.UNIQUENESS ,c.COLUMN_NAME, c.COLUMN_POSITION, c.DESCEND, cons.CONSTRAINT_TYPE FROM ALL_INDEXES i JOIN ALL_IND_COLUMNS c ON i.INDEX_NAME = c.INDEX_NAME AND i.TABLE_NAME = c.TABLE_NAME AND i.TABLE_OWNER = c.TABLE_OWNER LEFT JOIN ALL_CONSTRAINTS cons ON i.INDEX_NAME = cons.INDEX_NAME AND i.TABLE_NAME = cons.TABLE_NAME AND i.TABLE_OWNER = cons.OWNER WHERE i.TABLE_OWNER = '%s' AND i.TABLE_NAME = '%s' ORDER BY i.INDEX_NAME, c.COLUMN_POSITION;"; + private static String INDEX_SQL = "SELECT i.INDEX_NAME, CASE i.INDEX_TYPE WHEN 0 THEN 'BTREE' WHEN 1 THEN 'RTREE' WHEN 2 THEN 'FULLTEXT' WHEN 3 THEN 'BITMAP' WHEN 4 THEN 'UNION' END AS INDEX_TYPE, i.IS_PRIMARY," + + " i.IS_UNIQUE, i.FIELD_NUM, REPLACE (KEYS, '\"', '') AS KEYS FROM ALL_INDEXES i LEFT JOIN ALL_TABLES T ON i.TABLE_ID = T.TABLE_ID LEFT JOIN ALL_SCHEMAS CH ON CH.USER_ID = T.USER_ID AND CH.DB_ID = i.DB_ID" + + " where CH.SCHEMA_NAME = '%s' and T.TABLE_NAME = '%s'"; @Override public List indexes(Connection connection, String databaseName, String schemaName, String tableName) { @@ -175,29 +191,23 @@ public List indexes(Connection connection, String databaseName, Stri String keyName = resultSet.getString("INDEX_NAME"); TableIndex tableIndex = map.get(keyName); if (tableIndex != null) { - List columnList = tableIndex.getColumnList(); - columnList.add(getTableIndexColumn(resultSet)); - columnList = columnList.stream().sorted(Comparator.comparing(TableIndexColumn::getOrdinalPosition)) - .collect(Collectors.toList()); - tableIndex.setColumnList(columnList); + tableIndex.setColumnList(getTableIndexColumn(resultSet)); } else { TableIndex index = new TableIndex(); index.setDatabaseName(databaseName); index.setSchemaName(schemaName); index.setTableName(tableName); index.setName(keyName); - index.setUnique("UNIQUE".equalsIgnoreCase(resultSet.getString("UNIQUENESS"))); + index.setUnique((resultSet.getBoolean("IS_UNIQUE"))); // index.setType(resultSet.getString("Index_type")); // index.setComment(resultSet.getString("Index_comment")); - List tableIndexColumns = new ArrayList<>(); - tableIndexColumns.add(getTableIndexColumn(resultSet)); - index.setColumnList(tableIndexColumns); - if ("P".equalsIgnoreCase(resultSet.getString("CONSTRAINT_TYPE"))) { + index.setColumnList(getTableIndexColumn(resultSet)); + if (resultSet.getBoolean("IS_PRIMARY")) { index.setType(XUGUDBIndexTypeEnum.PRIMARY_KEY.getName()); } else if (index.getUnique()) { index.setType(XUGUDBIndexTypeEnum.UNIQUE.getName()); - } else if ("BITMAP".equalsIgnoreCase(resultSet.getString("INDEX_TYPE"))) { - index.setType(XUGUDBIndexTypeEnum.BITMAP.getName()); + } else if ("BTREE".equalsIgnoreCase(resultSet.getString("INDEX_TYPE"))) { + index.setType(XUGUDBIndexTypeEnum.BTREE.getName()); } else { index.setType(XUGUDBIndexTypeEnum.NORMAL.getName()); } @@ -209,20 +219,58 @@ public List indexes(Connection connection, String databaseName, Stri } - private TableIndexColumn getTableIndexColumn(ResultSet resultSet) throws SQLException { - TableIndexColumn tableIndexColumn = new TableIndexColumn(); - tableIndexColumn.setColumnName(resultSet.getString("COLUMN_NAME")); - tableIndexColumn.setOrdinalPosition(resultSet.getShort("COLUMN_POSITION")); -// tableIndexColumn.setCollation(resultSet.getString("Collation")); -// tableIndexColumn.setCardinality(resultSet.getLong("Cardinality")); -// tableIndexColumn.setSubPart(resultSet.getLong("Sub_part")); - String collation = resultSet.getString("DESCEND"); - if ("ASC".equalsIgnoreCase(collation)) { - tableIndexColumn.setAscOrDesc("ASC"); - } else if ("DESC".equalsIgnoreCase(collation)) { - tableIndexColumn.setAscOrDesc("DESC"); + private List getTableIndexColumn(ResultSet resultSet) throws SQLException { + List tableIndexColumnList = new ArrayList<>(); + String[] keys = resultSet.getString("KEYS").split(","); + for (String key : keys) { + TableIndexColumn tableIndexColumn = new TableIndexColumn(); + tableIndexColumn.setColumnName(key); + // TODO 先临时赋值0 + tableIndexColumn.setOrdinalPosition((short) 0); + tableIndexColumnList.add(tableIndexColumn); } - return tableIndexColumn; + return tableIndexColumnList; + } + + private static String SELECT_TABLE_COLUMNS = "select c.* from ALL_COLUMNS c LEFT JOIN ALL_TABLES T ON c.TABLE_ID = T.TABLE_ID LEFT JOIN ALL_SCHEMAS CH ON CH.USER_ID = T.USER_ID AND CH.DB_ID = c.DB_ID where CH.SCHEMA_NAME = '%s' and T.TABLE_NAME = '%s' order by c.COL_NO"; + + @Override + public List columns(Connection connection, String databaseName, String schemaName, String tableName) { + String sql = String.format(SELECT_TABLE_COLUMNS, schemaName, tableName); + 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("COL_NAME")); + column.setName(resultSet.getString("COL_NAME")); + //column.setColumnType(resultSet.getString("COLUMN_TYPE")); + if (resultSet.getBoolean("VARYING")) { + if (resultSet.getString("TYPE_NAME").toUpperCase().equals(XUGUDBColumnTypeEnum.CHAR.name())) { + column.setColumnType("VAR"+resultSet.getString("TYPE_NAME").toUpperCase()); + } else { + column.setColumnType(resultSet.getString("TYPE_NAME").toUpperCase()); + } + } else { + column.setColumnType(resultSet.getString("TYPE_NAME").toUpperCase()); + } + + //column.setDataType(resultSet.getInt("DATA_TYPE")); + column.setDefaultValue(resultSet.getString("DEF_VAL")); + //column.setAutoIncrement(resultSet.getString("EXTRA").contains("auto_increment")); + column.setComment(resultSet.getString("COMMENTS")); + // column.setPrimaryKey("PRI".equalsIgnoreCase(resultSet.getString("COLUMN_KEY"))); + column.setNullable(resultSet.getBoolean("NOT_NULL") ? 1 : 0); + column.setOrdinalPosition(resultSet.getInt("SCALE")); + // column.setDecimalDigits(resultSet.getInt("NUMERIC_SCALE")); + //column.setCharSetName(resultSet.getString("CHARACTER_SET_NAME")); + // column.setCollationName(resultSet.getString("COLLATION_NAME")); + column.setColumnSize(resultSet.getInt("SCALE") == -1 ? null : resultSet.getInt("SCALE")); + tableColumns.add(column); + } + return tableColumns; + }); } @Override diff --git a/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/type/XUGUDBIndexTypeEnum.java b/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/type/XUGUDBIndexTypeEnum.java index c2917dfc6..e57bf1e32 100644 --- a/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/type/XUGUDBIndexTypeEnum.java +++ b/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/type/XUGUDBIndexTypeEnum.java @@ -17,7 +17,7 @@ public enum XUGUDBIndexTypeEnum { UNIQUE("Unique", "UNIQUE INDEX"), - BITMAP("BITMAP", "BITMAP INDEX"); + BTREE("BTREE", "btree"); diff --git a/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/xugudb.json b/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/xugudb.json index befbdecbc..b69036f09 100644 --- a/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/xugudb.json +++ b/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/xugudb.json @@ -1,6 +1,6 @@ { "dbType": "XUGUDB", - "supportDatabase": false, + "supportDatabase": true, "supportSchema": true, "driverConfigList": [ { @@ -8,7 +8,7 @@ "defaultDriver": true, "custom": false, "downloadJdbcDriverUrls": [ - "https://cdn.chat2db-ai.com/lib/DmJdbcDriver18-8.1.2.141.jar" + "https://cdn.chat2db-ai.com/lib/xugu-jdbc-12.1.12.jar" ], "jdbcDriver": "xugu-jdbc-12.1.12.jar", "jdbcDriverClass": "com.xugu.cloudjdbc.Driver" From 5b84ea81257bb130e4400be9aef9a1bb934eec1f Mon Sep 17 00:00:00 2001 From: tmlx1990 Date: Fri, 14 Jun 2024 17:00:03 +0800 Subject: [PATCH 5/5] =?UTF-8?q?xugudb=E4=BF=AE=E6=94=B9=E8=A1=A8=E3=80=81v?= =?UTF-8?q?iew=E3=80=81functions=E3=80=81procedures=E3=80=81triggers?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E6=8F=90=E4=BA=A4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../chat2db/plugin/xugudb/XUGUDBManage.java | 63 +++++---- .../chat2db/plugin/xugudb/XUGUDBMetaData.java | 121 +++++++++++++----- .../xugudb/type/XUGUDBColumnTypeEnum.java | 61 +++++++-- 3 files changed, 170 insertions(+), 75 deletions(-) diff --git a/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/XUGUDBManage.java b/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/XUGUDBManage.java index 6a2e973aa..024d7e91b 100644 --- a/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/XUGUDBManage.java +++ b/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/XUGUDBManage.java @@ -1,7 +1,5 @@ package ai.chat2db.plugin.xugudb; -import java.sql.*; - import ai.chat2db.spi.DBManage; import ai.chat2db.spi.jdbc.DefaultDBManage; import ai.chat2db.spi.sql.Chat2DBContext; @@ -10,10 +8,16 @@ import org.apache.commons.lang3.ObjectUtils; import org.apache.commons.lang3.StringUtils; +import java.sql.Connection; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; + public class XUGUDBManage extends DefaultDBManage implements DBManage { private String format(String tableName) { return "\"" + tableName + "\""; } + private static String ROUTINES_SQL = "SELECT OWNER, NAME, TEXT FROM ALL_SOURCE WHERE TYPE = '%s' AND OWNER = '%s' AND NAME = '%s' ORDER BY LINE"; private static String TRIGGER_SQL_LIST = "SELECT OWNER, TRIGGER_NAME FROM ALL_TRIGGERS WHERE OWNER = '%s'"; @@ -28,12 +32,12 @@ public String exportDatabase(Connection connection, String databaseName, String exportTables(connection, sqlBuilder, schemaName, containData); exportViews(connection, schemaName, sqlBuilder); exportProcedures(connection, schemaName, sqlBuilder); - exportTriggers(connection,schemaName, sqlBuilder); + exportTriggers(connection, schemaName, sqlBuilder); return sqlBuilder.toString(); } private void exportTables(Connection connection, StringBuilder sqlBuilder, String schemaName, boolean containData) throws SQLException { - String sql =String.format("SELECT TABLE_NAME FROM ALL_TABLES where OWNER='%s' and TABLESPACE_NAME='MAIN'", schemaName); + String sql = String.format("SELECT TABLE_NAME FROM ALL_TABLES where OWNER='%s' and TABLESPACE_NAME='MAIN'", schemaName); try (ResultSet resultSet = connection.createStatement().executeQuery(sql)) { while (resultSet.next()) { String tableName = resultSet.getString("TABLE_NAME"); @@ -45,11 +49,11 @@ private void exportTables(Connection connection, StringBuilder sqlBuilder, Strin private void exportTable(Connection connection, String tableName, String schemaName, StringBuilder sqlBuilder, boolean containData) throws SQLException { String sql = """ - SELECT - (SELECT comments FROM user_tab_comments WHERE table_name = '%s') AS comments, - (SELECT dbms_metadata.get_ddl('TABLE', '%s', '%s') FROM dual) AS ddl - FROM dual; - """; + SELECT + (SELECT comments FROM user_tab_comments WHERE table_name = '%s') AS comments, + (SELECT dbms_metadata.get_ddl('TABLE', '%s', '%s') FROM dual) AS ddl + FROM dual; + """; try (Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery(String.format(sql, tableName, tableName, schemaName))) { String formatSchemaName = format(schemaName); String formatTableName = format(tableName); @@ -71,16 +75,16 @@ private void exportTable(Connection connection, String tableName, String schemaN } private void exportTableColumnComment(Connection connection, String schemaName, String tableName, StringBuilder sqlBuilder) throws SQLException { - String sql =String.format("select COLNAME,COMMENT$ from SYS.SYSCOLUMNCOMMENTS\n" + - "where SCHNAME = '%s' and TVNAME = '%s'and TABLE_TYPE = 'TABLE';", schemaName,tableName); - try(ResultSet resultSet = connection.createStatement().executeQuery(sql)) { - while (resultSet.next()) { - String columnName = resultSet.getString("COLNAME"); - String comment = resultSet.getString("COMMENT$"); - sqlBuilder.append("COMMENT ON COLUMN ").append(format(schemaName)).append(".").append(format(tableName)) - .append(".").append(format(columnName)).append(" IS ").append("'").append(comment).append("';").append("\n"); - } - } + String sql = String.format("select COLNAME,COMMENT$ from SYS.SYSCOLUMNCOMMENTS\n" + + "where SCHNAME = '%s' and TVNAME = '%s'and TABLE_TYPE = 'TABLE';", schemaName, tableName); + try (ResultSet resultSet = connection.createStatement().executeQuery(sql)) { + while (resultSet.next()) { + String columnName = resultSet.getString("COLNAME"); + String comment = resultSet.getString("COMMENT$"); + sqlBuilder.append("COMMENT ON COLUMN ").append(format(schemaName)).append(".").append(format(tableName)) + .append(".").append(format(columnName)).append(" IS ").append("'").append(comment).append("';").append("\n"); + } + } } @@ -106,13 +110,13 @@ private void exportProcedures(Connection connection, String schemaName, StringBu try (ResultSet resultSet = connection.getMetaData().getProcedures(null, schemaName, null)) { while (resultSet.next()) { String procedureName = resultSet.getString("PROCEDURE_NAME"); - exportProcedure(connection, schemaName,procedureName, sqlBuilder); + exportProcedure(connection, schemaName, procedureName, sqlBuilder); } } } private void exportProcedure(Connection connection, String schemaName, String procedureName, StringBuilder sqlBuilder) throws SQLException { - String sql = String.format(ROUTINES_SQL,"PROC", schemaName,procedureName); + String sql = String.format(ROUTINES_SQL, "PROC", schemaName, procedureName); try (Statement statement = connection.createStatement(); ResultSet resultSet = statement.executeQuery(sql)) { if (resultSet.next()) { sqlBuilder.append(resultSet.getString("TEXT")).append("\n"); @@ -121,17 +125,17 @@ private void exportProcedure(Connection connection, String schemaName, String pr } private void exportTriggers(Connection connection, String schemaName, StringBuilder sqlBuilder) throws SQLException { - String sql =String.format(TRIGGER_SQL_LIST, schemaName); + String sql = String.format(TRIGGER_SQL_LIST, schemaName); try (ResultSet resultSet = connection.createStatement().executeQuery(sql)) { while (resultSet.next()) { String triggerName = resultSet.getString("TRIGGER_NAME"); - exportTrigger(connection,schemaName, triggerName, sqlBuilder); + exportTrigger(connection, schemaName, triggerName, sqlBuilder); } } } private void exportTrigger(Connection connection, String schemaName, String triggerName, StringBuilder sqlBuilder) throws SQLException { - String sql = String.format(TRIGGER_SQL, schemaName,triggerName); + String sql = String.format(TRIGGER_SQL, schemaName, triggerName); try (ResultSet resultSet = connection.createStatement().executeQuery(sql)) { if (resultSet.next()) { sqlBuilder.append(resultSet.getString("TRIGGER_BODY")).append("\n"); @@ -139,13 +143,16 @@ private void exportTrigger(Connection connection, String schemaName, String trig } } + @Override public void connectDatabase(Connection connection, String database) { - if (org.springframework.util.StringUtils.isEmpty(database)) { + ConnectInfo connectInfo = Chat2DBContext.getConnectInfo(); + if (ObjectUtils.anyNull(connectInfo) || StringUtils.isEmpty(connectInfo.getSchemaName())) { return; } + String schemaName = connectInfo.getSchemaName(); try { - SQLExecutor.getInstance().execute(connection,"use " + database ); + SQLExecutor.getInstance().execute(connection, "SET SCHEMA TO " + schemaName); } catch (SQLException e) { throw new RuntimeException(e); } @@ -153,7 +160,7 @@ public void connectDatabase(Connection connection, String database) { @Override public void dropTable(Connection connection, String databaseName, String schemaName, String tableName) { - String sql = "DROP TABLE IF EXISTS " +tableName; - SQLExecutor.getInstance().execute(connection,sql, resultSet -> null); + String sql = "DROP TABLE IF EXISTS " + tableName; + SQLExecutor.getInstance().execute(connection, sql, resultSet -> null); } } diff --git a/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/XUGUDBMetaData.java b/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/XUGUDBMetaData.java index 77d9b7f80..d7d3f74c8 100644 --- a/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/XUGUDBMetaData.java +++ b/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/XUGUDBMetaData.java @@ -8,7 +8,6 @@ import ai.chat2db.spi.SqlBuilder; import ai.chat2db.spi.jdbc.DefaultMetaService; import ai.chat2db.spi.model.*; -import ai.chat2db.spi.sql.Chat2DBContext; import ai.chat2db.spi.sql.SQLExecutor; import ai.chat2db.spi.util.SortUtils; import com.google.common.collect.Lists; @@ -18,37 +17,42 @@ import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; -import java.util.*; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.LinkedHashMap; +import java.util.List; import java.util.stream.Collectors; import static ai.chat2db.spi.util.SortUtils.sortDatabase; public class XUGUDBMetaData extends DefaultMetaService implements MetaData { private List systemDatabases = Arrays.asList("information_schema", "performance_schema", "sys"); + @Override public List databases(Connection connection) { List databases = SQLExecutor.getInstance().databases(connection); return sortDatabase(databases, systemDatabases, connection); } - private List systemSchemas = Arrays.asList("CTISYS", "SYS","SYSDBA","SYSSSO","SYSAUDITOR"); + private List systemSchemas = Arrays.asList("CTISYS", "SYS", "SYSDBA", "SYSSSO", "SYSAUDITOR"); @Override public List schemas(Connection connection, String databaseName) { List schemas = SQLExecutor.getInstance().schemas(connection, databaseName, null); return SortUtils.sortSchema(schemas, systemSchemas); } - private String format(String tableName){ + + private String format(String tableName) { return "\"" + tableName + "\""; - } + } @Override public String tableDDL(Connection connection, String databaseName, String schemaName, String tableName) { String sql = """ - SELECT - (SELECT dbms_metadata.get_ddl('%s.%s') FROM dual) AS ddl - FROM dual; - """; + SELECT + (SELECT dbms_metadata.get_ddl('%s.%s') FROM dual) AS ddl + FROM dual; + """; StringBuilder ddlBuilder = new StringBuilder(); String tableDDLSql = String.format(sql, schemaName, tableName); SQLExecutor.getInstance().execute(connection, tableDDLSql, resultSet -> { @@ -60,18 +64,38 @@ public String tableDDL(Connection connection, String databaseName, String schema return ddlBuilder.toString(); } + private static String FUNCTIONS_SQL + = "select p.PROC_NAME From ALL_PROCEDURES p LEFT JOIN DBA_DATABASES DB ON p.DB_ID = DB.DB_ID LEFT JOIN DBA_SCHEMAS CH ON p.SCHEMA_ID = CH.SCHEMA_ID where DB.DB_NAME = '%s' and CH.SCHEMA_NAME = '%s' and p.RET_TYPE is not null "; + + + @Override + public List functions(Connection connection, String databaseName, String schemaName) { + List functions = new ArrayList<>(); + String sql = String.format(FUNCTIONS_SQL, databaseName, schemaName); + return SQLExecutor.getInstance().execute(connection, sql, resultSet -> { + while (resultSet.next()) { + Function function = new Function(); + function.setDatabaseName(databaseName); + function.setSchemaName(schemaName); + function.setFunctionName(resultSet.getString("PROC_NAME")); + functions.add(function); + } + return functions; + }); + } + private static String ROUTINES_SQL - = "SELECT OWNER, NAME, TEXT FROM ALL_SOURCE WHERE TYPE = '%s' AND OWNER = '%s' AND NAME = '%s' ORDER BY LINE"; + = "select DB.DB_NAME, CH.SCHEMA_NAME, p.PROC_NAME, p.DEFINE From ALL_PROCEDURES p LEFT JOIN DBA_DATABASES DB ON p.DB_ID = DB.DB_ID LEFT JOIN DBA_SCHEMAS CH ON p.SCHEMA_ID = CH.SCHEMA_ID where DB.DB_NAME = '%s' and CH.SCHEMA_NAME = '%s' and p.PROC_NAME = '%s' and p.RET_TYPE is not null "; @Override public Function function(Connection connection, @NotEmpty String databaseName, String schemaName, - String functionName) { + String functionName) { - String sql = String.format(ROUTINES_SQL, "PROC",schemaName, functionName); + String sql = String.format(ROUTINES_SQL, databaseName, schemaName, functionName); return SQLExecutor.getInstance().execute(connection, sql, resultSet -> { StringBuilder sb = new StringBuilder(); while (resultSet.next()) { - sb.append(resultSet.getString("TEXT") + "\n"); + sb.append(resultSet.getString("DEFINE") + "\n"); } Function function = new Function(); function.setDatabaseName(databaseName); @@ -84,14 +108,17 @@ public Function function(Connection connection, @NotEmpty String databaseName, S } + private static String PROCEDURE_SQL + = "select DB.DB_NAME, CH.SCHEMA_NAME, p.PROC_NAME, p.DEFINE From ALL_PROCEDURES p LEFT JOIN DBA_DATABASES DB ON p.DB_ID = DB.DB_ID LEFT JOIN DBA_SCHEMAS CH ON p.SCHEMA_ID = CH.SCHEMA_ID where DB.DB_NAME = '%s' and CH.SCHEMA_NAME = '%s' and p.PROC_NAME = '%s' and p.RET_TYPE is null "; + @Override public Procedure procedure(Connection connection, @NotEmpty String databaseName, String schemaName, - String procedureName) { - String sql = String.format(ROUTINES_SQL, "PROC", schemaName,procedureName); + String procedureName) { + String sql = String.format(PROCEDURE_SQL, databaseName, schemaName, procedureName); return SQLExecutor.getInstance().execute(connection, sql, resultSet -> { StringBuilder sb = new StringBuilder(); while (resultSet.next()) { - sb.append(resultSet.getString("TEXT") + "\n"); + sb.append(resultSet.getString("DEFINE") + "\n"); } Procedure procedure = new Procedure(); procedure.setDatabaseName(databaseName); @@ -102,20 +129,40 @@ public Procedure procedure(Connection connection, @NotEmpty String databaseName, }); } + private static String PROCEDURES_SQL + = "select p.PROC_NAME From ALL_PROCEDURES p LEFT JOIN DBA_DATABASES DB ON p.DB_ID = DB.DB_ID LEFT JOIN DBA_SCHEMAS CH ON p.SCHEMA_ID = CH.SCHEMA_ID where DB.DB_NAME = '%s' and CH.SCHEMA_NAME = '%s' and p.RET_TYPE is null "; + + + @Override + public List procedures(Connection connection, String databaseName, String schemaName) { + List procedures = new ArrayList<>(); + String sql = String.format(PROCEDURES_SQL, databaseName, schemaName); + return SQLExecutor.getInstance().execute(connection, sql, resultSet -> { + while (resultSet.next()) { + Procedure procedure = new Procedure(); + procedure.setDatabaseName(databaseName); + procedure.setSchemaName(schemaName); + procedure.setProcedureName(resultSet.getString("PROC_NAME")); + procedures.add(procedure); + } + return procedures; + }); + } + + private static String TRIGGER_SQL - = "SELECT OWNER, TRIGGER_NAME, TABLE_OWNER, TABLE_NAME, TRIGGERING_TYPE, TRIGGERING_EVENT, STATUS, TRIGGER_BODY " - + "FROM ALL_TRIGGERS WHERE OWNER = '%s' AND TRIGGER_NAME = '%s'"; + = "select t.trig_name,t.DEFINE from all_triggers t LEFT JOIN DBA_DATABASES DB ON t.DB_ID = DB.DB_ID LEFT JOIN DBA_SCHEMAS CH ON t.SCHEMA_ID = CH.SCHEMA_ID where DB.DB_NAME = '%s' and CH.SCHEMA_NAME = '%s' and t.trig_name = '%s'"; - private static String TRIGGER_SQL_LIST = "SELECT OWNER, TRIGGER_NAME FROM ALL_TRIGGERS WHERE OWNER = '%s'"; + private static String TRIGGER_SQL_LIST = "select t.trig_name from all_triggers t LEFT JOIN DBA_DATABASES DB ON t.DB_ID = DB.DB_ID LEFT JOIN DBA_SCHEMAS CH ON t.SCHEMA_ID = CH.SCHEMA_ID where DB.DB_NAME = '%s' and CH.SCHEMA_NAME = '%s'"; @Override public List triggers(Connection connection, String databaseName, String schemaName) { List triggers = new ArrayList<>(); - String sql = String.format(TRIGGER_SQL_LIST, schemaName); + String sql = String.format(TRIGGER_SQL_LIST, databaseName, schemaName); return SQLExecutor.getInstance().execute(connection, sql, resultSet -> { while (resultSet.next()) { Trigger trigger = new Trigger(); - trigger.setTriggerName(resultSet.getString("TRIGGER_NAME")); + trigger.setTriggerName(resultSet.getString("trig_name")); trigger.setSchemaName(schemaName); trigger.setDatabaseName(databaseName); triggers.add(trigger); @@ -126,22 +173,23 @@ public List triggers(Connection connection, String databaseName, String @Override public Trigger trigger(Connection connection, @NotEmpty String databaseName, String schemaName, - String triggerName) { + String triggerName) { - String sql = String.format(TRIGGER_SQL, schemaName, triggerName); + String sql = String.format(TRIGGER_SQL, databaseName, schemaName, 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("TRIGGER_BODY")); + trigger.setTriggerBody(resultSet.getString("DEFINE")); } return trigger; }); } private static String VIEW_SQL_LIST = "SELECT DB.DB_NAME, CH.SCHEMA_NAME, v.VIEW_NAME, v.DEFINE, v.OPTION,v.VALID, v.IS_SYS, v.COMMENTS FROM all_views v LEFT JOIN DBA_DATABASES DB ON v.DB_ID = DB.DB_ID LEFT JOIN DBA_SCHEMAS CH ON v.SCHEMA_ID = CH.SCHEMA_ID where DB.DB_NAME = '%s' and CH.SCHEMA_NAME = '%s'"; + @Override public List
views(Connection connection, String databaseName, String schemaName) { String sql = String.format(VIEW_SQL_LIST, databaseName, schemaName); @@ -161,26 +209,26 @@ public List
views(Connection connection, String databaseName, String sche } private static String VIEW_SQL - = "SELECT OWNER, VIEW_NAME, TEXT FROM ALL_VIEWS WHERE OWNER = '%s' AND VIEW_NAME = '%s'"; + = " SELECT CH.SCHEMA_NAME, v.VIEW_NAME, v.DEFINE FROM ALL_VIEWS v LEFT JOIN DBA_DATABASES DB ON v.DB_ID = DB.DB_ID LEFT JOIN DBA_SCHEMAS CH ON v.SCHEMA_ID = CH.SCHEMA_ID where DB.DB_NAME = '%s' and CH.SCHEMA_NAME = '%s' and v.VIEW_NAME = '%s'"; @Override public Table view(Connection connection, String databaseName, String schemaName, String viewName) { - String sql = String.format(VIEW_SQL, schemaName, viewName); + String sql = String.format(VIEW_SQL, databaseName, schemaName, 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("TEXT")); + table.setDdl(resultSet.getString("DEFINE")); } return table; }); } private static String INDEX_SQL = "SELECT i.INDEX_NAME, CASE i.INDEX_TYPE WHEN 0 THEN 'BTREE' WHEN 1 THEN 'RTREE' WHEN 2 THEN 'FULLTEXT' WHEN 3 THEN 'BITMAP' WHEN 4 THEN 'UNION' END AS INDEX_TYPE, i.IS_PRIMARY," - + " i.IS_UNIQUE, i.FIELD_NUM, REPLACE (KEYS, '\"', '') AS KEYS FROM ALL_INDEXES i LEFT JOIN ALL_TABLES T ON i.TABLE_ID = T.TABLE_ID LEFT JOIN ALL_SCHEMAS CH ON CH.USER_ID = T.USER_ID AND CH.DB_ID = i.DB_ID" - + " where CH.SCHEMA_NAME = '%s' and T.TABLE_NAME = '%s'"; + + " i.IS_UNIQUE, i.FIELD_NUM, REPLACE (KEYS, '\"', '') AS KEYS FROM ALL_INDEXES i LEFT JOIN ALL_TABLES T ON i.TABLE_ID = T.TABLE_ID LEFT JOIN ALL_SCHEMAS CH ON CH.USER_ID = T.USER_ID AND CH.DB_ID = i.DB_ID" + + " where CH.SCHEMA_NAME = '%s' and T.TABLE_NAME = '%s'"; @Override public List indexes(Connection connection, String databaseName, String schemaName, String tableName) { @@ -232,6 +280,7 @@ private List getTableIndexColumn(ResultSet resultSet) throws S return tableIndexColumnList; } + private static String SELECT_TABLE_COLUMNS = "select c.* from ALL_COLUMNS c LEFT JOIN ALL_TABLES T ON c.TABLE_ID = T.TABLE_ID LEFT JOIN ALL_SCHEMAS CH ON CH.USER_ID = T.USER_ID AND CH.DB_ID = c.DB_ID where CH.SCHEMA_NAME = '%s' and T.TABLE_NAME = '%s' order by c.COL_NO"; @Override @@ -248,7 +297,7 @@ public List columns(Connection connection, String databaseName, Str //column.setColumnType(resultSet.getString("COLUMN_TYPE")); if (resultSet.getBoolean("VARYING")) { if (resultSet.getString("TYPE_NAME").toUpperCase().equals(XUGUDBColumnTypeEnum.CHAR.name())) { - column.setColumnType("VAR"+resultSet.getString("TYPE_NAME").toUpperCase()); + column.setColumnType("VAR" + resultSet.getString("TYPE_NAME").toUpperCase()); } else { column.setColumnType(resultSet.getString("TYPE_NAME").toUpperCase()); } @@ -260,12 +309,12 @@ public List columns(Connection connection, String databaseName, Str column.setDefaultValue(resultSet.getString("DEF_VAL")); //column.setAutoIncrement(resultSet.getString("EXTRA").contains("auto_increment")); column.setComment(resultSet.getString("COMMENTS")); - // column.setPrimaryKey("PRI".equalsIgnoreCase(resultSet.getString("COLUMN_KEY"))); - column.setNullable(resultSet.getBoolean("NOT_NULL") ? 1 : 0); + // column.setPrimaryKey("PRI".equalsIgnoreCase(resultSet.getString("COLUMN_KEY"))); + column.setNullable(resultSet.getBoolean("NOT_NULL") ? 0 : 1); column.setOrdinalPosition(resultSet.getInt("SCALE")); - // column.setDecimalDigits(resultSet.getInt("NUMERIC_SCALE")); + // column.setDecimalDigits(resultSet.getInt("NUMERIC_SCALE")); //column.setCharSetName(resultSet.getString("CHARACTER_SET_NAME")); - // column.setCollationName(resultSet.getString("COLLATION_NAME")); + // column.setCollationName(resultSet.getString("COLLATION_NAME")); column.setColumnSize(resultSet.getInt("SCALE") == -1 ? null : resultSet.getInt("SCALE")); tableColumns.add(column); } @@ -291,6 +340,9 @@ public TableMeta getTableMeta(String databaseName, String schemaName, String tab @Override public String getMetaDataName(String... names) { + if (Arrays.stream(names).count() > 1) { + return Arrays.stream(names).skip(1).filter(name -> StringUtils.isNotBlank(name)).map(name -> "\"" + name + "\"").collect(Collectors.joining(".")); + } return Arrays.stream(names).filter(name -> StringUtils.isNotBlank(name)).map(name -> "\"" + name + "\"").collect(Collectors.joining(".")); } @@ -299,4 +351,5 @@ public String getMetaDataName(String... names) { public List getSystemSchemas() { return systemSchemas; } + } diff --git a/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/type/XUGUDBColumnTypeEnum.java b/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/type/XUGUDBColumnTypeEnum.java index aa9ca6901..405a9f439 100644 --- a/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/type/XUGUDBColumnTypeEnum.java +++ b/chat2db-server/chat2db-plugins/chat2db-xugudb/src/main/java/ai/chat2db/plugin/xugudb/type/XUGUDBColumnTypeEnum.java @@ -7,9 +7,7 @@ import com.google.common.collect.Maps; import org.apache.commons.lang3.StringUtils; -import java.util.Arrays; -import java.util.List; -import java.util.Map; +import java.util.*; public enum XUGUDBColumnTypeEnum implements ColumnBuilder { @@ -124,15 +122,44 @@ public String buildCreateColumnSql(TableColumn column) { script.append(buildDefaultValue(column, type)).append(" "); - script.append(buildAutoIncrement(column,type)).append(" "); + script.append(buildAutoIncrement(column, type)).append(" "); script.append(buildNullable(column, type)).append(" "); return script.toString(); } + public String buildUpdateColumnSql(TableColumn column) { + XUGUDBColumnTypeEnum type = COLUMN_TYPE_MAP.get(column.getColumnType().toUpperCase()); + if (type == null) { + return ""; + } + StringBuilder script = new StringBuilder(); + script.append("ALTER TABLE ").append("\"").append(column.getSchemaName()).append("\".\"").append(column.getTableName()).append("\""); + script.append(" ").append("MODIFY (").append("\"").append(column.getName()).append("\"").append(" "); + boolean isModify = false; + Integer oldColumnSize = Optional.ofNullable(column.getOldColumn()) + .map(TableColumn::getColumnSize) + .orElse(null); + + Integer newColumnSize = Optional.ofNullable(column.getColumnSize()) + .orElse(null); + if (!column.getOldColumn().getColumnType().equals(column.getColumnType()) + || !Objects.equals(oldColumnSize, newColumnSize)) { + script.append(buildDataType(column, type)).append(" "); + isModify = true; + } + if (!Objects.equals(column.getOldColumn().getNullable(), column.getNullable())) { + script.append(buildNullable(column, type)).append(" "); + isModify = true; + } + script.append(") \n"); + + return isModify ? script.toString() : ""; + } + private String buildAutoIncrement(TableColumn column, XUGUDBColumnTypeEnum type) { - if(!type.getColumnType().isSupportAutoIncrement()){ + if (!type.getColumnType().isSupportAutoIncrement()) { return ""; } if (column.getAutoIncrement() != null && column.getAutoIncrement() @@ -150,9 +177,17 @@ private String buildNullable(TableColumn column, XUGUDBColumnTypeEnum type) { return ""; } if (column.getNullable() != null && 1 == column.getNullable()) { - return "NULL"; + if (EditStatus.MODIFY.name().equals(column.getEditStatus())) { + return "DROP NOT NULL"; + } else { + return "NULL"; + } } else { - return "NOT NULL"; + if (EditStatus.MODIFY.name().equals(column.getEditStatus())) { + return "SET NOT NULL"; + } else { + return "NOT NULL"; + } } } @@ -246,15 +281,15 @@ public String buildModifyColumn(TableColumn tableColumn) { } if (EditStatus.MODIFY.name().equals(tableColumn.getEditStatus())) { StringBuilder script = new StringBuilder(); - script.append("ALTER TABLE ").append("\"").append(tableColumn.getSchemaName()).append("\".\"").append(tableColumn.getTableName()).append("\""); - script.append(" ").append("MODIFY (").append(buildCreateColumnSql(tableColumn)).append(") \n"); - if (!StringUtils.equalsIgnoreCase(tableColumn.getOldName(), tableColumn.getName())) { - script.append(";"); script.append("ALTER TABLE ").append("\"").append(tableColumn.getSchemaName()).append("\".\"").append(tableColumn.getTableName()).append("\""); - script.append(" ").append("RENAME COLUMN ").append("\"").append(tableColumn.getOldName()).append("\"").append(" TO ").append("\"").append(tableColumn.getName()).append("\""); - + script.append(" ").append("RENAME COLUMN ").append("\"").append(tableColumn.getOldName()).append("\"").append(" TO ").append("\"").append(tableColumn.getName()).append("\" ").append(";\n").append(buildUpdateColumnSql(tableColumn)); + //script.append(";\n"); + } else { + //script.append("ALTER TABLE ").append("\"").append(tableColumn.getSchemaName()).append("\".\"").append(tableColumn.getTableName()).append("\""); + script.append(buildUpdateColumnSql(tableColumn)).append("\n"); } + return script.toString(); }