mirror of
https://github.com/CodePhiliaX/Chat2DB.git
synced 2025-07-29 10:43:06 +08:00
Supports fuzzy query of table names, not case sensitive.
Automatically add pagination parameters when users query SQL without pagination parameters. Sort the database schema and prioritize the user-defined ones.
This commit is contained in:
@ -2,12 +2,26 @@ package ai.chat2db.plugin.db2;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import ai.chat2db.plugin.db2.builder.DB2SqlBuilder;
|
||||
import ai.chat2db.spi.MetaData;
|
||||
import ai.chat2db.spi.SqlBuilder;
|
||||
import ai.chat2db.spi.jdbc.DefaultMetaService;
|
||||
import ai.chat2db.spi.jdbc.DefaultSqlBuilder;
|
||||
import ai.chat2db.spi.model.Schema;
|
||||
import ai.chat2db.spi.sql.SQLExecutor;
|
||||
import ai.chat2db.spi.util.SortUtils;
|
||||
|
||||
public class DB2MetaData extends DefaultMetaService implements MetaData {
|
||||
|
||||
private List<String> systemSchemas = Arrays.asList("NULLID","SQLJ","SYSCAT","SYSFUN","SYSIBM","SYSIBMADM","SYSIBMINTERNAL","SYSIBMTS","SYSPROC","SYSPUBLIC","SYSSTAT","SYSTOOLS");
|
||||
@Override
|
||||
public List<Schema> schemas(Connection connection, String databaseName) {
|
||||
List<Schema> schemas = SQLExecutor.getInstance().schemas(connection, databaseName, null);
|
||||
return SortUtils.sortSchema(schemas, systemSchemas);
|
||||
}
|
||||
private String functionSQL
|
||||
= "CREATE FUNCTION tableSchema.ufn_GetCreateTableScript( @schema_name NVARCHAR(128), @table_name NVARCHAR"
|
||||
+ "(128)) RETURNS NVARCHAR(MAX) AS BEGIN DECLARE @CreateTableScript NVARCHAR(MAX); DECLARE @IndexScripts "
|
||||
@ -40,7 +54,6 @@ public class DB2MetaData extends DefaultMetaService implements MetaData {
|
||||
@Override
|
||||
public String tableDDL(Connection connection, String databaseName, String schemaName, String tableName) {
|
||||
try {
|
||||
System.out.println(functionSQL);
|
||||
SQLExecutor.getInstance().executeSql(connection, functionSQL.replace("tableSchema", schemaName), resultSet -> null);
|
||||
} catch (Exception e) {
|
||||
//log.error("创建函数失败", e);
|
||||
@ -59,6 +72,9 @@ public class DB2MetaData extends DefaultMetaService implements MetaData {
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public SqlBuilder getSqlBuilder() {
|
||||
return new DB2SqlBuilder();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,23 @@
|
||||
package ai.chat2db.plugin.db2.builder;
|
||||
|
||||
import ai.chat2db.spi.SqlBuilder;
|
||||
import ai.chat2db.spi.jdbc.DefaultSqlBuilder;
|
||||
|
||||
public class DB2SqlBuilder extends DefaultSqlBuilder {
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String pageLimit(String sql, int offset, int pageNo, int pageSize) {
|
||||
int startRow = offset + 1;
|
||||
int endRow = offset+ pageSize;
|
||||
StringBuilder sqlBuilder = new StringBuilder(sql.length() + 120);
|
||||
sqlBuilder.append("SELECT * FROM (SELECT TMP_PAGE.*,ROWNUMBER() OVER() AS PAGEHELPER_ROW_ID FROM ( \n");
|
||||
sqlBuilder.append(sql);
|
||||
sqlBuilder.append("\n ) AS TMP_PAGE) TMP_PAGE WHERE PAGEHELPER_ROW_ID BETWEEN ");
|
||||
sqlBuilder.append(startRow);
|
||||
sqlBuilder.append(" AND ");
|
||||
sqlBuilder.append(endRow);
|
||||
return sqlBuilder.toString();
|
||||
}
|
||||
}
|
@ -3,19 +3,26 @@ package ai.chat2db.plugin.dm;
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import ai.chat2db.spi.MetaData;
|
||||
import ai.chat2db.spi.jdbc.DefaultMetaService;
|
||||
import ai.chat2db.spi.model.Function;
|
||||
import ai.chat2db.spi.model.Procedure;
|
||||
import ai.chat2db.spi.model.Table;
|
||||
import ai.chat2db.spi.model.Trigger;
|
||||
import ai.chat2db.spi.model.*;
|
||||
import ai.chat2db.spi.sql.SQLExecutor;
|
||||
import ai.chat2db.spi.util.SortUtils;
|
||||
import ai.chat2db.spi.util.SqlUtils;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
|
||||
public class DMMetaData extends DefaultMetaService implements MetaData {
|
||||
|
||||
private List<String> systemSchemas = Arrays.asList("CTISYS", "SYS","SYSDBA","SYSSSO","SYSAUDITOR");
|
||||
|
||||
@Override
|
||||
public List<Schema> schemas(Connection connection, String databaseName) {
|
||||
List<Schema> schemas = SQLExecutor.getInstance().schemas(connection, databaseName, null);
|
||||
return SortUtils.sortSchema(schemas, systemSchemas);
|
||||
}
|
||||
public String tableDDL(Connection connection, String databaseName, String schemaName, String tableName) {
|
||||
String selectObjectDDLSQL = String.format(
|
||||
"select dbms_metadata.get_ddl(%s, %s, %s) AS \"sql\" from dual",
|
||||
|
@ -3,21 +3,24 @@ package ai.chat2db.plugin.h2;
|
||||
import java.sql.Connection;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.ResultSetMetaData;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
import ai.chat2db.spi.MetaData;
|
||||
import ai.chat2db.spi.jdbc.DefaultMetaService;
|
||||
import ai.chat2db.spi.model.Function;
|
||||
import ai.chat2db.spi.model.Procedure;
|
||||
import ai.chat2db.spi.model.Table;
|
||||
import ai.chat2db.spi.model.Trigger;
|
||||
import ai.chat2db.spi.model.*;
|
||||
import ai.chat2db.spi.sql.SQLExecutor;
|
||||
import ai.chat2db.spi.util.SortUtils;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
|
||||
public class H2Meta extends DefaultMetaService implements MetaData {
|
||||
|
||||
|
||||
private List<String> systemSchemas = Arrays.asList("INFORMATION_SCHEMA");
|
||||
@Override
|
||||
public List<Schema> schemas(Connection connection, String databaseName) {
|
||||
List<Schema> schemas = SQLExecutor.getInstance().schemas(connection, databaseName, null);
|
||||
return SortUtils.sortSchema(schemas, systemSchemas);
|
||||
}
|
||||
@Override
|
||||
public String tableDDL(Connection connection, @NotEmpty String databaseName, String schemaName,
|
||||
@NotEmpty String tableName) {
|
||||
@ -69,19 +72,13 @@ public class H2Meta extends DefaultMetaService implements MetaData {
|
||||
createTableDDL.append(tableName).append(" (\n");
|
||||
createTableDDL.append(String.join(",\n", columnDefinitions));
|
||||
createTableDDL.append("\n);\n");
|
||||
|
||||
System.out.println("DDL建表语句:");
|
||||
System.out.println(createTableDDL.toString());
|
||||
|
||||
// 输出索引信息
|
||||
System.out.println("\nDDL索引语句:");
|
||||
for (Map.Entry<String, List<String>> entry : indexMap.entrySet()) {
|
||||
String indexName = entry.getKey();
|
||||
List<String> columnList = entry.getValue();
|
||||
String indexColumns = String.join(", ", columnList);
|
||||
String createIndexDDL = String.format("CREATE INDEX %s ON %s (%s);", indexName, tableName,
|
||||
indexColumns);
|
||||
System.out.println(createIndexDDL);
|
||||
createTableDDL.append(createIndexDDL);
|
||||
}
|
||||
return createTableDDL.toString();
|
||||
|
@ -5,6 +5,7 @@ import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import ai.chat2db.plugin.mysql.builder.MysqlSqlBuilder;
|
||||
import ai.chat2db.plugin.mysql.type.MysqlCharsetEnum;
|
||||
@ -17,9 +18,21 @@ import ai.chat2db.spi.jdbc.DefaultMetaService;
|
||||
import ai.chat2db.spi.model.*;
|
||||
import ai.chat2db.spi.sql.SQLExecutor;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import static ai.chat2db.spi.util.SortUtils.sortDatabase;
|
||||
|
||||
public class MysqlMetaData extends DefaultMetaService implements MetaData {
|
||||
|
||||
private List<String> systemDatabases = Arrays.asList("information_schema", "performance_schema", "mysql", "sys");
|
||||
@Override
|
||||
public List<Database> databases(Connection connection) {
|
||||
List<Database> databases = SQLExecutor.getInstance().databases(connection);
|
||||
return sortDatabase(databases,systemDatabases,connection);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String tableDDL(Connection connection, @NotEmpty String databaseName, String schemaName,
|
||||
@NotEmpty String tableName) {
|
||||
|
@ -104,4 +104,22 @@ public class MysqlSqlBuilder implements SqlBuilder {
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public String pageLimit(String sql, int offset, int pageNo, int pageSize) {
|
||||
StringBuilder sqlBuilder = new StringBuilder(sql.length() + 14);
|
||||
sqlBuilder.append(sql);
|
||||
if (offset == 0) {
|
||||
sqlBuilder.append("\n LIMIT ");
|
||||
sqlBuilder.append(pageSize);
|
||||
} else {
|
||||
sqlBuilder.append("\n LIMIT ");
|
||||
sqlBuilder.append(offset);
|
||||
sqlBuilder.append(",");
|
||||
sqlBuilder.append(pageSize);
|
||||
}
|
||||
return sqlBuilder.toString();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
@ -14,6 +14,7 @@ import ai.chat2db.spi.SqlBuilder;
|
||||
import ai.chat2db.spi.jdbc.DefaultMetaService;
|
||||
import ai.chat2db.spi.model.*;
|
||||
import ai.chat2db.spi.sql.SQLExecutor;
|
||||
import ai.chat2db.spi.util.SortUtils;
|
||||
import com.google.common.collect.Lists;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@ -22,6 +23,15 @@ public class OracleMetaData extends DefaultMetaService implements MetaData {
|
||||
|
||||
private static final String TABLE_DDL_SQL = "select dbms_metadata.get_ddl('TABLE','%s','%s') as sql from dual";
|
||||
|
||||
private List<String> systemSchemas = Arrays.asList("ANONYMOUS","APEX_030200","APEX_PUBLIC_USER","APPQOSSYS","BI","CTXSYS","DBSNMP","DIP","EXFSYS","FLOWS_FILES","HR","IX","MDDATA","MDSYS","MGMT_VIEW","OE","OLAPSYS","ORACLE_OCM","ORDDATA","ORDPLUGINS","ORDSYS","OUTLN","OWBSYS","OWBSYS_AUDIT","PM","SCOTT","SH","SI_INFORMTN_SCHEMA","SPATIAL_CSW_ADMIN_USR","SPATIAL_WFS_ADMIN_USR","SYS","SYSMAN","SYSTEM","WMSYS","XDB","XS$NULL");
|
||||
|
||||
|
||||
@Override
|
||||
public List<Schema> schemas(Connection connection, String databaseName) {
|
||||
List<Schema> schemas = SQLExecutor.getInstance().schemas(connection, databaseName, null);
|
||||
return SortUtils.sortSchema(schemas, systemSchemas);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String tableDDL(Connection connection, String databaseName, String schemaName, String tableName) {
|
||||
String sql = String.format(TABLE_DDL_SQL, tableName, schemaName);
|
||||
|
@ -6,6 +6,7 @@ import ai.chat2db.spi.SqlBuilder;
|
||||
import ai.chat2db.spi.model.Table;
|
||||
import ai.chat2db.spi.model.TableColumn;
|
||||
import ai.chat2db.spi.model.TableIndex;
|
||||
import ai.chat2db.spi.sql.Chat2DBContext;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
public class OracleSqlBuilder implements SqlBuilder {
|
||||
@ -99,4 +100,31 @@ public class OracleSqlBuilder implements SqlBuilder {
|
||||
|
||||
return script.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String pageLimit(String sql, int offset, int pageNo, int pageSize) {
|
||||
int startRow = offset;
|
||||
int endRow = offset + pageSize;
|
||||
StringBuilder sqlBuilder = new StringBuilder(sql.length() + 120);
|
||||
if (startRow > 0) {
|
||||
sqlBuilder.append("SELECT * FROM ( ");
|
||||
}
|
||||
if (endRow > 0) {
|
||||
sqlBuilder.append(" SELECT TMP_PAGE.*, ROWNUM CAHT2DB_AUTO_ROW_ID FROM ( ");
|
||||
}
|
||||
sqlBuilder.append("\n");
|
||||
sqlBuilder.append(sql);
|
||||
sqlBuilder.append("\n");
|
||||
if (endRow > 0) {
|
||||
sqlBuilder.append(" ) TMP_PAGE WHERE ROWNUM <= ");
|
||||
sqlBuilder.append(endRow);
|
||||
}
|
||||
if (startRow > 0) {
|
||||
sqlBuilder.append(" ) WHERE CAHT2DB_AUTO_ROW_ID > ");
|
||||
sqlBuilder.append(startRow);
|
||||
}
|
||||
return sqlBuilder.toString();
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -17,22 +17,23 @@ import ai.chat2db.spi.SqlBuilder;
|
||||
import ai.chat2db.spi.jdbc.DefaultMetaService;
|
||||
import ai.chat2db.spi.model.*;
|
||||
import ai.chat2db.spi.sql.SQLExecutor;
|
||||
import com.alibaba.druid.sql.visitor.functions.If;
|
||||
import com.alibaba.fastjson2.JSON;
|
||||
import ai.chat2db.spi.util.SortUtils;
|
||||
import com.google.common.collect.Lists;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import static ai.chat2db.plugin.postgresql.consts.SQLConst.FUNCTION_SQL;
|
||||
import static ai.chat2db.spi.util.SortUtils.sortDatabase;
|
||||
|
||||
public class PostgreSQLMetaData extends DefaultMetaService implements MetaData {
|
||||
|
||||
private static final String SELECT_KEY_INDEX = "SELECT ccu.table_schema AS Foreign_schema_name, ccu.table_name AS Foreign_table_name, ccu.column_name AS Foreign_column_name, constraint_type AS Constraint_type, tc.CONSTRAINT_NAME AS Key_name, tc.TABLE_NAME, kcu.Column_name, tc.is_deferrable, tc.initially_deferred FROM information_schema.table_constraints AS tc JOIN information_schema.key_column_usage AS kcu ON tc.CONSTRAINT_NAME = kcu.CONSTRAINT_NAME JOIN information_schema.constraint_column_usage AS ccu ON ccu.constraint_name = tc.constraint_name WHERE tc.TABLE_SCHEMA = '%s' AND tc.TABLE_NAME = '%s';";
|
||||
|
||||
|
||||
private List<String> systemDatabases = Arrays.asList("postgres");
|
||||
@Override
|
||||
public List<Database> databases(Connection connection) {
|
||||
return SQLExecutor.getInstance().executeSql(connection, "SELECT datname FROM pg_database;", resultSet -> {
|
||||
List<Database> list = SQLExecutor.getInstance().executeSql(connection, "SELECT datname FROM pg_database;", resultSet -> {
|
||||
List<Database> databases = new ArrayList<>();
|
||||
try {
|
||||
while (resultSet.next()) {
|
||||
@ -49,8 +50,30 @@ public class PostgreSQLMetaData extends DefaultMetaService implements MetaData {
|
||||
}
|
||||
return databases;
|
||||
});
|
||||
|
||||
return sortDatabase(list, systemDatabases,connection);
|
||||
}
|
||||
|
||||
private List<String> systemSchemas = Arrays.asList("pg_toast","pg_temp_1","pg_toast_temp_1","pg_catalog","information_schema");
|
||||
|
||||
@Override
|
||||
public List<Schema> schemas(Connection connection, String databaseName) {
|
||||
List<Schema> schemas = SQLExecutor.getInstance().execute(connection,
|
||||
"SELECT catalog_name, schema_name FROM information_schema.schemata;", resultSet -> {
|
||||
List<Schema> databases = new ArrayList<>();
|
||||
while (resultSet.next()) {
|
||||
Schema schema = new Schema();
|
||||
String name = resultSet.getString("schema_name");
|
||||
String catalogName = resultSet.getString("catalog_name");
|
||||
schema.setName(name);
|
||||
schema.setDatabaseName(catalogName);
|
||||
databases.add(schema);
|
||||
}
|
||||
return databases;
|
||||
});
|
||||
return SortUtils.sortSchema(schemas, systemSchemas);
|
||||
}
|
||||
|
||||
|
||||
private static final String SELECT_TABLE_INDEX = "SELECT tmp.INDISPRIMARY AS Index_primary, tmp.TABLE_SCHEM, tmp.TABLE_NAME, tmp.NON_UNIQUE, tmp.INDEX_QUALIFIER, tmp.INDEX_NAME AS Key_name, tmp.indisclustered, tmp.ORDINAL_POSITION AS Seq_in_index, TRIM ( BOTH '\"' FROM pg_get_indexdef ( tmp.CI_OID, tmp.ORDINAL_POSITION, FALSE ) ) AS Column_name,CASE tmp.AM_NAME WHEN 'btree' THEN CASE tmp.I_INDOPTION [ tmp.ORDINAL_POSITION - 1 ] & 1 :: SMALLINT WHEN 1 THEN 'D' ELSE'A' END ELSE NULL END AS Collation, tmp.CARDINALITY, tmp.PAGES, tmp.FILTER_CONDITION , tmp.AM_NAME AS Index_method, tmp.DESCRIPTION AS Index_comment FROM ( SELECT n.nspname AS TABLE_SCHEM, ct.relname AS TABLE_NAME, NOT i.indisunique AS NON_UNIQUE, NULL AS INDEX_QUALIFIER, ci.relname AS INDEX_NAME,i.INDISPRIMARY , i.indisclustered , ( information_schema._pg_expandarray ( i.indkey ) ).n AS ORDINAL_POSITION, ci.reltuples AS CARDINALITY, ci.relpages AS PAGES, pg_get_expr ( i.indpred, i.indrelid ) AS FILTER_CONDITION, ci.OID AS CI_OID, i.indoption AS I_INDOPTION, am.amname AS AM_NAME , d.description FROM pg_class ct JOIN pg_namespace n ON ( ct.relnamespace = n.OID ) JOIN pg_index i ON ( ct.OID = i.indrelid ) JOIN pg_class ci ON ( ci.OID = i.indexrelid ) JOIN pg_am am ON ( ci.relam = am.OID ) left outer join pg_description d on i.indexrelid = d.objoid WHERE n.nspname = '%s' AND ct.relname = '%s' ) AS tmp ;";
|
||||
private static String ROUTINES_SQL
|
||||
= " SELECT p.proname, p.prokind, pg_catalog.pg_get_functiondef(p.oid) as \"code\" FROM pg_catalog.pg_proc p "
|
||||
@ -99,22 +122,6 @@ public class PostgreSQLMetaData extends DefaultMetaService implements MetaData {
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Schema> schemas(Connection connection, String databaseName) {
|
||||
return SQLExecutor.getInstance().execute(connection,
|
||||
"SELECT catalog_name, schema_name FROM information_schema.schemata;", resultSet -> {
|
||||
List<Schema> databases = new ArrayList<>();
|
||||
while (resultSet.next()) {
|
||||
Schema schema = new Schema();
|
||||
String name = resultSet.getString("schema_name");
|
||||
String catalogName = resultSet.getString("catalog_name");
|
||||
schema.setName(name);
|
||||
schema.setDatabaseName(catalogName);
|
||||
databases.add(schema);
|
||||
}
|
||||
return databases;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Function function(Connection connection, @NotEmpty String databaseName, String schemaName,
|
||||
|
@ -156,5 +156,20 @@ public class PostgreSQLSqlBuilder implements SqlBuilder {
|
||||
return script.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String pageLimit(String sql, int offset, int pageNo, int pageSize) {
|
||||
StringBuilder sqlStr = new StringBuilder(sql.length() + 17);
|
||||
sqlStr.append(sql);
|
||||
if (offset == 0) {
|
||||
sqlStr.append(" LIMIT ");
|
||||
sqlStr.append(pageSize);
|
||||
} else {
|
||||
sqlStr.append(" LIMIT ");
|
||||
sqlStr.append(pageSize);
|
||||
sqlStr.append(" OFFSET ");
|
||||
sqlStr.append(offset);
|
||||
}
|
||||
return sqlStr.toString();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -75,5 +75,8 @@ public class SqliteBuilder implements SqlBuilder {
|
||||
return script.toString();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String pageLimit(String sql, int offset, int pageNo, int pageSize) {
|
||||
return "select * from(" + sql + ") t LIMIT " + pageNo + " OFFSET " + offset + "";
|
||||
}
|
||||
}
|
||||
|
@ -14,10 +14,33 @@ import ai.chat2db.spi.SqlBuilder;
|
||||
import ai.chat2db.spi.jdbc.DefaultMetaService;
|
||||
import ai.chat2db.spi.model.*;
|
||||
import ai.chat2db.spi.sql.SQLExecutor;
|
||||
import ai.chat2db.spi.util.SortUtils;
|
||||
import jakarta.validation.constraints.NotEmpty;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import static ai.chat2db.spi.util.SortUtils.sortDatabase;
|
||||
|
||||
public class SqlServerMetaData extends DefaultMetaService implements MetaData {
|
||||
|
||||
|
||||
|
||||
private List<String> systemDatabases = Arrays.asList("master", "model", "msdb", "tempdb");
|
||||
@Override
|
||||
public List<Database> databases(Connection connection) {
|
||||
List<Database> databases = SQLExecutor.getInstance().databases(connection);
|
||||
return sortDatabase(databases,systemDatabases,connection);
|
||||
}
|
||||
|
||||
private List<String> systemSchemas = Arrays.asList("guest", "INFORMATION_SCHEMA", "sys", "db_owner",
|
||||
"db_accessadmin", "db_securityadmin", "db_ddladmin", "db_backupoperator", "db_datareader", "db_datawriter",
|
||||
"db_denydatareader", "db_denydatawriter");
|
||||
|
||||
@Override
|
||||
public List<Schema> schemas(Connection connection, String databaseName) {
|
||||
List<Schema> schemas = SQLExecutor.getInstance().schemas(connection, databaseName, null);
|
||||
return SortUtils.sortSchema(schemas, systemSchemas);
|
||||
}
|
||||
|
||||
private String functionSQL
|
||||
= "CREATE FUNCTION tableSchema.ufn_GetCreateTableScript( @schema_name NVARCHAR(128), @table_name NVARCHAR"
|
||||
+ "(128)) RETURNS NVARCHAR(MAX) AS BEGIN DECLARE @CreateTableScript NVARCHAR(MAX); DECLARE @IndexScripts "
|
||||
@ -49,7 +72,6 @@ public class SqlServerMetaData extends DefaultMetaService implements MetaData {
|
||||
@Override
|
||||
public String tableDDL(Connection connection, String databaseName, String schemaName, String tableName) {
|
||||
try {
|
||||
System.out.println(functionSQL);
|
||||
SQLExecutor.getInstance().executeSql(connection, functionSQL.replace("tableSchema", schemaName),
|
||||
resultSet -> null);
|
||||
} catch (Exception e) {
|
||||
|
@ -6,6 +6,7 @@ import ai.chat2db.spi.SqlBuilder;
|
||||
import ai.chat2db.spi.model.Table;
|
||||
import ai.chat2db.spi.model.TableColumn;
|
||||
import ai.chat2db.spi.model.TableIndex;
|
||||
import ai.chat2db.spi.sql.Chat2DBContext;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
public class SqlServerSqlBuilder implements SqlBuilder {
|
||||
@ -110,8 +111,8 @@ public class SqlServerSqlBuilder implements SqlBuilder {
|
||||
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());
|
||||
}
|
||||
@ -121,4 +122,24 @@ public class SqlServerSqlBuilder implements SqlBuilder {
|
||||
private String buildRenameTable(Table oldTable, Table newTable) {
|
||||
return String.format(RENAME_TABLE_SCRIPT, oldTable.getName(), newTable.getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String pageLimit(String sql, int offset, int pageNo, int pageSize) {
|
||||
String version = Chat2DBContext.getDbVersion();
|
||||
if (StringUtils.isNotBlank(version)) {
|
||||
String[] versions = version.split("\\.");
|
||||
if (versions.length > 0 && Integer.parseInt(versions[0]) >= 11) {
|
||||
StringBuilder sqlBuilder = new StringBuilder(sql.length() + 14);
|
||||
sqlBuilder.append(sql);
|
||||
sqlBuilder.append("\n OFFSET ");
|
||||
sqlBuilder.append(offset);
|
||||
sqlBuilder.append(" ROWS ");
|
||||
sqlBuilder.append(" FETCH NEXT ");
|
||||
sqlBuilder.append(pageSize);
|
||||
sqlBuilder.append(" ROWS ONLY");
|
||||
return sqlBuilder.toString();
|
||||
}
|
||||
}
|
||||
return "";
|
||||
}
|
||||
}
|
||||
|
@ -51,33 +51,7 @@ public class DatabaseServiceImpl implements DatabaseService {
|
||||
}
|
||||
|
||||
private List<Database> getDatabases(String dbType, Connection connection) {
|
||||
MetaData metaData = Chat2DBContext.getMetaData(dbType);
|
||||
List<Database> databases = metaData.databases(connection);
|
||||
sortDatabases(databases,connection);
|
||||
return databases;
|
||||
}
|
||||
|
||||
private void sortDatabases(List<Database> databases,Connection connection) {
|
||||
if (CollectionUtils.isEmpty(databases)) {
|
||||
return;
|
||||
}
|
||||
String ulr = null;
|
||||
try {
|
||||
ulr = connection.getMetaData().getURL();
|
||||
} catch (SQLException e) {
|
||||
log.error("get url error", e);
|
||||
}
|
||||
// If the database name contains the name of the current database, the current database is placed in the first place
|
||||
int num = -1;
|
||||
for (int i = 0; i < databases.size(); i++) {
|
||||
if (StringUtils.isNotBlank(ulr) && StringUtils.isNotBlank(databases.get(i).getName())&& ulr.contains(databases.get(i).getName())) {
|
||||
num = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (num != -1 && num != 0) {
|
||||
Collections.swap(databases, num, 0);
|
||||
}
|
||||
return Chat2DBContext.getMetaData(dbType).databases(connection);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -146,14 +146,24 @@ public class DlTemplateServiceImpl implements DlTemplateService {
|
||||
} catch (ParserException e) {
|
||||
log.warn("解析sql失败:{}", originalSql, e);
|
||||
}
|
||||
ExecuteResult executeResult = null;
|
||||
if (SqlTypeEnum.SELECT.getCode().equals(sqlType) && !SqlUtils.hasPageLimit(originalSql,dbType)) {
|
||||
String pageLimit = Chat2DBContext.getSqlBuilder().pageLimit(originalSql, offset, pageNo, pageSize);
|
||||
if(StringUtils.isNotBlank(pageLimit)) {
|
||||
executeResult = execute(pageLimit, 0, count);
|
||||
}
|
||||
}
|
||||
if (executeResult == null || !executeResult.getSuccess()) {
|
||||
executeResult = execute(originalSql, offset, count);
|
||||
}
|
||||
|
||||
|
||||
ExecuteResult executeResult = execute(originalSql, offset, count);
|
||||
executeResult.setSqlType(sqlType);
|
||||
executeResult.setOriginalSql(originalSql);
|
||||
try {
|
||||
SqlUtils.buildCanEditResult(originalSql, dbType, executeResult);
|
||||
} catch (Exception e) {
|
||||
|
||||
log.warn("buildCanEditResult error", e);
|
||||
}
|
||||
if (SqlTypeEnum.SELECT.getCode().equals(sqlType)) {
|
||||
executeResult.setPageNo(pageNo);
|
||||
|
@ -1,7 +1,10 @@
|
||||
package ai.chat2db.server.domain.repository.mapper;
|
||||
|
||||
import ai.chat2db.server.domain.repository.entity.TableCacheDO;
|
||||
import ai.chat2db.server.domain.repository.entity.TeamUserDO;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import org.apache.ibatis.annotations.Param;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -16,4 +19,6 @@ import java.util.List;
|
||||
public interface TableCacheMapper extends BaseMapper<TableCacheDO> {
|
||||
|
||||
void batchInsert(List<TableCacheDO> list);
|
||||
|
||||
IPage<TableCacheDO> pageQuery(IPage<TableCacheDO> page, @Param("dataSourceId") Long dataSourceId, @Param("databaseName") String databaseName, @Param("schemaName") String schemaName, @Param("searchKey") String searchKey);
|
||||
}
|
||||
|
@ -10,4 +10,23 @@
|
||||
(#{item.dataSourceId},#{item.databaseName},#{item.schemaName},#{item.tableName},#{item.key},#{item.version},#{item.columns},#{item.extendInfo})
|
||||
</foreach>
|
||||
</insert>
|
||||
|
||||
<select id="pageQuery" resultType="ai.chat2db.server.domain.repository.entity.TableCacheDO">
|
||||
select *
|
||||
from TABLE_CACHE tc
|
||||
<where>
|
||||
<if test="dataSourceId != null ">
|
||||
and tc.data_source_id = #{dataSourceId}
|
||||
</if>
|
||||
<if test="databaseName != null and databaseName != '' ">
|
||||
and tc.database_name = #{databaseName}
|
||||
</if>
|
||||
<if test="schemaName != null and schemaName != '' ">
|
||||
and tc.schema_name = #{schemaName}
|
||||
</if>
|
||||
<if test="searchKey != null and searchKey != '' ">
|
||||
and LOWER(tc.table_name) like LOWER(concat('%',#{searchKey},'%'))
|
||||
</if>
|
||||
</where>
|
||||
</select>
|
||||
</mapper>
|
||||
|
@ -35,6 +35,17 @@
|
||||
<version>2.0.4</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>mysql</groupId>-->
|
||||
<!-- <artifactId>mysql-connector-java</artifactId>-->
|
||||
<!-- <version>8.0.30</version>-->
|
||||
<!-- </dependency>-->
|
||||
<!-- <dependency>-->
|
||||
<!-- <groupId>com.github.jsqlparser</groupId>-->
|
||||
<!-- <artifactId>jsqlparser</artifactId>-->
|
||||
<!-- <version>4.6</version>-->
|
||||
<!-- <scope>test</scope>-->
|
||||
<!-- </dependency>-->
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
|
@ -1,21 +1,42 @@
|
||||
package ai.chat2db.server.web.api.controller.system;
|
||||
|
||||
import ai.chat2db.server.tools.common.util.ConfigUtils;
|
||||
import ai.chat2db.server.web.api.controller.system.util.SystemUtils;
|
||||
import ai.chat2db.server.web.api.controller.system.vo.AppVersionVO;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.scheduling.annotation.Scheduled;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Slf4j
|
||||
@Component
|
||||
public class AutomaticUpgrade {
|
||||
|
||||
@Scheduled(fixedRate = 3600000) // 每小时运行一次
|
||||
public void checkVersionUpdates() {
|
||||
AppVersionVO appVersion = SystemUtils.getLatestVersion(ConfigUtils.getLocalVersion(), "auto", "");
|
||||
if (appVersion != null) {
|
||||
SystemUtils.upgrade(appVersion);
|
||||
}
|
||||
}
|
||||
}
|
||||
////package ai.chat2db.server.web.api.controller.system;
|
||||
////
|
||||
////import ai.chat2db.server.tools.common.util.ConfigUtils;
|
||||
////import ai.chat2db.server.web.api.controller.system.util.SystemUtils;
|
||||
////import ai.chat2db.server.web.api.controller.system.vo.AppVersionVO;
|
||||
////import lombok.extern.slf4j.Slf4j;
|
||||
////import org.springframework.scheduling.annotation.Scheduled;
|
||||
////import org.springframework.stereotype.Component;
|
||||
////
|
||||
////@Slf4j
|
||||
////@Component
|
||||
////public class AutomaticUpgrade {
|
||||
////
|
||||
//// @Scheduled(fixedRate = 3600000) // 每小时运行一次
|
||||
//// public void checkVersionUpdates() {
|
||||
//// AppVersionVO appVersion = SystemUtils.getLatestVersion(ConfigUtils.getLocalVersion(), "auto", "");
|
||||
//// if (appVersion != null) {
|
||||
//// SystemUtils.upgrade(appVersion);
|
||||
//// }
|
||||
//// }
|
||||
////}
|
||||
//
|
||||
//const handleInsertText = (text, databaseCode: DatabaseTypeCode = DatabaseTypeCode.MYSQL) => {
|
||||
// if (
|
||||
// [DatabaseTypeCode.POSTGRESQL, DatabaseTypeCode.ORACLE, DatabaseTypeCode.DB2, DatabaseTypeCode.SQLITE].includes(
|
||||
// databaseCode,
|
||||
// )
|
||||
// ) {
|
||||
// return `\"${text}\"`;
|
||||
// } else if ([DatabaseTypeCode.SQLSERVER].includes(databaseCode)) {
|
||||
// return `[${text}]`;
|
||||
// } else if ([DatabaseTypeCode.MYSQL].includes(databaseCode)) {
|
||||
// return `\`${text}\``;
|
||||
// } else {
|
||||
// return `${text}`;
|
||||
// }
|
||||
// };
|
||||
//
|
||||
//"" oracele sqlite postgrsql h2 dm
|
||||
// ` MYSQL clickhouse MariaDB
|
||||
// [ sqlserver
|
||||
//
|
||||
|
@ -206,5 +206,4 @@ public interface MetaData {
|
||||
*/
|
||||
String getMetaDataName(String ...names);
|
||||
|
||||
|
||||
}
|
@ -21,4 +21,16 @@ public interface SqlBuilder {
|
||||
* @return
|
||||
*/
|
||||
String buildModifyTaleSql(Table oldTable, Table newTable);
|
||||
|
||||
|
||||
/**
|
||||
* Generate page limit sql
|
||||
*
|
||||
* @param sql
|
||||
* @param offset
|
||||
* @param pageNo
|
||||
* @param pageSize
|
||||
* @return
|
||||
*/
|
||||
String pageLimit(String sql, int offset, int pageNo, int pageSize);
|
||||
}
|
||||
|
@ -14,4 +14,9 @@ public class DefaultSqlBuilder implements SqlBuilder {
|
||||
public String buildModifyTaleSql(Table oldTable, Table newTable) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String pageLimit(String sql, int offset, int pageNo, int pageSize) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
@ -91,6 +91,26 @@ public class Chat2DBContext {
|
||||
return connection;
|
||||
}
|
||||
|
||||
public static String getDbVersion() {
|
||||
ConnectInfo connectInfo = getConnectInfo();
|
||||
String dbVersion = connectInfo.getDbVersion();
|
||||
if (dbVersion == null) {
|
||||
synchronized (connectInfo) {
|
||||
if (connectInfo.getDbVersion() != null) {
|
||||
return connectInfo.getDbVersion();
|
||||
} else {
|
||||
dbVersion = SQLExecutor.getInstance().getDbVersion(getConnection());
|
||||
connectInfo.setDbVersion(dbVersion);
|
||||
return connectInfo.getDbVersion();
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return dbVersion;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 设置context
|
||||
*
|
||||
|
@ -129,12 +129,23 @@ public class ConnectInfo {
|
||||
|
||||
public Connection connection;
|
||||
|
||||
|
||||
/**
|
||||
* Database version used for different database
|
||||
*/
|
||||
private String dbVersion;
|
||||
|
||||
|
||||
private DriverConfig driverConfig;
|
||||
|
||||
|
||||
public String getDbVersion() {
|
||||
return dbVersion;
|
||||
}
|
||||
|
||||
public void setDbVersion(String dbVersion) {
|
||||
this.dbVersion = dbVersion;
|
||||
}
|
||||
|
||||
public DriverConfig getDriverConfig() {
|
||||
return driverConfig;
|
||||
}
|
||||
|
@ -17,6 +17,7 @@ import ai.chat2db.spi.util.ResultSetUtils;
|
||||
import cn.hutool.core.date.TimeInterval;
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.jdbc.support.JdbcUtils;
|
||||
import org.springframework.util.Assert;
|
||||
@ -185,6 +186,11 @@ public class SQLExecutor {
|
||||
ExecuteResult executeResult = ExecuteResult.builder().sql(sql).success(Boolean.TRUE).build();
|
||||
try (Statement stmt = connection.createStatement()) {
|
||||
stmt.setFetchSize(EasyToolsConstant.MAX_PAGE_SIZE);
|
||||
stmt.setQueryTimeout(30);
|
||||
if (offset != null && count != null) {
|
||||
stmt.setMaxRows(offset + count);
|
||||
}
|
||||
|
||||
TimeInterval timeInterval = new TimeInterval();
|
||||
boolean query = stmt.execute(sql);
|
||||
executeResult.setDescription(I18nUtils.getMessage("sqlResult.success"));
|
||||
@ -200,11 +206,19 @@ public class SQLExecutor {
|
||||
// 获取header信息
|
||||
List<Header> headerList = Lists.newArrayListWithExpectedSize(col);
|
||||
executeResult.setHeaderList(headerList);
|
||||
int chat2dbAutoRowIdIndex = -1;// chat2db自动生成的行分页ID
|
||||
|
||||
for (int i = 1; i <= col; i++) {
|
||||
String name = ResultSetUtils.getColumnName(resultSetMetaData, i);
|
||||
if ("CAHT2DB_AUTO_ROW_ID".equals(name)) {
|
||||
chat2dbAutoRowIdIndex = i;
|
||||
continue;
|
||||
}
|
||||
String dataType = ai.chat2db.spi.util.JdbcUtils.resolveDataType(
|
||||
resultSetMetaData.getColumnTypeName(i), resultSetMetaData.getColumnType(i)).getCode();
|
||||
headerList.add(Header.builder()
|
||||
.dataType(ai.chat2db.spi.util.JdbcUtils.resolveDataType(
|
||||
resultSetMetaData.getColumnTypeName(i), resultSetMetaData.getColumnType(i)).getCode())
|
||||
.name(ResultSetUtils.getColumnName(resultSetMetaData, i))
|
||||
.dataType(dataType)
|
||||
.name(name)
|
||||
.build());
|
||||
}
|
||||
|
||||
@ -224,6 +238,9 @@ public class SQLExecutor {
|
||||
List<String> row = Lists.newArrayListWithExpectedSize(col);
|
||||
dataList.add(row);
|
||||
for (int i = 1; i <= col; i++) {
|
||||
if (chat2dbAutoRowIdIndex == i) {
|
||||
continue;
|
||||
}
|
||||
row.add(ai.chat2db.spi.util.JdbcUtils.getResultSetValue(rs, i, limitRowSize));
|
||||
}
|
||||
if (count != null && count > 0 && rowCount++ >= count) {
|
||||
@ -263,7 +280,11 @@ public class SQLExecutor {
|
||||
*/
|
||||
public List<Database> databases(Connection connection) {
|
||||
try (ResultSet resultSet = connection.getMetaData().getCatalogs();) {
|
||||
return ResultSetUtils.toObjectList(resultSet, Database.class);
|
||||
List<Database> databases = ResultSetUtils.toObjectList(resultSet, Database.class);
|
||||
if (CollectionUtils.isEmpty(databases)) {
|
||||
return databases;
|
||||
}
|
||||
return databases.stream().filter(database -> database.getName() != null).collect(Collectors.toList());
|
||||
} catch (SQLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
@ -428,4 +449,15 @@ public class SQLExecutor {
|
||||
}
|
||||
}
|
||||
|
||||
public String getDbVersion(Connection connection) {
|
||||
try {
|
||||
String dbVersion = connection.getMetaData().getDatabaseProductVersion();
|
||||
return dbVersion;
|
||||
} catch (Exception e) {
|
||||
log.error("get db version error", e);
|
||||
//throw new RuntimeException(e);
|
||||
}
|
||||
return "";
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -42,7 +42,6 @@ public class JdbcJarUtils {
|
||||
String outputPath = PATH + url.substring(url.lastIndexOf("/") + 1);
|
||||
File file = new File(outputPath);
|
||||
if (file.exists()) {
|
||||
System.out.println("File already exists: " + outputPath);
|
||||
continue;
|
||||
}
|
||||
asyncDownload(url);
|
||||
@ -77,7 +76,6 @@ public class JdbcJarUtils {
|
||||
}
|
||||
fos.flush();
|
||||
}
|
||||
System.out.println("File downloaded: " + outputPath);
|
||||
}
|
||||
});
|
||||
}
|
||||
@ -105,7 +103,6 @@ public class JdbcJarUtils {
|
||||
}
|
||||
fos.flush();
|
||||
}
|
||||
System.out.println("File downloaded: " + outputPath);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -0,0 +1,77 @@
|
||||
package ai.chat2db.spi.util;
|
||||
|
||||
import ai.chat2db.spi.model.Database;
|
||||
import ai.chat2db.spi.model.Schema;
|
||||
import org.apache.commons.collections4.CollectionUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.sql.Connection;
|
||||
import java.sql.SQLException;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class SortUtils {
|
||||
|
||||
public static List<Database> sortDatabase(List<Database> databases, List<String> list, Connection connection) {
|
||||
if (CollectionUtils.isEmpty(databases)) {
|
||||
return databases;
|
||||
}
|
||||
List<Database> systemDatabases = databases.stream()
|
||||
.filter(database -> list.contains(database.getName())).collect(Collectors.toList());
|
||||
List<Database> userDatabases = databases.stream()
|
||||
.filter(database -> !list.contains(database.getName())).collect(Collectors.toList());
|
||||
|
||||
if (CollectionUtils.isEmpty(userDatabases)) {
|
||||
return databases;
|
||||
}
|
||||
if (CollectionUtils.isEmpty(systemDatabases)) {
|
||||
return userDatabases;
|
||||
}
|
||||
List<Database> databaseList = Stream.concat(userDatabases.stream(), systemDatabases.stream())
|
||||
.collect(Collectors.toList());
|
||||
// If the database name contains the name of the current database, the current database is placed in the first place
|
||||
|
||||
String ulr;
|
||||
try {
|
||||
ulr = connection.getMetaData().getURL();
|
||||
} catch (SQLException e) {
|
||||
return databaseList;
|
||||
}
|
||||
// If the database name contains the name of the current database, the current database is placed in the first place
|
||||
int no = -1;
|
||||
for (int i = 0; i < databases.size(); i++) {
|
||||
if (StringUtils.isNotBlank(ulr)
|
||||
&& StringUtils.isNotBlank(databases.get(i).getName())
|
||||
&& ulr.contains(databases.get(i).getName())
|
||||
&& !"mysql".equalsIgnoreCase(databases.get(i).getName())) {
|
||||
no = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (no != -1 && no != 0) {
|
||||
Collections.swap(databaseList, no, 0);
|
||||
}
|
||||
return databaseList;
|
||||
}
|
||||
|
||||
public static List<Schema> sortSchema(List<Schema> schemas, List<String> systemSchemas) {
|
||||
if (CollectionUtils.isEmpty(schemas)) {
|
||||
return schemas;
|
||||
}
|
||||
List<Schema> systemSchema = schemas.stream()
|
||||
.filter(schema -> systemSchemas.contains(schema.getName()) || "APEX_".startsWith(schema.getName())).collect(Collectors.toList());
|
||||
List<Schema> userSchema = schemas.stream()
|
||||
.filter(schema -> !systemSchemas.contains(schema.getName()) && !"APEX_".startsWith(schema.getName())).collect(Collectors.toList());
|
||||
|
||||
if (CollectionUtils.isEmpty(userSchema)) {
|
||||
return schemas;
|
||||
}
|
||||
if (CollectionUtils.isEmpty(systemSchema)) {
|
||||
return userSchema;
|
||||
}
|
||||
return Stream.concat(userSchema.stream(), systemSchema.stream())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
@ -12,13 +12,12 @@ import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLTableSource;
|
||||
import com.alibaba.druid.sql.parser.SQLParserUtils;
|
||||
import net.sf.jsqlparser.expression.BinaryExpression;
|
||||
import net.sf.jsqlparser.expression.Function;
|
||||
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 net.sf.jsqlparser.statement.select.*;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@ -49,6 +48,17 @@ public class SqlUtils {
|
||||
executeResult.setCanEdit(false);
|
||||
return;
|
||||
}
|
||||
if (item instanceof SelectExpressionItem) {
|
||||
SelectExpressionItem selectExpressionItem = (SelectExpressionItem) item;
|
||||
// 如果表达式是一个函数
|
||||
if (selectExpressionItem.getExpression() instanceof Function) {
|
||||
Function function = (Function) selectExpressionItem.getExpression();
|
||||
// 检查函数是否为 "COUNT"
|
||||
if ("COUNT".equalsIgnoreCase(function.getName())) {
|
||||
executeResult.setCanEdit(false);
|
||||
return; }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
executeResult.setCanEdit(true);
|
||||
@ -58,6 +68,8 @@ public class SqlUtils {
|
||||
sqlSelectStatement.getSelect().getFirstQueryBlock().getFrom());
|
||||
executeResult.setTableName(getMetaDataTableName(sqlExprTableSource.getCatalog(), sqlExprTableSource.getSchema(), sqlExprTableSource.getTableName()));
|
||||
}
|
||||
}else {
|
||||
executeResult.setCanEdit(false);
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
@ -116,4 +128,29 @@ public class SqlUtils {
|
||||
DataTypeEnum dataTypeEnum = DataTypeEnum.getByCode(dataType);
|
||||
return dataTypeEnum.getSqlValue(value);
|
||||
}
|
||||
|
||||
public static boolean hasPageLimit(String sql, DbType dbType) {
|
||||
try {
|
||||
Statement statement = CCJSqlParserUtil.parse(sql);
|
||||
if (statement instanceof Select) {
|
||||
Select selectStatement = (Select) statement;
|
||||
SelectBody selectBody = selectStatement.getSelectBody();
|
||||
// 检查常见的分页方法
|
||||
if (selectBody instanceof PlainSelect) {
|
||||
PlainSelect plainSelect = (PlainSelect) selectBody;
|
||||
// 检查 LIMIT
|
||||
if (plainSelect.getLimit() != null || plainSelect.getOffset() != null || plainSelect.getTop() != null || plainSelect.getFetch() != null) {
|
||||
return true;
|
||||
}
|
||||
if (DbType.oracle.equals(dbType)) {
|
||||
return sql.contains("ROWNUM") || sql.contains("rownum");
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
return false;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
Reference in New Issue
Block a user