From 6167134a12c6426792dff2b57d0d42aa9cfec243 Mon Sep 17 00:00:00 2001 From: tmlx1990 Date: Wed, 27 Dec 2023 17:09:03 +0800 Subject: [PATCH] =?UTF-8?q?fix:=20#974=20=E4=BC=98=E5=8C=96MySQL=E4=BF=AE?= =?UTF-8?q?=E6=94=B9=E5=88=97=E9=A1=BA=E5=BA=8F=E7=AE=97=E6=B3=95=E3=80=82?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../plugin/mysql/builder/MysqlSqlBuilder.java | 158 +++++++++++++++--- 1 file changed, 131 insertions(+), 27 deletions(-) diff --git a/chat2db-server/chat2db-plugins/chat2db-mysql/src/main/java/ai/chat2db/plugin/mysql/builder/MysqlSqlBuilder.java b/chat2db-server/chat2db-plugins/chat2db-mysql/src/main/java/ai/chat2db/plugin/mysql/builder/MysqlSqlBuilder.java index 6bf55192..9081ec7e 100644 --- a/chat2db-server/chat2db-plugins/chat2db-mysql/src/main/java/ai/chat2db/plugin/mysql/builder/MysqlSqlBuilder.java +++ b/chat2db-server/chat2db-plugins/chat2db-mysql/src/main/java/ai/chat2db/plugin/mysql/builder/MysqlSqlBuilder.java @@ -8,10 +8,12 @@ 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.List; -import java.util.stream.Collectors; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; public class MysqlSqlBuilder extends DefaultSqlBuilder implements SqlBuilder { @@ -19,14 +21,14 @@ public class MysqlSqlBuilder extends DefaultSqlBuilder implements SqlBuilder { public String buildCreateTableSql(Table table) { StringBuilder script = new StringBuilder(); script.append("CREATE TABLE "); - if(StringUtils.isNotBlank(table.getDatabaseName())) { + if (StringUtils.isNotBlank(table.getDatabaseName())) { script.append("`").append(table.getDatabaseName()).append("`").append("."); } script.append("`").append(table.getName()).append("`").append(" (").append("\n"); // append column for (TableColumn column : table.getColumnList()) { - if(StringUtils.isBlank(column.getName())|| StringUtils.isBlank(column.getColumnType())){ + if (StringUtils.isBlank(column.getName()) || StringUtils.isBlank(column.getColumnType())) { continue; } MysqlColumnTypeEnum typeEnum = MysqlColumnTypeEnum.getByType(column.getColumnType()); @@ -35,7 +37,7 @@ public class MysqlSqlBuilder extends DefaultSqlBuilder implements SqlBuilder { // append primary key and index for (TableIndex tableIndex : table.getIndexList()) { - if(StringUtils.isBlank(tableIndex.getName())|| StringUtils.isBlank(tableIndex.getType())){ + if (StringUtils.isBlank(tableIndex.getName()) || StringUtils.isBlank(tableIndex.getType())) { continue; } MysqlIndexTypeEnum mysqlIndexTypeEnum = MysqlIndexTypeEnum.getByType(tableIndex.getType()); @@ -78,7 +80,7 @@ public class MysqlSqlBuilder extends DefaultSqlBuilder implements SqlBuilder { public String buildModifyTaleSql(Table oldTable, Table newTable) { StringBuilder script = new StringBuilder(); script.append("ALTER TABLE "); - if(StringUtils.isNotBlank(oldTable.getDatabaseName())) { + if (StringUtils.isNotBlank(oldTable.getDatabaseName())) { script.append("`").append(oldTable.getDatabaseName()).append("`").append("."); } script.append("`").append(oldTable.getName()).append("`").append("\n"); @@ -94,7 +96,7 @@ public class MysqlSqlBuilder extends DefaultSqlBuilder implements SqlBuilder { // append modify column for (TableColumn tableColumn : newTable.getColumnList()) { - if (StringUtils.isNotBlank(tableColumn.getEditStatus()) && StringUtils.isNotBlank(tableColumn.getColumnType())&& StringUtils.isNotBlank(tableColumn.getName())){ + if (StringUtils.isNotBlank(tableColumn.getEditStatus()) && StringUtils.isNotBlank(tableColumn.getColumnType()) && StringUtils.isNotBlank(tableColumn.getName())) { MysqlColumnTypeEnum typeEnum = MysqlColumnTypeEnum.getByType(tableColumn.getColumnType()); script.append("\t").append(typeEnum.buildModifyColumn(tableColumn)).append(",\n"); } @@ -111,7 +113,7 @@ public class MysqlSqlBuilder extends DefaultSqlBuilder implements SqlBuilder { // append reorder column script.append("\t").append(buildGenerateReorderColumnSql(oldTable, newTable)); - if(script.length()>2) { + if (script.length() > 2) { script = new StringBuilder(script.substring(0, script.length() - 2)); script.append(";"); } @@ -120,7 +122,6 @@ public class MysqlSqlBuilder extends DefaultSqlBuilder implements SqlBuilder { } - @Override public String pageLimit(String sql, int offset, int pageNo, int pageSize) { StringBuilder sqlBuilder = new StringBuilder(sql.length() + 14); @@ -138,12 +139,10 @@ public class MysqlSqlBuilder extends DefaultSqlBuilder implements SqlBuilder { } - - @Override public String buildCreateDatabaseSql(Database database) { StringBuilder sqlBuilder = new StringBuilder(); - sqlBuilder.append("CREATE DATABASE `"+database.getName()+"`"); + sqlBuilder.append("CREATE DATABASE `" + database.getName() + "`"); if (StringUtils.isNotBlank(database.getCharset())) { sqlBuilder.append(" DEFAULT CHARACTER SET=").append(database.getCharset()); } @@ -152,38 +151,143 @@ public class MysqlSqlBuilder extends DefaultSqlBuilder implements SqlBuilder { } return sqlBuilder.toString(); } + public String buildGenerateReorderColumnSql(Table oldTable, Table newTable) { StringBuilder sql = new StringBuilder(); int n = 0; - for (int i = 0; i < newTable.getColumnList().size(); i++) { - TableColumn column = newTable.getColumnList().get(i); - //String columnName = newTable.getColumnList().get(i).getName(); - // 获取oldTable.getColumnList()中name属性的list - List oldColumnList = oldTable.getColumnList().stream() - .map(TableColumn::getName) - .collect(Collectors.toList()); + // 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); - if (i > oldColumnList.indexOf(column.getName())) { + 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 "); + MysqlColumnTypeEnum typeEnum = MysqlColumnTypeEnum.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 "); + MysqlColumnTypeEnum typeEnum = MysqlColumnTypeEnum.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 "); - sql.append("`").append(column.getDatabaseName()).append("`").append("."); + if (StringUtils.isNotBlank(oldTable.getDatabaseName())) { + sql.append("`").append(oldTable.getDatabaseName()).append("`").append("."); + } sql.append("`").append(oldTable.getName()).append("`").append("\n"); } sql.append(" MODIFY COLUMN "); MysqlColumnTypeEnum typeEnum = MysqlColumnTypeEnum.getByType(column.getColumnType()); sql.append(typeEnum.buildColumn(column)); sql.append(" "); - if (i > 0) { - sql.append(" AFTER "); - sql.append(newTable.getColumnList().get(i - 1).getName()); + sql.append(" AFTER "); + if (i < a) { + sql.append(originalArray[a]); } else { - sql.append(" FIRST"); + 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 sql.toString(); + 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; + } + }