feat:support Serializable

This commit is contained in:
SwallowGG
2024-03-15 14:07:51 +08:00
parent 3ae6f88247
commit 0fe586d263
33 changed files with 207 additions and 239 deletions

View File

@ -250,6 +250,10 @@ export const dataSourceFormConfigs: IConnectionConfig[] = [
{
"key": "zeroDateTimeBehavior",
"value": "convertToNull"
},
{
"key": "useInformationSchema",
"value": "true"
}
],
type: DatabaseTypeCode.MYSQL,

View File

@ -11,7 +11,7 @@ import ai.chat2db.spi.model.TableIndex;
import org.apache.commons.lang3.StringUtils;
public class ClickHouseSqlBuilder extends DefaultSqlBuilder implements SqlBuilder {
public class ClickHouseSqlBuilder extends DefaultSqlBuilder {
@Override
public String buildCreateTableSql(Table table) {
StringBuilder script = new StringBuilder();

View File

@ -5,7 +5,7 @@ import ai.chat2db.spi.jdbc.DefaultSqlBuilder;
import ai.chat2db.spi.model.Schema;
import org.apache.commons.lang3.StringUtils;
public class H2SqlBuilder extends DefaultSqlBuilder implements SqlBuilder {
public class H2SqlBuilder extends DefaultSqlBuilder {
@Override
public String buildCreateSchemaSql(Schema schema) {

View File

@ -14,7 +14,7 @@ import java.util.Map;
import java.util.stream.Collectors;
public class KingBaseSqlBuilder extends DefaultSqlBuilder implements SqlBuilder {
public class KingBaseSqlBuilder extends DefaultSqlBuilder {
@Override
public String buildCreateTableSql(Table table) {
StringBuilder script = new StringBuilder();

View File

@ -0,0 +1,17 @@
package ai.chat2db.plugin.mongodb;
import ai.chat2db.spi.model.Command;
import ai.chat2db.spi.model.ExecuteResult;
import ai.chat2db.spi.sql.SQLExecutor;
import java.util.List;
public class MongodbCommandExecutor extends SQLExecutor {
@Override
public List<ExecuteResult> executeSelectTable(Command command) {
String sql = "db." + command.getTableName() + ".find()";
command.setScript(sql);
return execute(command);
}
}

View File

@ -1,9 +1,9 @@
package ai.chat2db.plugin.mongodb;
import ai.chat2db.spi.CommandExecutor;
import ai.chat2db.spi.MetaData;
import ai.chat2db.spi.jdbc.DefaultMetaService;
import ai.chat2db.spi.model.Database;
import ai.chat2db.spi.sql.SQLExecutor;
import com.google.common.collect.Lists;
import java.sql.Connection;
@ -17,4 +17,9 @@ public class MongodbMetaData extends DefaultMetaService implements MetaData {
public List<Database> databases(Connection connection) {
return Lists.newArrayList();
}
@Override
public CommandExecutor getCommandExecutor() {
return new MongodbCommandExecutor();
}
}

View File

@ -14,7 +14,7 @@ import org.apache.commons.lang3.StringUtils;
import java.util.*;
public class MysqlSqlBuilder extends DefaultSqlBuilder implements SqlBuilder {
public class MysqlSqlBuilder extends DefaultSqlBuilder {
@Override
public String buildCreateTableSql(Table table) {
StringBuilder script = new StringBuilder();

View File

@ -2,14 +2,13 @@ package ai.chat2db.plugin.oracle.builder;
import ai.chat2db.plugin.oracle.type.OracleColumnTypeEnum;
import ai.chat2db.plugin.oracle.type.OracleIndexTypeEnum;
import ai.chat2db.spi.SqlBuilder;
import ai.chat2db.spi.jdbc.DefaultSqlBuilder;
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 OracleSqlBuilder extends DefaultSqlBuilder implements SqlBuilder {
public class OracleSqlBuilder extends DefaultSqlBuilder {
@Override
public String buildCreateTableSql(Table table) {
StringBuilder script = new StringBuilder();

View File

@ -2,7 +2,6 @@ package ai.chat2db.plugin.postgresql.builder;
import ai.chat2db.plugin.postgresql.type.PostgreSQLColumnTypeEnum;
import ai.chat2db.plugin.postgresql.type.PostgreSQLIndexTypeEnum;
import ai.chat2db.spi.SqlBuilder;
import ai.chat2db.spi.jdbc.DefaultSqlBuilder;
import ai.chat2db.spi.model.*;
import org.apache.commons.collections4.CollectionUtils;
@ -14,7 +13,7 @@ import java.util.Map;
import java.util.stream.Collectors;
public class PostgreSQLSqlBuilder extends DefaultSqlBuilder implements SqlBuilder {
public class PostgreSQLSqlBuilder extends DefaultSqlBuilder {
@Override
public String buildCreateTableSql(Table table) {
StringBuilder script = new StringBuilder();

View File

@ -1,34 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>ai.chat2db</groupId>
<artifactId>chat2db-plugins</artifactId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<dependencies>
<dependency>
<groupId>ai.chat2db</groupId>
<artifactId>chat2db-spi</artifactId>
</dependency>
</dependencies>
<artifactId>chat2db-redis</artifactId>
<build>
<resources>
<resource>
<directory>src/main/java</directory>
<includes>
<!--The properties configuration file will be placed together with the compiled class file-->
<include>**/*.json</include>
</includes>
</resource>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
</build>
</project>

View File

@ -1,8 +0,0 @@
package ai.chat2db.plugin.redis;
import ai.chat2db.spi.DBManage;
import ai.chat2db.spi.jdbc.DefaultDBManage;
public class RedisDBManage extends DefaultDBManage implements DBManage {
}

View File

@ -1,57 +0,0 @@
package ai.chat2db.plugin.redis;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;
import ai.chat2db.spi.MetaData;
import ai.chat2db.spi.jdbc.DefaultMetaService;
import ai.chat2db.spi.model.Database;
import ai.chat2db.spi.model.Table;
import ai.chat2db.spi.sql.SQLExecutor;
import org.apache.commons.lang3.StringUtils;
public class RedisMetaData extends DefaultMetaService implements MetaData {
@Override
public List<Database> databases(Connection connection) {
List<Database> databases = new ArrayList<>();
return SQLExecutor.getInstance().execute(connection,"config get databases", resultSet -> {
try {
if (resultSet.next()) {
Object count = resultSet.getObject(2);
if(StringUtils.isNotBlank(count.toString())) {
for (int i = 0; i < Integer.parseInt(count.toString()); i++) {
Database database = Database.builder().name(String.valueOf(i)).build();
databases.add(database);
}
}
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
return databases;
});
}
@Override
public List<Table> tables(Connection connection, String databaseName, String schemaName, String tableName) {
return SQLExecutor.getInstance().execute(connection,"scan 0 MATCH * COUNT 1000", resultSet -> {
List<Table> tables = new ArrayList<>();
try {
while (resultSet.next()) {
ArrayList list = (ArrayList)resultSet.getObject(2);
for (Object object : list) {
Table table = new Table();
table.setName(object.toString());
tables.add(table);
}
}
} catch (SQLException e) {
throw new RuntimeException(e);
}
return tables;
});
}
}

View File

@ -1,27 +0,0 @@
package ai.chat2db.plugin.redis;
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 RedisPlugin implements Plugin {
@Override
public DBConfig getDBConfig() {
return FileUtils.readJsonValue(this.getClass(),"redis.json", DBConfig.class);
}
@Override
public MetaData getMetaData() {
return new RedisMetaData();
}
@Override
public DBManage getDBManage() {
return new RedisDBManage();
}
}

View File

@ -1,18 +0,0 @@
{
"dbType": "REDIS",
"supportDatabase": false,
"supportSchema": false,
"driverConfigList": [
{
"url": "jdbc:redis://127.0.0.1:6379/0",
"custom": false,
"defaultDriver": true,
"downloadJdbcDriverUrls": [
"https://oss.sqlgpt.cn/lib/redis-jdbc-driver-1.3.jar"
],
"jdbcDriver": "redis-jdbc-driver-1.3.jar",
"jdbcDriverClass": "jdbc.RedisDriver"
}
],
"name": "Redis"
}

View File

@ -10,7 +10,7 @@ import ai.chat2db.spi.model.TableIndex;
import org.apache.commons.lang3.StringUtils;
public class SqliteBuilder extends DefaultSqlBuilder implements SqlBuilder {
public class SqliteBuilder extends DefaultSqlBuilder {
@Override
public String buildCreateTableSql(Table table) {
StringBuilder script = new StringBuilder();

View File

@ -8,7 +8,7 @@ import ai.chat2db.spi.model.*;
import ai.chat2db.spi.sql.Chat2DBContext;
import org.apache.commons.lang3.StringUtils;
public class SqlServerSqlBuilder extends DefaultSqlBuilder implements SqlBuilder {
public class SqlServerSqlBuilder extends DefaultSqlBuilder {
@Override
public String buildCreateTableSql(Table table) {
StringBuilder script = new StringBuilder();

View File

@ -28,7 +28,6 @@
<module>chat2db-mongodb</module>
<module>chat2db-presto</module>
<module>chat2db-hive</module>
<module>chat2db-redis</module>
<module>chat2db-kingbase</module>
</modules>

View File

@ -37,6 +37,9 @@ public class DlExecuteParam {
private String databaseName;
private String tableName;
/**
* schema name
*/

View File

@ -27,6 +27,14 @@ public interface DlTemplateService {
ListResult<ExecuteResult> execute(DlExecuteParam param);
/**
*
* @param param
* @return
*/
ListResult<ExecuteResult> executeSelectTable(DlExecuteParam param);
/**
* Data source execution update
*

View File

@ -111,11 +111,6 @@
<artifactId>chat2db-presto</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>ai.chat2db</groupId>
<artifactId>chat2db-redis</artifactId>
<version>${revision}</version>
</dependency>
<dependency>
<groupId>ai.chat2db</groupId>
<artifactId>chat2db-sqlite</artifactId>

View File

@ -17,7 +17,6 @@ import ai.chat2db.spi.ValueHandler;
import ai.chat2db.spi.model.*;
import ai.chat2db.spi.sql.Chat2DBContext;
import ai.chat2db.spi.sql.ConnectInfo;
import ai.chat2db.spi.sql.SQLExecutor;
import ai.chat2db.spi.util.JdbcUtils;
import ai.chat2db.spi.util.SqlUtils;
import com.alibaba.druid.DbType;
@ -28,6 +27,7 @@ import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
@ -61,12 +61,15 @@ public class DlTemplateServiceImpl implements DlTemplateService {
CommandExecutor executor = Chat2DBContext.getMetaData().getCommandExecutor();
Command command = commandConverter.param2model(param);
List<ExecuteResult> results = executor.execute(command);
return reBuildHeader(results,param.getSchemaName(),param.getDatabaseName());
}
private ListResult<ExecuteResult> reBuildHeader(List<ExecuteResult> results,String schemaName,String databaseName){
ListResult<ExecuteResult> listResult = ListResult.of(results);
for (ExecuteResult executeResult : results) {
List<Header> headers = executeResult.getHeaderList();
if (executeResult.getSuccess() && executeResult.isCanEdit() && CollectionUtils.isNotEmpty(headers)) {
headers = setColumnInfo(headers, executeResult.getTableName(), param.getSchemaName(),
param.getDatabaseName());
headers = setColumnInfo(headers, executeResult.getTableName(), schemaName, databaseName);
executeResult.setHeaderList(headers);
}
if (!executeResult.getSuccess()) {
@ -77,12 +80,13 @@ public class DlTemplateServiceImpl implements DlTemplateService {
addOperationLog(executeResult);
}
return listResult;
}
// if ("SQLSERVER".equalsIgnoreCase(type)) {
// RemoveSpecialGO(param);
// }
@Override
public ListResult<ExecuteResult> executeSelectTable(DlExecuteParam param) {
Command command = commandConverter.param2model(param);
List<ExecuteResult> results = Chat2DBContext.getMetaData().getCommandExecutor().executeSelectTable(command);
return reBuildHeader(results,param.getSchemaName(),param.getDatabaseName());
}
@Override
@ -159,8 +163,9 @@ public class DlTemplateServiceImpl implements DlTemplateService {
@Override
public DataResult<String> updateSelectResult(UpdateSelectResultParam param) {
SqlBuilder sqlBuilder = Chat2DBContext.getSqlBuilder();
String sql = sqlBuilder.generateSqlBasedOnResults(param.getTableName(), param.getHeaderList(),
param.getOperations());
QueryResult queryResult = new QueryResult();
BeanUtils.copyProperties(param, queryResult);
String sql = sqlBuilder.buildSqlByQuery(queryResult);
return DataResult.of(sql);
}

View File

@ -97,18 +97,7 @@ public class RdbDmlController {
@RequestMapping(value = "/execute_table", method = {RequestMethod.POST, RequestMethod.PUT})
public ListResult<ExecuteResultVO> executeTable(@RequestBody DmlTableRequest request) {
DlExecuteParam param = rdbWebConverter.request2param(request);
// parse sql
String type = Chat2DBContext.getConnectInfo().getDbType();
MetaData metaData = Chat2DBContext.getMetaData();
if (DataSourceTypeEnum.MONGODB.getCode().equals(type)) {
param.setSql("db." + request.getTableName() + ".find()");
} else if (DataSourceTypeEnum.SQLSERVER.getCode().equals(type)){
param.setSql("select * from" + metaData.getMetaDataName(request.getSchemaName()) + "." + metaData.getMetaDataName(request.getTableName()));
}else {
// Splice `tableName` to avoid the problem of keywords being occupied
param.setSql("select * from " + metaData.getMetaDataName(request.getTableName()));
}
return dlTemplateService.execute(param)
return dlTemplateService.executeSelectTable(param)
.map(rdbWebConverter::dto2vo);
}

View File

@ -86,4 +86,21 @@
<artifactId>bson</artifactId>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-source-plugin</artifactId>
<version>3.2.1</version> <!-- 使用最新版本 -->
<executions>
<execution>
<id>attach-sources</id>
<goals>
<goal>jar</goal> <!-- 打包源代码成jar -->
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>

View File

@ -27,6 +27,12 @@ public interface CommandExecutor {
ExecuteResult executeUpdate(String sql, Connection connection, int n)throws SQLException;
/**
* Execute command
*/
List<ExecuteResult> executeSelectTable(Command command);
/**
*
*

View File

@ -3,7 +3,9 @@ package ai.chat2db.spi;
import java.sql.Connection;
import java.util.List;
import ai.chat2db.server.tools.base.wrapper.result.PageResult;
import ai.chat2db.spi.model.*;
import cn.hutool.db.Page;
import jakarta.validation.constraints.NotEmpty;
/**
@ -52,6 +54,19 @@ public interface MetaData {
*/
List<Table> tables(Connection connection, @NotEmpty String databaseName, String schemaName, String tableName);
/**
* Querying all table under a schema.
*
* @param connection
* @param databaseName
* @param schemaName
* @param tableNamePattern
* @param pageNo
* @param pageSize
* @return
*/
PageResult<Table> tables(Connection connection, String databaseName, String schemaName, String tableNamePattern, int pageNo, int pageSize);
/**
* Querying view information.
*

View File

@ -4,7 +4,7 @@ import ai.chat2db.spi.model.*;
import java.util.List;
public interface SqlBuilder {
public interface SqlBuilder<T> {
/**
* Generate create table sql
@ -12,7 +12,7 @@ public interface SqlBuilder {
* @param table
* @return
*/
String buildCreateTableSql(Table table);
String buildCreateTableSql(T table);
/**
@ -22,7 +22,7 @@ public interface SqlBuilder {
* @param oldTable
* @return
*/
String buildModifyTaleSql(Table oldTable, Table newTable);
String buildModifyTaleSql(T oldTable, T newTable);
/**
@ -79,7 +79,7 @@ public interface SqlBuilder {
/**
* generate sql based on results
*/
String generateSqlBasedOnResults(String tableName, List<Header> headerList, List<ResultOperation> operations);
String buildSqlByQuery(QueryResult queryResult);
/**
* DML SQL
@ -87,5 +87,5 @@ public interface SqlBuilder {
* @param type
* @return
*/
String getTableDmlSql(Table table,String type);
String getTableDmlSql(T table,String type);
}

View File

@ -3,9 +3,9 @@ package ai.chat2db.spi.jdbc;
import java.sql.Connection;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import ai.chat2db.server.tools.base.wrapper.result.PageResult;
import ai.chat2db.spi.CommandExecutor;
import ai.chat2db.spi.MetaData;
import ai.chat2db.spi.SqlBuilder;
@ -48,6 +48,16 @@ public class DefaultMetaService implements MetaData {
return SQLExecutor.getInstance().tables(connection, StringUtils.isEmpty(databaseName) ? null : databaseName, StringUtils.isEmpty(schemaName) ? null : schemaName, tableName, new String[]{"TABLE","SYSTEM TABLE"});
}
@Override
public PageResult<Table> tables(Connection connection, String databaseName, String schemaName, String tableNamePattern, int pageNo, int pageSize) {
List<Table> tables = tables(connection, databaseName, schemaName, tableNamePattern);
if(CollectionUtils.isEmpty(tables)){
return PageResult.of(tables,0L,pageNo, pageSize);
}
List result = tables.stream().skip((pageNo - 1) * pageSize).limit(pageSize).collect(Collectors.toList());
return PageResult.of(result, (long) tables.size(), pageNo, pageSize);
}
@Override
public Table view(Connection connection, String databaseName, String schemaName, String viewName) {
return null;

View File

@ -19,7 +19,7 @@ import org.apache.commons.lang3.StringUtils;
import java.util.ArrayList;
import java.util.List;
public class DefaultSqlBuilder implements SqlBuilder {
public class DefaultSqlBuilder implements SqlBuilder<Table> {
@Override
@ -90,8 +90,10 @@ public class DefaultSqlBuilder implements SqlBuilder {
}
@Override
public String generateSqlBasedOnResults(String tableName, List<Header> headerList, List<ResultOperation> operations) {
public String buildSqlByQuery(QueryResult queryResult) {
List<Header> headerList = queryResult.getHeaderList();
List<ResultOperation> operations = queryResult.getOperations();
String tableName = queryResult.getTableName();
StringBuilder stringBuilder = new StringBuilder();
MetaData metaSchema = Chat2DBContext.getMetaData();
List<String> keyColumns = getPrimaryColumns(headerList);

View File

@ -38,6 +38,11 @@ public class Command implements Serializable {
*/
private String schemaName;
/**
*
*/
private String tableName;
/**
*Page coding
* Only available for select statements

View File

@ -2,6 +2,7 @@ package ai.chat2db.spi.model;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
import lombok.AllArgsConstructor;
import lombok.Data;
@ -104,7 +105,12 @@ public class ExecuteResult implements Serializable {
private boolean canEdit;
/**
* Table Name
* Table Name for the result
*/
private String tableName;
/**
* Extra information that can be used by the plugin
*/
private Map<String,Object> extra;
}

View File

@ -0,0 +1,16 @@
package ai.chat2db.spi.model;
import lombok.Data;
import java.io.Serializable;
import java.util.List;
import java.util.Map;
@Data
public class QueryResult implements Serializable {
private String tableName;
private List<Header> headerList;
private List<ResultOperation> operations;
private Map<String, Object> extra;
}

View File

@ -16,6 +16,7 @@ import ai.chat2db.server.tools.base.excption.BusinessException;
import ai.chat2db.server.tools.common.util.EasyCollectionUtils;
import ai.chat2db.server.tools.common.util.I18nUtils;
import ai.chat2db.spi.CommandExecutor;
import ai.chat2db.spi.MetaData;
import ai.chat2db.spi.ValueHandler;
import ai.chat2db.spi.enums.DataTypeEnum;
import ai.chat2db.spi.enums.SqlTypeEnum;
@ -74,6 +75,7 @@ public class SQLExecutor implements CommandExecutor {
}
return null;
}
public void execute(Connection connection, String sql, ResultSetConsumer consumer) {
log.info("execute:{}", sql);
try (Statement stmt = connection.createStatement()) {
@ -168,9 +170,20 @@ public class SQLExecutor implements CommandExecutor {
return executeResult;
}
@Override
public List<ExecuteResult> executeSelectTable(Command command) {
MetaData metaData = Chat2DBContext.getMetaData();
String tableName = metaData.getMetaDataName(command.getDatabaseName(), command.getSchemaName(),
command.getTableName());
String sql = "select * from " + tableName;
command.setScript(sql);
return execute(command);
}
/**
* Executes the given SQL query using the provided connection.
*
* @param sql The SQL query to be executed.
* @param connection The database connection to use for the query.
* @param limitRowSize Flag to indicate if row size should be limited.