support sqlserver metadata update

This commit is contained in:
SwallowGG
2023-10-07 19:27:06 +08:00
parent d483dd1df2
commit 04462d7811
20 changed files with 1002 additions and 205 deletions

View File

@ -39,7 +39,7 @@ public interface MetaData {
* @return
*/
String tableDDL(Connection connection, @NotEmpty String databaseName, String schemaName,
@NotEmpty String tableName);
@NotEmpty String tableName);
/**
* Querying all table under a schema.
@ -114,7 +114,7 @@ public interface MetaData {
* @return
*/
List<TableColumn> columns(Connection connection, @NotEmpty String databaseName, String schemaName,
@NotEmpty String tableName);
@NotEmpty String tableName);
/**
* Querying all columns under a table.
@ -127,7 +127,7 @@ public interface MetaData {
* @return
*/
List<TableColumn> columns(Connection connection, @NotEmpty String databaseName, String schemaName, String tableName,
String columnName);
String columnName);
/**
* Querying all indexes under a table.
@ -138,7 +138,7 @@ public interface MetaData {
* @return
*/
List<TableIndex> indexes(Connection connection, @NotEmpty String databaseName, String schemaName,
@NotEmpty String tableName);
@NotEmpty String tableName);
/**
* Querying function detail under a schema.
@ -171,11 +171,10 @@ public interface MetaData {
* @param procedureName
* @return
*/
Procedure procedure(Connection connection, @NotEmpty String databaseName, String schemaName,String procedureName);
Procedure procedure(Connection connection, @NotEmpty String databaseName, String schemaName, String procedureName);
/**
*
* @param connection
* @return
*/
@ -184,17 +183,28 @@ public interface MetaData {
/**
* Get sql builder.
*
* @return
*/
SqlBuilder getSqlBuilder();
/**
*
* @param databaseName
* @param schemaName
* @param tableName
* @return
*/
TableMeta getTableMeta( String databaseName, String schemaName, String tableName);
TableMeta getTableMeta(String databaseName, String schemaName, String tableName);
/**
* Get meta data name.
*
* @param names
* @return
*/
String getMetaDataName(String ...names);
}

View File

