Skip to content

Commit

Permalink
Merge pull request #1008 from tmlx1990/fix974
Browse files Browse the repository at this point in the history
Fix974、992 修复MySQL修改列顺序后生成SQL语句错误问题
  • Loading branch information
Chat2DB-Pro authored Dec 27, 2023
2 parents 804cb03 + 6167134 commit eb9ff6e
Show file tree
Hide file tree
Showing 2 changed files with 166 additions and 10 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -8,22 +8,27 @@
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 MysqlSqlBuilder extends DefaultSqlBuilder implements SqlBuilder {
@Override
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());
Expand All @@ -32,7 +37,7 @@ public String buildCreateTableSql(Table table) {

// 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());
Expand Down Expand Up @@ -75,7 +80,7 @@ public String buildCreateTableSql(Table table) {
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");
Expand All @@ -91,7 +96,7 @@ public String buildModifyTaleSql(Table oldTable, Table newTable) {

// 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");
}
Expand All @@ -104,7 +109,11 @@ public String buildModifyTaleSql(Table oldTable, Table newTable) {
script.append("\t").append(mysqlIndexTypeEnum.buildModifyIndex(tableIndex)).append(",\n");
}
}
if(script.length()>2) {

// append reorder column
script.append("\t").append(buildGenerateReorderColumnSql(oldTable, newTable));

if (script.length() > 2) {
script = new StringBuilder(script.substring(0, script.length() - 2));
script.append(";");
}
Expand All @@ -113,7 +122,6 @@ public String buildModifyTaleSql(Table oldTable, Table newTable) {
}



@Override
public String pageLimit(String sql, int offset, int pageNo, int pageSize) {
StringBuilder sqlBuilder = new StringBuilder(sql.length() + 14);
Expand All @@ -131,12 +139,10 @@ public String pageLimit(String sql, int offset, int pageNo, int pageSize) {
}




@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());
}
Expand All @@ -146,4 +152,142 @@ 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<String, Integer> 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 ");
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 ");
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 ");
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;
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -318,6 +318,18 @@ private String buildDataType(TableColumn column, MysqlColumnTypeEnum type) {
return columnType;
}

public String buildColumn(TableColumn column) {
MysqlColumnTypeEnum 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(" ");
return script.toString();
}

private String unsignedDataType(String dataTypeName, String middle) {
String[] split = dataTypeName.split(" ");
if (split.length == 2) {
Expand Down

0 comments on commit eb9ff6e

Please sign in to comment.