mirror of
https://github.com/CodePhiliaX/Chat2DB.git
synced 2025-08-02 13:34:07 +08:00
support sqlserver metadata update
This commit is contained in:
@ -15,6 +15,11 @@
|
||||
<groupId>ai.chat2db</groupId>
|
||||
<artifactId>chat2db-spi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>ai.chat2db</groupId>
|
||||
<artifactId>chat2db-mysql</artifactId>
|
||||
<version>2.0.0-SNAPSHOT</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<artifactId>chat2db-mariadb</artifactId>
|
||||
|
@ -4,6 +4,7 @@ import java.sql.Connection;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import ai.chat2db.plugin.mysql.MysqlMetaData;
|
||||
import ai.chat2db.spi.MetaData;
|
||||
import ai.chat2db.spi.jdbc.DefaultMetaService;
|
||||
import ai.chat2db.spi.model.Function;
|
||||
@ -13,109 +14,109 @@ import ai.chat2db.spi.model.Trigger;
|
||||
import ai.chat2db.spi.sql.SQLExecutor;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
|
||||
public class MariaDBMetaData extends DefaultMetaService implements MetaData {
|
||||
public class MariaDBMetaData extends MysqlMetaData implements MetaData {
|
||||
|
||||
|
||||
private static String ROUTINES_SQL
|
||||
=
|
||||
"SELECT SPECIFIC_NAME, ROUTINE_COMMENT, ROUTINE_DEFINITION FROM information_schema.routines WHERE "
|
||||
+ "routine_type = '%s' AND ROUTINE_SCHEMA ='%s' AND "
|
||||
+ "routine_name = '%s';";
|
||||
|
||||
@Override
|
||||
public Function function(Connection connection, @NotEmpty String databaseName, String schemaName,
|
||||
String functionName) {
|
||||
|
||||
String sql = String.format(ROUTINES_SQL, "FUNCTION", databaseName, functionName);
|
||||
return SQLExecutor.getInstance().execute(connection, sql, resultSet -> {
|
||||
Function function = new Function();
|
||||
function.setDatabaseName(databaseName);
|
||||
function.setSchemaName(schemaName);
|
||||
function.setFunctionName(functionName);
|
||||
if (resultSet.next()) {
|
||||
function.setSpecificName(resultSet.getString("SPECIFIC_NAME"));
|
||||
function.setRemarks(resultSet.getString("ROUTINE_COMMENT"));
|
||||
function.setFunctionBody(resultSet.getString("ROUTINE_DEFINITION"));
|
||||
}
|
||||
return function;
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private static String TRIGGER_SQL
|
||||
= "SELECT TRIGGER_NAME,EVENT_MANIPULATION, ACTION_STATEMENT FROM INFORMATION_SCHEMA.TRIGGERS where "
|
||||
+ "TRIGGER_SCHEMA = '%s' AND TRIGGER_NAME = '%s';";
|
||||
|
||||
private static String TRIGGER_SQL_LIST
|
||||
= "SELECT TRIGGER_NAME FROM INFORMATION_SCHEMA.TRIGGERS where TRIGGER_SCHEMA = '%s';";
|
||||
|
||||
@Override
|
||||
public List<Trigger> triggers(Connection connection, String databaseName, String schemaName) {
|
||||
List<Trigger> triggers = new ArrayList<>();
|
||||
String sql = String.format(TRIGGER_SQL_LIST, databaseName);
|
||||
return SQLExecutor.getInstance().execute(connection, sql, resultSet -> {
|
||||
while (resultSet.next()) {
|
||||
Trigger trigger = new Trigger();
|
||||
trigger.setTriggerName(resultSet.getString("TRIGGER_NAME"));
|
||||
trigger.setSchemaName(schemaName);
|
||||
trigger.setDatabaseName(databaseName);
|
||||
triggers.add(trigger);
|
||||
}
|
||||
return triggers;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Trigger trigger(Connection connection, @NotEmpty String databaseName, String schemaName,
|
||||
String triggerName) {
|
||||
|
||||
String sql = String.format(TRIGGER_SQL, databaseName, triggerName);
|
||||
return SQLExecutor.getInstance().execute(connection, sql, resultSet -> {
|
||||
Trigger trigger = new Trigger();
|
||||
trigger.setDatabaseName(databaseName);
|
||||
trigger.setSchemaName(schemaName);
|
||||
trigger.setTriggerName(triggerName);
|
||||
if (resultSet.next()) {
|
||||
trigger.setTriggerBody(resultSet.getString("ACTION_STATEMENT"));
|
||||
}
|
||||
return trigger;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Procedure procedure(Connection connection, @NotEmpty String databaseName, String schemaName,
|
||||
String procedureName) {
|
||||
String sql = String.format(ROUTINES_SQL, "PROCEDURE", databaseName, procedureName);
|
||||
return SQLExecutor.getInstance().execute(connection, sql, resultSet -> {
|
||||
Procedure procedure = new Procedure();
|
||||
procedure.setDatabaseName(databaseName);
|
||||
procedure.setSchemaName(schemaName);
|
||||
procedure.setProcedureName(procedureName);
|
||||
if (resultSet.next()) {
|
||||
procedure.setSpecificName(resultSet.getString("SPECIFIC_NAME"));
|
||||
procedure.setRemarks(resultSet.getString("ROUTINE_COMMENT"));
|
||||
procedure.setProcedureBody(resultSet.getString("ROUTINE_DEFINITION"));
|
||||
}
|
||||
return procedure;
|
||||
});
|
||||
}
|
||||
|
||||
private static String VIEW_SQL
|
||||
= "SELECT TABLE_SCHEMA AS DatabaseName, TABLE_NAME AS ViewName, VIEW_DEFINITION AS definition, CHECK_OPTION, "
|
||||
+ "IS_UPDATABLE FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_SCHEMA = '%s' AND TABLE_NAME = '%s';";
|
||||
|
||||
@Override
|
||||
public Table view(Connection connection, String databaseName, String schemaName, String viewName) {
|
||||
String sql = String.format(VIEW_SQL, databaseName, viewName);
|
||||
return SQLExecutor.getInstance().execute(connection, sql, resultSet -> {
|
||||
Table table = new Table();
|
||||
table.setDatabaseName(databaseName);
|
||||
table.setSchemaName(schemaName);
|
||||
table.setName(viewName);
|
||||
if (resultSet.next()) {
|
||||
table.setDdl(resultSet.getString("definition"));
|
||||
}
|
||||
return table;
|
||||
});
|
||||
}
|
||||
// private static String ROUTINES_SQL
|
||||
// =
|
||||
// "SELECT SPECIFIC_NAME, ROUTINE_COMMENT, ROUTINE_DEFINITION FROM information_schema.routines WHERE "
|
||||
// + "routine_type = '%s' AND ROUTINE_SCHEMA ='%s' AND "
|
||||
// + "routine_name = '%s';";
|
||||
//
|
||||
// @Override
|
||||
// public Function function(Connection connection, @NotEmpty String databaseName, String schemaName,
|
||||
// String functionName) {
|
||||
//
|
||||
// String sql = String.format(ROUTINES_SQL, "FUNCTION", databaseName, functionName);
|
||||
// return SQLExecutor.getInstance().execute(connection, sql, resultSet -> {
|
||||
// Function function = new Function();
|
||||
// function.setDatabaseName(databaseName);
|
||||
// function.setSchemaName(schemaName);
|
||||
// function.setFunctionName(functionName);
|
||||
// if (resultSet.next()) {
|
||||
// function.setSpecificName(resultSet.getString("SPECIFIC_NAME"));
|
||||
// function.setRemarks(resultSet.getString("ROUTINE_COMMENT"));
|
||||
// function.setFunctionBody(resultSet.getString("ROUTINE_DEFINITION"));
|
||||
// }
|
||||
// return function;
|
||||
// });
|
||||
//
|
||||
// }
|
||||
//
|
||||
// private static String TRIGGER_SQL
|
||||
// = "SELECT TRIGGER_NAME,EVENT_MANIPULATION, ACTION_STATEMENT FROM INFORMATION_SCHEMA.TRIGGERS where "
|
||||
// + "TRIGGER_SCHEMA = '%s' AND TRIGGER_NAME = '%s';";
|
||||
//
|
||||
// private static String TRIGGER_SQL_LIST
|
||||
// = "SELECT TRIGGER_NAME FROM INFORMATION_SCHEMA.TRIGGERS where TRIGGER_SCHEMA = '%s';";
|
||||
//
|
||||
// @Override
|
||||
// public List<Trigger> triggers(Connection connection, String databaseName, String schemaName) {
|
||||
// List<Trigger> triggers = new ArrayList<>();
|
||||
// String sql = String.format(TRIGGER_SQL_LIST, databaseName);
|
||||
// return SQLExecutor.getInstance().execute(connection, sql, resultSet -> {
|
||||
// while (resultSet.next()) {
|
||||
// Trigger trigger = new Trigger();
|
||||
// trigger.setTriggerName(resultSet.getString("TRIGGER_NAME"));
|
||||
// trigger.setSchemaName(schemaName);
|
||||
// trigger.setDatabaseName(databaseName);
|
||||
// triggers.add(trigger);
|
||||
// }
|
||||
// return triggers;
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public Trigger trigger(Connection connection, @NotEmpty String databaseName, String schemaName,
|
||||
// String triggerName) {
|
||||
//
|
||||
// String sql = String.format(TRIGGER_SQL, databaseName, triggerName);
|
||||
// return SQLExecutor.getInstance().execute(connection, sql, resultSet -> {
|
||||
// Trigger trigger = new Trigger();
|
||||
// trigger.setDatabaseName(databaseName);
|
||||
// trigger.setSchemaName(schemaName);
|
||||
// trigger.setTriggerName(triggerName);
|
||||
// if (resultSet.next()) {
|
||||
// trigger.setTriggerBody(resultSet.getString("ACTION_STATEMENT"));
|
||||
// }
|
||||
// return trigger;
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// @Override
|
||||
// public Procedure procedure(Connection connection, @NotEmpty String databaseName, String schemaName,
|
||||
// String procedureName) {
|
||||
// String sql = String.format(ROUTINES_SQL, "PROCEDURE", databaseName, procedureName);
|
||||
// return SQLExecutor.getInstance().execute(connection, sql, resultSet -> {
|
||||
// Procedure procedure = new Procedure();
|
||||
// procedure.setDatabaseName(databaseName);
|
||||
// procedure.setSchemaName(schemaName);
|
||||
// procedure.setProcedureName(procedureName);
|
||||
// if (resultSet.next()) {
|
||||
// procedure.setSpecificName(resultSet.getString("SPECIFIC_NAME"));
|
||||
// procedure.setRemarks(resultSet.getString("ROUTINE_COMMENT"));
|
||||
// procedure.setProcedureBody(resultSet.getString("ROUTINE_DEFINITION"));
|
||||
// }
|
||||
// return procedure;
|
||||
// });
|
||||
// }
|
||||
//
|
||||
// private static String VIEW_SQL
|
||||
// = "SELECT TABLE_SCHEMA AS DatabaseName, TABLE_NAME AS ViewName, VIEW_DEFINITION AS definition, CHECK_OPTION, "
|
||||
// + "IS_UPDATABLE FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_SCHEMA = '%s' AND TABLE_NAME = '%s';";
|
||||
//
|
||||
// @Override
|
||||
// public Table view(Connection connection, String databaseName, String schemaName, String viewName) {
|
||||
// String sql = String.format(VIEW_SQL, databaseName, viewName);
|
||||
// return SQLExecutor.getInstance().execute(connection, sql, resultSet -> {
|
||||
// Table table = new Table();
|
||||
// table.setDatabaseName(databaseName);
|
||||
// table.setSchemaName(schemaName);
|
||||
// table.setName(viewName);
|
||||
// if (resultSet.next()) {
|
||||
// table.setDdl(resultSet.getString("definition"));
|
||||
// }
|
||||
// return table;
|
||||
// });
|
||||
// }
|
||||
}
|
||||
|
@ -178,7 +178,6 @@ public class MysqlMetaData extends DefaultMetaService implements MetaData {
|
||||
}
|
||||
|
||||
|
||||
|
||||
private static String VIEW_SQL
|
||||
= "SELECT TABLE_SCHEMA AS DatabaseName, TABLE_NAME AS ViewName, VIEW_DEFINITION AS definition, CHECK_OPTION, "
|
||||
+ "IS_UPDATABLE FROM INFORMATION_SCHEMA.VIEWS WHERE TABLE_SCHEMA = '%s' AND TABLE_NAME = '%s';";
|
||||
@ -271,4 +270,9 @@ public class MysqlMetaData extends DefaultMetaService implements MetaData {
|
||||
.collations(MysqlCollationEnum.getCollations())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMetaDataName(String... names) {
|
||||
return Arrays.stream(names).map(name -> "`" + name + "`").collect(Collectors.joining("."));
|
||||
}
|
||||
}
|
||||
|
@ -281,4 +281,9 @@ public class OracleMetaData extends DefaultMetaService implements MetaData {
|
||||
.collations(Lists.newArrayList())
|
||||
.build();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMetaDataName(String... names) {
|
||||
return Arrays.stream(names).map(name -> "\"" + name + "\"").collect(Collectors.joining("."));
|
||||
}
|
||||
}
|
||||
|
@ -79,6 +79,9 @@ public class OracleSqlBuilder implements SqlBuilder {
|
||||
if (StringUtils.isNotBlank(tableColumn.getEditStatus())) {
|
||||
OracleColumnTypeEnum typeEnum = OracleColumnTypeEnum.getByType(tableColumn.getColumnType());
|
||||
script.append("\t").append(typeEnum.buildModifyColumn(tableColumn)).append(";\n");
|
||||
if(StringUtils.isNotBlank(tableColumn.getComment())){
|
||||
script.append("\n").append(buildComment(tableColumn)).append(";\n");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,9 @@ package ai.chat2db.plugin.sqlite;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import ai.chat2db.spi.MetaData;
|
||||
import ai.chat2db.spi.jdbc.DefaultMetaService;
|
||||
@ -35,4 +37,9 @@ public class SqliteMetaData extends DefaultMetaService implements MetaData {
|
||||
public List<Schema> schemas(Connection connection,String databaseName) {
|
||||
return Lists.newArrayList();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getMetaDataName(String... names) {
|
||||
return Arrays.stream(names).collect(Collectors.joining("."));
|
||||
}
|
||||
}
|
||||
|
@ -17,6 +17,12 @@
|
||||
<groupId>ai.chat2db</groupId>
|
||||
<artifactId>chat2db-spi</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>com.microsoft.sqlserver</groupId>
|
||||
<artifactId>mssql-jdbc</artifactId>
|
||||
<version>11.2.1.jre17</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
@ -0,0 +1,124 @@
|
||||
package ai.chat2db.plugin.sqlserver.builder;
|
||||
|
||||
import ai.chat2db.plugin.sqlserver.type.SqlServerColumnTypeEnum;
|
||||
import ai.chat2db.plugin.sqlserver.type.SqlServerIndexTypeEnum;
|
||||
import ai.chat2db.spi.SqlBuilder;
|
||||
import ai.chat2db.spi.model.Table;
|
||||
import ai.chat2db.spi.model.TableColumn;
|
||||
import ai.chat2db.spi.model.TableIndex;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
public class SqlServerSqlBuilder implements SqlBuilder {
|
||||
@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;
|
||||
}
|
||||
SqlServerColumnTypeEnum typeEnum = SqlServerColumnTypeEnum.getByType(column.getColumnType());
|
||||
script.append("\t").append(typeEnum.buildCreateColumnSql(column)).append(",\n");
|
||||
}
|
||||
|
||||
script = new StringBuilder(script.substring(0, script.length() - 2));
|
||||
script.append("\n)\ngo\n");
|
||||
|
||||
for (TableIndex tableIndex : table.getIndexList()) {
|
||||
if (StringUtils.isBlank(tableIndex.getName()) || StringUtils.isBlank(tableIndex.getType())) {
|
||||
continue;
|
||||
}
|
||||
SqlServerIndexTypeEnum sqlServerIndexTypeEnum = SqlServerIndexTypeEnum.getByType(tableIndex.getType());
|
||||
script.append("\n").append(sqlServerIndexTypeEnum.buildIndexScript(tableIndex));
|
||||
if (StringUtils.isNotBlank(tableIndex.getComment())) {
|
||||
script.append("\n").append(buildIndexComment(tableIndex));
|
||||
}
|
||||
}
|
||||
|
||||
for (TableColumn column : table.getColumnList()) {
|
||||
if (StringUtils.isBlank(column.getName()) || StringUtils.isBlank(column.getColumnType()) || StringUtils.isBlank(column.getComment())) {
|
||||
continue;
|
||||
}
|
||||
script.append("\n").append(buildColumnComment(column));
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(table.getComment())) {
|
||||
script.append("\n").append(buildTableComment(table));
|
||||
}
|
||||
|
||||
|
||||
return script.toString();
|
||||
}
|
||||
|
||||
private static String INDEX_COMMENT_SCRIPT = "exec sp_addextendedproperty 'MS_Description','%s','SCHEMA','%s','TABLE','%s','INDEX','%s' \ngo";
|
||||
|
||||
|
||||
private String buildIndexComment(TableIndex tableIndex) {
|
||||
return String.format(INDEX_COMMENT_SCRIPT, tableIndex.getComment(), tableIndex.getSchemaName(), tableIndex.getTableName(), tableIndex.getName());
|
||||
}
|
||||
|
||||
private static String TABLE_COMMENT_SCRIPT = "exec sp_addextendedproperty 'MS_Description','%s','SCHEMA','%s','TABLE','%s' \ngo";
|
||||
|
||||
|
||||
private String buildTableComment(Table table) {
|
||||
return String.format(TABLE_COMMENT_SCRIPT, table.getComment(), table.getSchemaName(), table.getName());
|
||||
}
|
||||
|
||||
private static String COLUMN_COMMENT_SCRIPT = "exec sp_addextendedproperty 'MS_Description','%s','SCHEMA','%s','TABLE','%s','COLUMN','%s' \ngo";
|
||||
|
||||
private String buildColumnComment(TableColumn column) {
|
||||
return String.format(COLUMN_COMMENT_SCRIPT, column.getComment(), column.getSchemaName(), column.getTableName(), column.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String buildModifyTaleSql(Table oldTable, Table newTable) {
|
||||
StringBuilder script = new StringBuilder();
|
||||
|
||||
if (!StringUtils.equalsIgnoreCase(oldTable.getName(), newTable.getName())) {
|
||||
script.append(buildRenameTable(oldTable, newTable));
|
||||
}
|
||||
if (!StringUtils.equalsIgnoreCase(oldTable.getComment(), newTable.getComment())) {
|
||||
if(oldTable.getComment() == null){
|
||||
script.append("\n").append(buildTableComment(newTable));
|
||||
}else {
|
||||
script.append("\n").append(buildUpdateTableComment(newTable));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// append modify column
|
||||
for (TableColumn tableColumn : newTable.getColumnList()) {
|
||||
if (StringUtils.isNotBlank(tableColumn.getEditStatus())) {
|
||||
SqlServerColumnTypeEnum typeEnum = SqlServerColumnTypeEnum.getByType(tableColumn.getColumnType());
|
||||
script.append(typeEnum.buildModifyColumn(tableColumn)).append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
// append modify index
|
||||
for (TableIndex tableIndex : newTable.getIndexList()) {
|
||||
if (StringUtils.isNotBlank(tableIndex.getEditStatus()) && StringUtils.isNotBlank(tableIndex.getType())) {
|
||||
SqlServerIndexTypeEnum mysqlIndexTypeEnum = SqlServerIndexTypeEnum.getByType(tableIndex.getType());
|
||||
script.append("\t").append(mysqlIndexTypeEnum.buildModifyIndex(tableIndex)).append("\n");
|
||||
if (StringUtils.isNotBlank(tableIndex.getComment())) {
|
||||
script.append("\n").append(buildIndexComment(tableIndex)).append("\ngo");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return script.toString();
|
||||
}
|
||||
|
||||
|
||||
private static String UPDATE_TABLE_COMMENT_SCRIPT = "exec sp_updateextendedproperty 'MS_Description','%s','SCHEMA','%s','TABLE','%s' \ngo";
|
||||
private String buildUpdateTableComment(Table newTable) {
|
||||
return String.format(UPDATE_TABLE_COMMENT_SCRIPT, newTable.getComment(), newTable.getSchemaName(), newTable.getName());
|
||||
}
|
||||
|
||||
private static String RENAME_TABLE_SCRIPT = "exec sp_rename '%s','%s','OBJECT' \ngo";
|
||||
|
||||
private String buildRenameTable(Table oldTable, Table newTable) {
|
||||
return String.format(RENAME_TABLE_SCRIPT, oldTable.getName(), newTable.getName());
|
||||
}
|
||||
}
|
@ -0,0 +1,337 @@
|
||||
package ai.chat2db.plugin.sqlserver.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 SqlServerColumnTypeEnum implements ColumnBuilder {
|
||||
//JSON("JSON", false, false, true, false, false, false, true, false, false, false)
|
||||
|
||||
BIGINT("BIGINT", false, false, true, false, false, false, true, true),
|
||||
|
||||
BINARY("BINARY", false, false, true, false, false, false, true, true),
|
||||
|
||||
BIT("BIT", false, false, true, false, false, false, true, true),
|
||||
|
||||
CHAR("CHAR", true, false, true, false, false, true, true, true),
|
||||
|
||||
DATE("DATE", false, false, true, false, false, false, true, true),
|
||||
|
||||
DATETIME("DATETIME", false, false, true, false, false, false, true, true),
|
||||
|
||||
DATETIME2("DATETIME2", true, false, true, false, false, false, true, true),
|
||||
|
||||
|
||||
DATETIMEOFFSET("DATETIMEOFFSET", true, false, true, false, false, false, true, true),
|
||||
|
||||
|
||||
DECIMAL("DECIMAL", true, true, true, false, false, false, true, true),
|
||||
|
||||
|
||||
FLOAT("FLOAT", true, false, true, false, false, false, true, true),
|
||||
|
||||
|
||||
GEOGRAPHY("GEOGRAPHY", false, false, true, false, false, false, true, true),
|
||||
|
||||
GEOMETRY("GEOMETRY", false, false, true, false, false, false, true, true),
|
||||
|
||||
HIERARCHYID("HIERARCHYID", false, false, true, false, false, false, true, true),
|
||||
|
||||
IMAGE("IMAGE", false, false, true, false, false, false, true, true),
|
||||
|
||||
INT("INT", false, false, true, false, false, false, true, true),
|
||||
|
||||
|
||||
MONEY("MONEY", false, false, true, false, false, false, true, true),
|
||||
|
||||
NCHAR("NCHAR", true, false, true, false, false, true, true, true),
|
||||
|
||||
NTEXT("NTEXT", false, false, true, false, false, false, true, true),
|
||||
|
||||
NUMERIC("NUMERIC", true, true, true, false, false, false, true, true),
|
||||
|
||||
NVARCHAR("NVARCHAR", true, false, true, false, false, true, true, true),
|
||||
|
||||
NVARCHAR_MAX("NVARCHAR(MAX)", false, false, true, false, false, true, true, true),
|
||||
|
||||
|
||||
REAL("REAL", false, false, true, false, false, false, true, true),
|
||||
|
||||
SMALLDATETIME("SMALLDATETIME", false, false, true, false, false, false, true, true),
|
||||
|
||||
SMALLINT("SMALLINT", false, false, true, false, false, false, true, true),
|
||||
|
||||
SMALLMONEY("SMALLMONEY", false, false, true, false, false, false, true, true),
|
||||
|
||||
SQL_VARIANT("SQL_VARIANT", false, false, true, false, false, false, true, true),
|
||||
|
||||
SYSNAME("SYSNAME", false, false, true, false, false, false, true, true),
|
||||
|
||||
TEXT("TEXT", false, false, true, false, false, true, true, true),
|
||||
|
||||
TIME("TIME", true, false, true, false, false, false, true, true),
|
||||
|
||||
TIMESTAMP("TIMESTAMP", false, false, true, false, false, false, true, true),
|
||||
|
||||
|
||||
TINYINT("TINYINT", false, false, true, false, false, false, true, true),
|
||||
|
||||
UNIQUEIDENTIFIER("UNIQUEIDENTIFIER", false, false, true, false, false, false, true, true),
|
||||
|
||||
|
||||
VARBINARY("VARBINARY", true, false, true, false, false, false, true, true),
|
||||
|
||||
VARBINARY_MAX("VARBINARY(MAX)", false, false, true, false, false, false, true, true),
|
||||
|
||||
VARCHAR("VARCHAR", true, false, true, false, false, true, true, true),
|
||||
|
||||
VARCHAR_MAX("VARCHAR(MAX)", false, false, true, false, false, true, true, true),
|
||||
|
||||
XML("XML", false, false, true, false, false, false, true, true),
|
||||
|
||||
|
||||
;
|
||||
private ColumnType columnType;
|
||||
|
||||
public static SqlServerColumnTypeEnum getByType(String dataType) {
|
||||
return COLUMN_TYPE_MAP.get(dataType.toUpperCase());
|
||||
}
|
||||
|
||||
private static Map<String, SqlServerColumnTypeEnum> COLUMN_TYPE_MAP = Maps.newHashMap();
|
||||
|
||||
static {
|
||||
for (SqlServerColumnTypeEnum value : SqlServerColumnTypeEnum.values()) {
|
||||
COLUMN_TYPE_MAP.put(value.getColumnType().getTypeName(), value);
|
||||
}
|
||||
}
|
||||
|
||||
public ColumnType getColumnType() {
|
||||
return columnType;
|
||||
}
|
||||
|
||||
|
||||
SqlServerColumnTypeEnum(String dataTypeName, boolean supportLength, boolean supportScale, boolean supportNullable, boolean supportAutoIncrement, boolean supportCharset, boolean supportCollation, boolean supportComments, boolean supportDefaultValue) {
|
||||
this.columnType = new ColumnType(dataTypeName, supportLength, supportScale, supportNullable, supportAutoIncrement, supportCharset, supportCollation, supportComments, supportDefaultValue, false, false, false);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String buildCreateColumnSql(TableColumn column) {
|
||||
SqlServerColumnTypeEnum type = this;
|
||||
StringBuilder script = new StringBuilder();
|
||||
|
||||
script.append("[").append(column.getName()).append("]").append(" ");
|
||||
|
||||
script.append(buildDataType(column, type)).append(" ");
|
||||
|
||||
script.append(buildSparse(column, type)).append(" ");
|
||||
|
||||
script.append(buildDefaultValue(column, type)).append(" ");
|
||||
|
||||
script.append(buildNullable(column, type)).append(" ");
|
||||
|
||||
script.append(buildCollation(column, type)).append(" ");
|
||||
|
||||
return script.toString();
|
||||
}
|
||||
|
||||
public String buildUpdateColumnSql(TableColumn column) {
|
||||
SqlServerColumnTypeEnum type = this;
|
||||
|
||||
StringBuilder script = new StringBuilder();
|
||||
|
||||
script.append("[").append(column.getName()).append("]").append(" ");
|
||||
|
||||
script.append(buildDataType(column, type)).append(" ");
|
||||
|
||||
script.append(buildNullable(column, type)).append(" \ngo\n");
|
||||
|
||||
if (StringUtils.isNotBlank(column.getDefaultValue()) && column.getOldColumn().getDefaultValue() != null && !StringUtils.equalsIgnoreCase(column.getDefaultValue(), column.getOldColumn().getDefaultValue())) {
|
||||
script.append("ALTER TABLE ").append("[").append(column.getSchemaName()).append("].[").append(column.getTableName()).append("]");
|
||||
script.append(" ").append("DROP CONSTRAINT ").append("[").append(column.getDefaultConstraintName()).append("]");
|
||||
|
||||
script.append("ALTER TABLE ").append("[").append(column.getSchemaName()).append("].[").append(column.getTableName()).append("]");
|
||||
script.append(" ").append("ADD ").append(buildDefaultValue(column, type)).append(" for ").append(column.getName()).append(" \ngo\n");
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(column.getDefaultValue()) && column.getOldColumn().getDefaultValue() == null) {
|
||||
script.append("ALTER TABLE ").append("[").append(column.getSchemaName()).append("].[").append(column.getTableName()).append("]");
|
||||
script.append(" ").append("ADD ").append(buildDefaultValue(column, type)).append(" for ").append(column.getName()).append(" \ngo\n");
|
||||
}
|
||||
|
||||
|
||||
if (column.getSparse() != null && column.getSparse()) {
|
||||
script.append("ALTER TABLE ").append("[").append(column.getSchemaName()).append("].[").append(column.getTableName()).append("]");
|
||||
script.append(" ").append("ALTER COLUMN ").append("[").append(column.getName()).append("]").append(" add ").append("SPARSE").append(" \ngo\n");
|
||||
}
|
||||
|
||||
if (StringUtils.isNotBlank(column.getCollationName())) {
|
||||
script.append("ALTER TABLE ").append("[").append(column.getSchemaName()).append("].[").append(column.getTableName()).append("]");
|
||||
script.append(" ").append("ALTER COLUMN ").append("[").append(column.getName()).append("]").append(" ").append("COLLATE ").append(column.getCollationName()).append(" \ngo\n");
|
||||
}
|
||||
return script.toString();
|
||||
}
|
||||
|
||||
private String buildSparse(TableColumn column, SqlServerColumnTypeEnum type) {
|
||||
if (Boolean.TRUE.equals(column.getSparse())) {
|
||||
return "SPARSE";
|
||||
} else {
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
||||
private String buildCollation(TableColumn column, SqlServerColumnTypeEnum type) {
|
||||
if (!type.getColumnType().isSupportCollation() || StringUtils.isEmpty(column.getCollationName())) {
|
||||
return "";
|
||||
}
|
||||
return StringUtils.join("COLLATE ", column.getCollationName());
|
||||
}
|
||||
|
||||
|
||||
private String buildNullable(TableColumn column, SqlServerColumnTypeEnum type) {
|
||||
if (!type.getColumnType().isSupportNullable()) {
|
||||
return "";
|
||||
}
|
||||
if (column.getNullable() != null && 1 == column.getNullable()) {
|
||||
return "NULL";
|
||||
} else {
|
||||
return "NOT NULL";
|
||||
}
|
||||
}
|
||||
|
||||
private String buildDefaultValue(TableColumn column, SqlServerColumnTypeEnum 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, SqlServerColumnTypeEnum type) {
|
||||
String columnType = type.columnType.getTypeName();
|
||||
if (Arrays.asList(CHAR, NCHAR, NVARCHAR, VARBINARY, VARCHAR).contains(type)) {
|
||||
StringBuilder script = new StringBuilder();
|
||||
script.append(columnType);
|
||||
if (column.getColumnSize() != null) {
|
||||
script.append("(").append(column.getColumnSize()).append(")");
|
||||
}
|
||||
|
||||
return script.toString();
|
||||
}
|
||||
|
||||
if (Arrays.asList(DECIMAL, FLOAT, TIMESTAMP, TIME, DATETIME2, DATETIMEOFFSET, FLOAT, NUMERIC).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().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();
|
||||
}
|
||||
|
||||
|
||||
return columnType;
|
||||
}
|
||||
|
||||
private static String RENAME_COLUMN_SCRIPT = "exec sp_rename '%s.%s','%s','COLUMN' \ngo";
|
||||
|
||||
private String renameColumn(TableColumn tableColumn) {
|
||||
return String.format(RENAME_COLUMN_SCRIPT, tableColumn.getTableName(), tableColumn.getOldName(), tableColumn.getName());
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String buildModifyColumn(TableColumn tableColumn) {
|
||||
|
||||
if (EditStatus.DELETE.name().equals(tableColumn.getEditStatus())) {
|
||||
StringBuilder script = new StringBuilder();
|
||||
if (StringUtils.isNotBlank(tableColumn.getDefaultConstraintName())) {
|
||||
script.append("ALTER TABLE ").append("[").append(tableColumn.getSchemaName()).append("].[").append(tableColumn.getTableName()).append("]");
|
||||
script.append(" ").append("DROP CONSTRAINT ").append("[").append(tableColumn.getDefaultConstraintName()).append("]");
|
||||
script.append("\ngo\n");
|
||||
}
|
||||
script.append("ALTER TABLE ").append("[").append(tableColumn.getSchemaName()).append("].[").append(tableColumn.getTableName()).append("]");
|
||||
script.append(" ").append("DROP COLUMN ").append("[").append(tableColumn.getName()).append("]");
|
||||
script.append("\ngo\n");
|
||||
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(" \ngo\n");
|
||||
return script.toString();
|
||||
}
|
||||
if (EditStatus.MODIFY.name().equals(tableColumn.getEditStatus())) {
|
||||
StringBuilder script = new StringBuilder();
|
||||
|
||||
if (!StringUtils.equalsIgnoreCase(tableColumn.getOldName(), tableColumn.getName())) {
|
||||
script.append(renameColumn(tableColumn));
|
||||
script.append("\n");
|
||||
}
|
||||
script.append("ALTER TABLE ").append("[").append(tableColumn.getSchemaName()).append("].[").append(tableColumn.getTableName()).append("]");
|
||||
script.append(" ").append("ALTER COLUMN ").append(buildUpdateColumnSql(tableColumn)).append(" \n");
|
||||
|
||||
if (StringUtils.isNotBlank(tableColumn.getComment())) {
|
||||
script.append("\n").append(buildModifyColumnComment(tableColumn));
|
||||
}
|
||||
|
||||
return script.toString();
|
||||
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
private static String COLUMN_MODIFY_COMMENT_SCRIPT = "IF ((SELECT COUNT(*) FROM ::fn_listextendedproperty('MS_Description',\n" +
|
||||
"'SCHEMA', N'%s',\n" +
|
||||
"'TABLE', N'%s',\n" +
|
||||
"'COLUMN', N'%s')) > 0)\n" +
|
||||
" EXEC sp_updateextendedproperty\n" +
|
||||
"'MS_Description', N'%s',\n" +
|
||||
"'SCHEMA', N'%s',\n" +
|
||||
"'TABLE', N'%s',\n" +
|
||||
"'COLUMN', N'%s'\n" +
|
||||
"ELSE\n" +
|
||||
" EXEC sp_addextendedproperty\n" +
|
||||
"'MS_Description', N'%s',\n" +
|
||||
"'SCHEMA', N'%s',\n" +
|
||||
"'TABLE', N'%s',\n" +
|
||||
"'COLUMN', N'%s'\n go";
|
||||
|
||||
private String buildModifyColumnComment(TableColumn tableColumn) {
|
||||
return String.format(COLUMN_MODIFY_COMMENT_SCRIPT, tableColumn.getSchemaName(), tableColumn.getTableName(),
|
||||
tableColumn.getName(), tableColumn.getComment(), tableColumn.getSchemaName(), tableColumn.getTableName(), tableColumn.getName(),
|
||||
tableColumn.getComment(), tableColumn.getSchemaName(), tableColumn.getTableName(), tableColumn.getName());
|
||||
}
|
||||
|
||||
public static List<ColumnType> getTypes() {
|
||||
return Arrays.stream(SqlServerColumnTypeEnum.values()).map(columnTypeEnum ->
|
||||
columnTypeEnum.getColumnType()
|
||||
).toList();
|
||||
}
|
||||
}
|
@ -0,0 +1,119 @@
|
||||
package ai.chat2db.plugin.sqlserver.type;
|
||||
|
||||
import ai.chat2db.spi.enums.EditStatus;
|
||||
import ai.chat2db.spi.model.TableIndex;
|
||||
import ai.chat2db.spi.model.TableIndexColumn;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
public enum SqlServerIndexTypeEnum {
|
||||
|
||||
PRIMARY_KEY("Primary", "PRIMARY KEY"),
|
||||
|
||||
// NORMAL("Normal", "INDEX"),
|
||||
//
|
||||
// UNIQUE("Unique", "UNIQUE INDEX"),
|
||||
|
||||
|
||||
UNIQUE_CLUSTERED("UNIQUE CLUSTERED", "UNIQUE CLUSTERED INDEX"),
|
||||
|
||||
CLUSTERED("CLUSTERED", "CLUSTERED INDEX"),
|
||||
|
||||
|
||||
NONCLUSTERED("NONCLUSTERED", "NONCLUSTERED INDEX"),
|
||||
|
||||
UNIQUE_NONCLUSTERED("UNIQUE NONCLUSTERED", "UNIQUE NONCLUSTERED INDEX"),
|
||||
|
||||
SPATIAL("SPATIAL", "SPATIAL INDEX"),
|
||||
|
||||
XML("XML", "XML INDEX");
|
||||
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
private String name;
|
||||
|
||||
|
||||
public String getKeyword() {
|
||||
return keyword;
|
||||
}
|
||||
|
||||
private String keyword;
|
||||
|
||||
SqlServerIndexTypeEnum(String name, String keyword) {
|
||||
this.name = name;
|
||||
this.keyword = keyword;
|
||||
}
|
||||
|
||||
|
||||
public static SqlServerIndexTypeEnum getByType(String type) {
|
||||
for (SqlServerIndexTypeEnum value : SqlServerIndexTypeEnum.values()) {
|
||||
if (value.name.equalsIgnoreCase(type)) {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
//ALTER TABLE [dbo].[Employees] ADD CONSTRAINT [PK__Employee__7AD04FF164ABF7C7] PRIMARY KEY CLUSTERED ([FirstName])
|
||||
|
||||
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 CONSTRAINT ").append(buildIndexName(tableIndex)).append(" ").append(keyword).append(" ").append(buildIndexColumn(tableIndex));
|
||||
} else {
|
||||
script.append("CREATE ").append(keyword).append(" ");
|
||||
script.append(buildIndexName(tableIndex)).append("\n ON [").append(tableIndex.getSchemaName()).append("].[").append(tableIndex.getTableName()).append("] ").append(buildIndexColumn(tableIndex));
|
||||
}
|
||||
script.append("\ngo");
|
||||
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())) {
|
||||
script.append(" ").append(column.getAscOrDesc());
|
||||
}
|
||||
script.append(",");
|
||||
}
|
||||
}
|
||||
script.deleteCharAt(script.length() - 1);
|
||||
script.append(")");
|
||||
return script.toString();
|
||||
}
|
||||
|
||||
private String buildIndexName(TableIndex tableIndex) {
|
||||
return "[" + 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 (SqlServerIndexTypeEnum.PRIMARY_KEY.getName().equals(tableIndex.getType())) {
|
||||
return StringUtils.join("ALTER TABLE [", tableIndex.getSchemaName(), "].[", tableIndex.getTableName(), "] DROP CONSTRAINT ", buildIndexName(tableIndex),"\ngo");
|
||||
}
|
||||
StringBuilder script = new StringBuilder();
|
||||
script.append("DROP INDEX ");
|
||||
script.append(buildIndexName(tableIndex));
|
||||
script.append(" ON [").append(tableIndex.getSchemaName()).append("].[").append(tableIndex.getTableName()).append("] \ngo");
|
||||
|
||||
return script.toString();
|
||||
}
|
||||
}
|
@ -0,0 +1,60 @@
|
||||
package ai.chat2db.server.domain.api.param;
|
||||
|
||||
import ai.chat2db.spi.model.Header;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class UpdateSelectResultParam {
|
||||
/**
|
||||
* 控制台id
|
||||
*/
|
||||
@NotNull
|
||||
private Long consoleId;
|
||||
|
||||
/**
|
||||
* 数据源id
|
||||
*/
|
||||
@NotNull
|
||||
private Long dataSourceId;
|
||||
|
||||
/**
|
||||
* DB名称
|
||||
*/
|
||||
private String databaseName;
|
||||
|
||||
|
||||
/**
|
||||
* schema名称
|
||||
*/
|
||||
private String schemaName;
|
||||
|
||||
|
||||
/**
|
||||
* 展示头的列表
|
||||
*/
|
||||
@NotEmpty
|
||||
private List<Header> headerList;
|
||||
|
||||
|
||||
/**
|
||||
* 修改后数据的列表
|
||||
*/
|
||||
@NotEmpty
|
||||
private List<List<String>> dataList;
|
||||
|
||||
/**
|
||||
* 数据的列表
|
||||
*/
|
||||
@NotEmpty
|
||||
private List<List<String>> oldDataList;
|
||||
|
||||
/**
|
||||
* 表名
|
||||
*/
|
||||
@NotEmpty
|
||||
private String tableName;
|
||||
}
|
@ -86,6 +86,7 @@ public class TableServiceImpl implements TableService {
|
||||
|
||||
@Override
|
||||
public ListResult<Sql> buildSql(Table oldTable, Table newTable) {
|
||||
initOldTable(oldTable, newTable);
|
||||
SqlBuilder sqlBuilder = Chat2DBContext.getSqlBuilder();
|
||||
List<Sql> sqls = new ArrayList<>();
|
||||
if (oldTable == null) {
|
||||
@ -96,6 +97,19 @@ public class TableServiceImpl implements TableService {
|
||||
return ListResult.of(sqls);
|
||||
}
|
||||
|
||||
private void initOldTable(Table oldTable, Table newTable) {
|
||||
if (oldTable == null) {
|
||||
return;
|
||||
}
|
||||
Map<String, TableColumn> columnMap = oldTable.getColumnList().stream().collect(Collectors.toMap(TableColumn::getName, Function.identity()));
|
||||
for (TableColumn newColumn : newTable.getColumnList()) {
|
||||
TableColumn oldColumn = columnMap.get(newColumn.getName());
|
||||
if (oldColumn != null) {
|
||||
newColumn.setOldColumn(oldColumn);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<Table> pageQuery(TablePageQueryParam param, TableSelector selector) {
|
||||
MetaData metaSchema = Chat2DBContext.getMetaData();
|
||||
|
@ -4,6 +4,7 @@ import java.sql.Connection;
|
||||
import java.util.List;
|
||||
|
||||
import ai.chat2db.server.domain.api.param.DlExecuteParam;
|
||||
import ai.chat2db.server.domain.api.param.UpdateSelectResultParam;
|
||||
import ai.chat2db.server.domain.api.service.DlTemplateService;
|
||||
import ai.chat2db.server.tools.base.wrapper.result.DataResult;
|
||||
import ai.chat2db.server.tools.base.wrapper.result.ListResult;
|
||||
@ -11,6 +12,7 @@ import ai.chat2db.server.web.api.aspect.ConnectionInfoAspect;
|
||||
import ai.chat2db.server.web.api.controller.rdb.converter.RdbWebConverter;
|
||||
import ai.chat2db.server.web.api.controller.rdb.request.DdlCountRequest;
|
||||
import ai.chat2db.server.web.api.controller.rdb.request.DmlRequest;
|
||||
import ai.chat2db.server.web.api.controller.rdb.request.SelectResultUpdateRequest;
|
||||
import ai.chat2db.server.web.api.controller.rdb.vo.ExecuteResultVO;
|
||||
import ai.chat2db.spi.model.ExecuteResult;
|
||||
import ai.chat2db.spi.sql.Chat2DBContext;
|
||||
@ -54,6 +56,20 @@ public class RdbDmlController {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* update 查询结果
|
||||
*
|
||||
* @param request
|
||||
* @return
|
||||
*/
|
||||
@RequestMapping(value = "/execute_update", method = {RequestMethod.POST, RequestMethod.PUT})
|
||||
public DataResult<String> executeUpdate(@RequestBody SelectResultUpdateRequest request) {
|
||||
UpdateSelectResultParam param = rdbWebConverter.request2param(request);
|
||||
return dlTemplateService.updateSelectResult(param);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 增删改查等数据运维
|
||||
*
|
||||
|
@ -174,11 +174,13 @@ public class TableController {
|
||||
tableIndex.setTableName(table.getName());
|
||||
tableIndex.setDatabaseName(request.getDatabaseName());
|
||||
}
|
||||
|
||||
return tableService.buildSql(rdbWebConverter.tableRequest2param(request.getOldTable()),table)
|
||||
.map(rdbWebConverter::dto2vo);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* 数据库支持的数据类型
|
||||
*
|
||||
|
@ -2,22 +2,9 @@ package ai.chat2db.server.web.api.controller.rdb.converter;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import ai.chat2db.server.domain.api.param.DlCountParam;
|
||||
import ai.chat2db.server.domain.api.param.DlExecuteParam;
|
||||
import ai.chat2db.server.domain.api.param.DropParam;
|
||||
import ai.chat2db.server.domain.api.param.ShowCreateTableParam;
|
||||
import ai.chat2db.server.domain.api.param.TablePageQueryParam;
|
||||
import ai.chat2db.server.domain.api.param.TableQueryParam;
|
||||
import ai.chat2db.server.domain.api.param.*;
|
||||
import ai.chat2db.server.web.api.controller.data.source.vo.DatabaseVO;
|
||||
import ai.chat2db.server.web.api.controller.rdb.request.DataExportRequest;
|
||||
import ai.chat2db.server.web.api.controller.rdb.request.DdlCountRequest;
|
||||
import ai.chat2db.server.web.api.controller.rdb.request.DdlExportRequest;
|
||||
import ai.chat2db.server.web.api.controller.rdb.request.DdlRequest;
|
||||
import ai.chat2db.server.web.api.controller.rdb.request.DmlRequest;
|
||||
import ai.chat2db.server.web.api.controller.rdb.request.TableBriefQueryRequest;
|
||||
import ai.chat2db.server.web.api.controller.rdb.request.TableDeleteRequest;
|
||||
import ai.chat2db.server.web.api.controller.rdb.request.TableDetailQueryRequest;
|
||||
import ai.chat2db.server.web.api.controller.rdb.request.TableRequest;
|
||||
import ai.chat2db.server.web.api.controller.rdb.request.*;
|
||||
import ai.chat2db.server.web.api.controller.rdb.vo.ColumnVO;
|
||||
import ai.chat2db.server.web.api.controller.rdb.vo.ExecuteResultVO;
|
||||
import ai.chat2db.server.web.api.controller.rdb.vo.IndexVO;
|
||||
@ -234,4 +221,7 @@ public abstract class RdbWebConverter {
|
||||
public abstract List<DatabaseVO> databaseDto2vo(List<Database> dto);
|
||||
|
||||
public abstract MetaSchemaVO metaSchemaDto2vo(MetaSchema data);
|
||||
|
||||
|
||||
public abstract UpdateSelectResultParam request2param(SelectResultUpdateRequest request);
|
||||
}
|
||||
|
@ -0,0 +1,44 @@
|
||||
package ai.chat2db.server.web.api.controller.rdb.request;
|
||||
|
||||
import ai.chat2db.server.web.api.controller.data.source.request.DataSourceBaseRequest;
|
||||
import ai.chat2db.server.web.api.controller.data.source.request.DataSourceConsoleRequestInfo;
|
||||
import ai.chat2db.server.web.api.controller.rdb.vo.HeaderVO;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@Data
|
||||
public class SelectResultUpdateRequest extends DataSourceBaseRequest implements DataSourceConsoleRequestInfo {
|
||||
|
||||
/**
|
||||
* 展示头的列表
|
||||
*/
|
||||
private List<HeaderVO> headerList;
|
||||
|
||||
/**
|
||||
* 修改后数据的列表
|
||||
*/
|
||||
private List<List<String>> dataList;
|
||||
|
||||
/**
|
||||
* 数据的列表
|
||||
*/
|
||||
private List<List<String>> oldDataList;
|
||||
|
||||
/**
|
||||
* 表名
|
||||
*/
|
||||
private String tableName;
|
||||
|
||||
/**
|
||||
* 控制台id
|
||||
*/
|
||||
@NotNull
|
||||
private Long consoleId;
|
||||
@Override
|
||||
public Long getConsoleId() {
|
||||
return consoleId;
|
||||
}
|
||||
|
||||
}
|
@ -175,7 +175,6 @@ public interface MetaData {
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* @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);
|
||||
|
||||
|
||||
/**
|
||||
* Get meta data name.
|
||||
*
|
||||
* @param names
|
||||
* @return
|
||||
*/
|
||||
String getMetaDataName(String ...names);
|
||||
|
||||
|
||||
}
|
@ -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
|
||||
@ -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;
|
||||
}
|
||||
|
@ -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<>();
|
||||
// 创建表
|
||||
@ -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);
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user