@ -16,6 +16,11 @@ import lombok.experimental.SuperBuilder;
@NoArgsConstructor
@AllArgsConstructor
public class TableColumn {
/**
* Old column, when modifying a column, you need this parameter
*/
private TableColumn oldColumn;
/**
* 旧的列名,在修改列的时候需要这个参数
* 在返回的时候oldName=name
@ -58,6 +63,8 @@ public class TableColumn {
@JsonAlias({"COLUMN_DEF"})
private String defaultValue;
/**
* 是否自增
* 为空 代表没有值 数据库的实际语义是 false
@ -88,7 +95,7 @@ public class TableColumn {
private String databaseName;
/**
* Data source dependent type name, for a UDT the type name is fully qualified
* Data source dependent type name, for a UDT the type name is fully qualified
*/
private String typeName;
@ -151,8 +158,8 @@ public class TableColumn {
/**
* String => Indicates whether this is a generated column
* * YES --- if this a generated column
* * NO --- if this not a generated column
* * YES --- if this a generated column
* * NO --- if this not a generated column
*/
private Boolean generatedColumn;
@ -166,9 +173,15 @@ public class TableColumn {
private String collationName;
//Mysql
private String value;
//ORACLE
private String unit;
// sqlserver
private Boolean sparse;
// sqlserver
private String defaultConstraintName;
}

View File

@ -9,6 +9,7 @@ import java.util.Set;
import java.util.stream.Collectors;
import ai.chat2db.server.tools.common.util.EasyIntegerUtils;
import ai.chat2db.spi.enums.DataTypeEnum;
import com.alibaba.druid.DbType;
import com.alibaba.druid.sql.SQLUtils;
import com.alibaba.druid.sql.ast.SQLDataTypeImpl;
@ -57,6 +58,10 @@ import ai.chat2db.spi.model.TableIndexColumn;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.Statements;
import net.sf.jsqlparser.statement.select.PlainSelect;
import net.sf.jsqlparser.statement.select.Select;
import net.sf.jsqlparser.statement.select.SelectExpressionItem;
import net.sf.jsqlparser.statement.select.SelectItem;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.StringUtils;
@ -69,6 +74,31 @@ public class SqlUtils {
public static final String DEFAULT_TABLE_NAME = "table1";
public static boolean canEdit(String sql) {
try {
Statement statement = CCJSqlParserUtil.parse(sql);
if (statement instanceof Select) {
Select select = (Select) statement;
PlainSelect plainSelect = (PlainSelect) select.getSelectBody();
if (plainSelect.getJoins() == null && plainSelect.getFromItem() != null) {
for (SelectItem item : plainSelect.getSelectItems()) {
if (item instanceof SelectExpressionItem) {
SelectExpressionItem expressionItem = (SelectExpressionItem) item;
if (expressionItem.getAlias() != null) {
return false; // 找到了一个别名
}
}
}
return true;
}
}
} catch (Exception e) {
return false;
}
return false;
}
public static List<Sql> buildSql(Table oldTable, Table newTable) {
List<Sql> sqlList = new ArrayList<>();
// 创建表
@ -86,7 +116,7 @@ public class SqlUtils {
mySqlCreateTableStatement.addColumn(sqlColumnDefinition);
sqlColumnDefinition.setName(tableColumn.getName());
sqlColumnDefinition.setDataType(new SQLDataTypeImpl(tableColumn.getColumnType()));
if (tableColumn.getNullable()==1) {
if (tableColumn.getNullable() == 1) {
sqlColumnDefinition.addConstraint(new SQLNullConstraint());
} else {
sqlColumnDefinition.addConstraint(new SQLNotNullConstraint());
@ -130,7 +160,7 @@ public class SqlUtils {
SQLSelectOrderByItem sqlSelectOrderByItem = new SQLSelectOrderByItem();
sqlSelectOrderByItem.setExpr(new SQLIdentifierExpr(tableIndexColumn.getColumnName()));
CollationEnum collation = EasyEnumUtils.getEnum(CollationEnum.class,
tableIndexColumn.getCollation());
tableIndexColumn.getCollation());
if (collation != null) {
sqlSelectOrderByItem.setType(collation.getSqlOrderingSpecification());
}
@ -147,7 +177,7 @@ public class SqlUtils {
SQLSelectOrderByItem sqlSelectOrderByItem = new SQLSelectOrderByItem();
sqlSelectOrderByItem.setExpr(new SQLIdentifierExpr(tableIndexColumn.getColumnName()));
CollationEnum collation = EasyEnumUtils.getEnum(CollationEnum.class,
tableIndexColumn.getCollation());
tableIndexColumn.getCollation());
if (collation != null) {
sqlSelectOrderByItem.setType(collation.getSqlOrderingSpecification());
}
@ -193,19 +223,19 @@ public class SqlUtils {
private static void modifyColumn(List<Sql> sqlList, Table oldTable, Table newTable) {
Map<String, TableColumn> oldColumnMap = EasyCollectionUtils.toIdentityMap(oldTable.getColumnList(),
tableColumn -> {
if (tableColumn.getOldName() != null) {
return tableColumn.getOldName();
}
return tableColumn.getName();
});
tableColumn -> {
if (tableColumn.getOldName() != null) {
return tableColumn.getOldName();
}
return tableColumn.getName();
});
Map<String, TableColumn> newColumnMap = EasyCollectionUtils.toIdentityMap(newTable.getColumnList(),
tableColumn -> {
if (tableColumn.getOldName() != null) {
return tableColumn.getOldName();
}
return tableColumn.getName();
});
tableColumn -> {
if (tableColumn.getOldName() != null) {
return tableColumn.getOldName();
}
return tableColumn.getName();
});
SQLAlterTableStatement sqlAlterTableStatement = new SQLAlterTableStatement();
sqlAlterTableStatement.setDbType(DbType.mysql);
@ -222,7 +252,7 @@ public class SqlUtils {
sqlAlterTableAddColumn.addColumn(sqlColumnDefinition);
sqlColumnDefinition.setName(newTableColumn.getName());
sqlColumnDefinition.setDataType(new SQLDataTypeImpl(newTableColumn.getColumnType()));
if (newTableColumn.getNullable()!=1) {
if (newTableColumn.getNullable() != 1) {
sqlColumnDefinition.addConstraint(new SQLNotNullConstraint());
}
if (!Objects.isNull(newTableColumn.getDefaultValue())) {
@ -236,12 +266,12 @@ public class SqlUtils {
}
// 代表可能修改字段 或者没变
boolean hasChange = !StringUtils.equals(oldTableColumn.getName(), newTableColumn.getName())
|| !StringUtils.equals(oldTableColumn.getColumnType(), newTableColumn.getColumnType())
|| !EasyIntegerUtils.equals(oldTableColumn.getNullable(), newTableColumn.getNullable(), 1)
|| !StringUtils.equals(oldTableColumn.getDefaultValue(), newTableColumn.getDefaultValue())
|| !EasyBooleanUtils.equals(oldTableColumn.getAutoIncrement(), newTableColumn.getAutoIncrement(),
Boolean.FALSE)
|| !StringUtils.equals(oldTableColumn.getComment(), newTableColumn.getComment());
|| !StringUtils.equals(oldTableColumn.getColumnType(), newTableColumn.getColumnType())
|| !EasyIntegerUtils.equals(oldTableColumn.getNullable(), newTableColumn.getNullable(), 1)
|| !StringUtils.equals(oldTableColumn.getDefaultValue(), newTableColumn.getDefaultValue())
|| !EasyBooleanUtils.equals(oldTableColumn.getAutoIncrement(), newTableColumn.getAutoIncrement(),
Boolean.FALSE)
|| !StringUtils.equals(oldTableColumn.getComment(), newTableColumn.getComment());
// 没有修改字段
if (!hasChange) {
@ -257,7 +287,7 @@ public class SqlUtils {
mySqlAlterTableChangeColumn.setNewColumnDefinition(sqlColumnDefinition);
sqlColumnDefinition.setName(newTableColumn.getName());
sqlColumnDefinition.setDataType(new SQLDataTypeImpl(newTableColumn.getColumnType()));
if (newTableColumn.getNullable()!=1) {
if (newTableColumn.getNullable() != 1) {
sqlColumnDefinition.addConstraint(new SQLNotNullConstraint());
}
if (!Objects.isNull(newTableColumn.getDefaultValue())) {
@ -275,7 +305,7 @@ public class SqlUtils {
mySqlAlterTableModifyColumn.setNewColumnDefinition(sqlColumnDefinition);
sqlColumnDefinition.setName(newTableColumn.getName());
sqlColumnDefinition.setDataType(new SQLDataTypeImpl(newTableColumn.getColumnType()));
if (newTableColumn.getNullable()!=1) {
if (newTableColumn.getNullable() != 1) {
sqlColumnDefinition.addConstraint(new SQLNotNullConstraint());
}
if (!Objects.isNull(newTableColumn.getDefaultValue())) {
@ -301,17 +331,17 @@ public class SqlUtils {
// 比较主键是否有修改
// 主键
Set<String> oldPrimaryKeySet = EasyCollectionUtils.stream(oldTable.getColumnList())
.filter(tableColumn -> BooleanUtils.isTrue(tableColumn.getPrimaryKey()))
.map(TableColumn::getName)
.collect(Collectors.toSet());
.filter(tableColumn -> BooleanUtils.isTrue(tableColumn.getPrimaryKey()))
.map(TableColumn::getName)
.collect(Collectors.toSet());
Set<String> newPrimaryKeySet = EasyCollectionUtils.stream(newTable.getColumnList())
.filter(tableColumn -> BooleanUtils.isTrue(tableColumn.getPrimaryKey()))
.map(TableColumn::getName)
.collect(Collectors.toSet());
.filter(tableColumn -> BooleanUtils.isTrue(tableColumn.getPrimaryKey()))
.map(TableColumn::getName)
.collect(Collectors.toSet());
boolean primaryKeyChange = oldPrimaryKeySet.stream()
.anyMatch(oldPrimaryKey -> !newPrimaryKeySet.contains(oldPrimaryKey))
|| newPrimaryKeySet.stream()
.anyMatch(newPrimaryKey -> !oldPrimaryKeySet.contains(newPrimaryKey));
.anyMatch(oldPrimaryKey -> !newPrimaryKeySet.contains(oldPrimaryKey))
|| newPrimaryKeySet.stream()
.anyMatch(newPrimaryKey -> !oldPrimaryKeySet.contains(newPrimaryKey));
if (primaryKeyChange) {
sqlAlterTableStatement.addItem(new SQLAlterTableDropPrimaryKey());
SQLAlterTableAddConstraint sqlAlterTableAddConstraint = new SQLAlterTableAddConstraint();
@ -321,10 +351,10 @@ public class SqlUtils {
mySqlPrimaryKey.setIndexType("PRIMARY");
// 排序
EasyCollectionUtils.stream(newTable.getColumnList())
.filter(tableColumn -> BooleanUtils.isTrue(tableColumn.getPrimaryKey()))
.map(TableColumn::getName)
.forEach(tableColumnName -> mySqlPrimaryKey.addColumn(
new SQLSelectOrderByItem(new SQLIdentifierExpr(tableColumnName))));
.filter(tableColumn -> BooleanUtils.isTrue(tableColumn.getPrimaryKey()))
.map(TableColumn::getName)
.forEach(tableColumnName -> mySqlPrimaryKey.addColumn(
new SQLSelectOrderByItem(new SQLIdentifierExpr(tableColumnName))));
}
if (CollectionUtils.isNotEmpty(sqlAlterTableStatement.getItems())) {
@ -334,9 +364,9 @@ public class SqlUtils {
private static void modifyIndex(List<Sql> sqlList, Table oldTable, Table newTable) {
Map<String, TableIndex> oldIndexMap = EasyCollectionUtils.toIdentityMap(oldTable.getIndexList(),
TableIndex::getName);
TableIndex::getName);
Map<String, TableIndex> newIndexMap = EasyCollectionUtils.toIdentityMap(newTable.getIndexList(),
TableIndex::getName);
TableIndex::getName);
newIndexMap.forEach((newTableIndexName, newTableIndex) -> {
TableIndex oldTableIndex = oldIndexMap.get(newTableIndexName);
// 代表新增索引
@ -352,7 +382,7 @@ public class SqlUtils {
SQLSelectOrderByItem sqlSelectOrderByItem = new SQLSelectOrderByItem();
sqlSelectOrderByItem.setExpr(new SQLIdentifierExpr(tableIndexColumn.getColumnName()));
CollationEnum collation = EasyEnumUtils.getEnum(CollationEnum.class,
tableIndexColumn.getCollation());
tableIndexColumn.getCollation());
if (collation != null) {
sqlSelectOrderByItem.setType(collation.getSqlOrderingSpecification());
}
@ -364,34 +394,34 @@ public class SqlUtils {
}
// 代表可能修改索引 或者没变
boolean hasChange = !StringUtils.equals(oldTableIndex.getName(), newTableIndex.getName())
|| !StringUtils.equals(oldTableIndex.getComment(), newTableIndex.getComment())
|| !Objects.equals(oldTableIndex.getUnique(), newTableIndex.getUnique());
|| !StringUtils.equals(oldTableIndex.getComment(), newTableIndex.getComment())
|| !Objects.equals(oldTableIndex.getUnique(), newTableIndex.getUnique());
if (!hasChange) {
Map<String, TableIndexColumn> oldTableIndexColumnMap = EasyCollectionUtils.toIdentityMap(
oldTableIndex.getColumnList(), TableIndexColumn::getColumnName);
oldTableIndex.getColumnList(), TableIndexColumn::getColumnName);
Map<String, TableIndexColumn> newTableIndexColumnMap = EasyCollectionUtils.toIdentityMap(
newTableIndex.getColumnList(), TableIndexColumn::getColumnName);
newTableIndex.getColumnList(), TableIndexColumn::getColumnName);
hasChange = oldTableIndexColumnMap.entrySet()
.stream()
.anyMatch(oldTableIndexColumnEntry -> {
TableIndexColumn newTableIndexColumn = newTableIndexColumnMap.get(
oldTableIndexColumnEntry.getKey());
if (newTableIndexColumn == null) {
return true;
}
TableIndexColumn oldTableIndexColumn = oldTableIndexColumnEntry.getValue();
return !StringUtils.equals(oldTableIndexColumn.getColumnName(),
newTableIndexColumn.getColumnName())
|| !CollationEnum.equals(oldTableIndexColumn.getCollation(),
newTableIndexColumn.getCollation());
})
|| newTableIndexColumnMap.entrySet()
.stream()
.anyMatch(newTableIndexColumnEntry -> {
TableIndexColumn oldTableIndexColumn = oldTableIndexColumnMap.get(
newTableIndexColumnEntry.getKey());
return oldTableIndexColumn == null;
});
.stream()
.anyMatch(oldTableIndexColumnEntry -> {
TableIndexColumn newTableIndexColumn = newTableIndexColumnMap.get(
oldTableIndexColumnEntry.getKey());
if (newTableIndexColumn == null) {
return true;
}
TableIndexColumn oldTableIndexColumn = oldTableIndexColumnEntry.getValue();
return !StringUtils.equals(oldTableIndexColumn.getColumnName(),
newTableIndexColumn.getColumnName())
|| !CollationEnum.equals(oldTableIndexColumn.getCollation(),
newTableIndexColumn.getCollation());
})
|| newTableIndexColumnMap.entrySet()
.stream()
.anyMatch(newTableIndexColumnEntry -> {
TableIndexColumn oldTableIndexColumn = oldTableIndexColumnMap.get(
newTableIndexColumnEntry.getKey());
return oldTableIndexColumn == null;
});
}
// 没有修改索引
@ -417,7 +447,7 @@ public class SqlUtils {
SQLSelectOrderByItem sqlSelectOrderByItem = new SQLSelectOrderByItem();
sqlSelectOrderByItem.setExpr(new SQLIdentifierExpr(tableIndexColumn.getColumnName()));
CollationEnum collation = EasyEnumUtils.getEnum(CollationEnum.class,
tableIndexColumn.getCollation());
tableIndexColumn.getCollation());
if (collation != null) {
sqlSelectOrderByItem.setType(collation.getSqlOrderingSpecification());
}
@ -449,8 +479,8 @@ public class SqlUtils {
if (!(sqlStatement instanceof SQLSelectStatement sqlSelectStatement)) {
throw new BusinessException("dataSource.sqlAnalysisError");
}
SQLExprTableSource sqlExprTableSource = (SQLExprTableSource)getSQLExprTableSource(
sqlSelectStatement.getSelect().getFirstQueryBlock().getFrom());
SQLExprTableSource sqlExprTableSource = (SQLExprTableSource) getSQLExprTableSource(
sqlSelectStatement.getSelect().getFirstQueryBlock().getFrom());
if (sqlExprTableSource == null) {
return DEFAULT_TABLE_NAME;
}
@ -466,7 +496,7 @@ public class SqlUtils {
return null;
}
public static List<String> parse(String sql,DbType dbType) {
public static List<String> parse(String sql, DbType dbType) {
List<String> list = new ArrayList<>();
try {
Statements statements = CCJSqlParserUtil.parseStatements(sql);
@ -480,4 +510,11 @@ public class SqlUtils {
return list;
}
public static String getSqlValue(String value, String dataType) {
if(value == null){
return null;
}
DataTypeEnum dataTypeEnum = DataTypeEnum.getByCode(dataType);
return dataTypeEnum.getSqlValue(value);
}
}