Merge branch 'dev' into fix/645

This commit is contained in:
ji
2023-11-12 22:46:51 +08:00
committed by GitHub
187 changed files with 3929 additions and 1992 deletions

View File

@ -74,5 +74,10 @@
<artifactId>jsqlparser</artifactId>
<version>4.6</version>
</dependency>
<dependency>
<groupId>org.locationtech.jts</groupId>
<artifactId>jts-core</artifactId>
<version>1.19.0</version> <!-- 确保使用最新的版本 -->
</dependency>
</dependencies>
</project>

View File

@ -206,4 +206,12 @@ public interface MetaData {
*/
String getMetaDataName(String ...names);
/**
* Get column builder.
*
* @return
*/
ValueHandler getValueHandler();
}

View File

@ -0,0 +1,17 @@
package ai.chat2db.spi;
import java.sql.ResultSet;
import java.sql.SQLException;
public interface ValueHandler {
/**
* 处理结果集中的列值
* @param rs
* @param index
* @param limitSize
* @return
* @throws SQLException
*/
String getString(ResultSet rs, int index, boolean limitSize)throws SQLException;
}

View File

@ -1,7 +1,7 @@
package ai.chat2db.spi.config;
import lombok.Data;
import org.apache.commons.collections4.CollectionUtils;
import java.util.List;
@ -9,7 +9,6 @@ import java.util.List;
* @author jipengfei
* @version : DBConfig.java
*/
@Data
public class DBConfig {
/**
@ -32,7 +31,6 @@ public class DBConfig {
*/
private List<DriverConfig> driverConfigList;
/**
* 建表语句
*/
@ -42,4 +40,73 @@ public class DBConfig {
* 修改表结构
*/
private String simpleAlterTable;
public String getDbType() {
return dbType;
}
public void setDbType(String dbType) {
this.dbType = dbType;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public DriverConfig getDefaultDriverConfig() {
if (this.defaultDriverConfig != null) {
return this.defaultDriverConfig;
} else {
if (!CollectionUtils.isEmpty(driverConfigList)) {
for (DriverConfig driverConfig : driverConfigList) {
if (driverConfig.isDefaultDriver()) {
return driverConfig;
}
}
return driverConfigList.get(0);
}
}
return null;
}
public void setDefaultDriverConfig(DriverConfig defaultDriverConfig) {
this.defaultDriverConfig = defaultDriverConfig;
}
public List<DriverConfig> getDriverConfigList() {
return driverConfigList;
}
public void setDriverConfigList(List<DriverConfig> driverConfigList) {
this.driverConfigList = driverConfigList;
if (!CollectionUtils.isEmpty(driverConfigList)) {
for (DriverConfig driverConfig : driverConfigList) {
if (driverConfig.isDefaultDriver()) {
this.defaultDriverConfig = driverConfig;
break;
}
}
}
}
public String getSimpleCreateTable() {
return simpleCreateTable;
}
public void setSimpleCreateTable(String simpleCreateTable) {
this.simpleCreateTable = simpleCreateTable;
}
public String getSimpleAlterTable() {
return simpleAlterTable;
}
public void setSimpleAlterTable(String simpleAlterTable) {
this.simpleAlterTable = simpleAlterTable;
}
}

View File

@ -3,6 +3,7 @@ package ai.chat2db.spi.config;
import java.util.List;
import ai.chat2db.spi.model.KeyValue;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
@ -12,6 +13,11 @@ import org.apache.commons.lang3.StringUtils;
*/
@Data
public class DriverConfig {
/**
* url
*/
private String url;
/**
* jdbcDriver
*/
@ -22,17 +28,14 @@ public class DriverConfig {
*/
private String jdbcDriverClass;
///**
// * name
// */
//private String name;
/**
* downloadJdbcDriverUrls
*/
private List<String> downloadJdbcDriverUrls;
/**
* dbType
*/
private String dbType;
/**
@ -40,6 +43,13 @@ public class DriverConfig {
*/
private boolean custom;
/**
* properties
*/
private List<KeyValue> extendInfo;
private boolean defaultDriver;
public boolean notEmpty() {
return StringUtils.isNotBlank(getJdbcDriver()) && StringUtils.isNotBlank(

View File

@ -8,6 +8,7 @@ import java.util.stream.Collectors;
import ai.chat2db.spi.MetaData;
import ai.chat2db.spi.SqlBuilder;
import ai.chat2db.spi.ValueHandler;
import ai.chat2db.spi.model.*;
import ai.chat2db.spi.sql.SQLExecutor;
import org.apache.commons.collections4.CollectionUtils;
@ -25,7 +26,15 @@ public class DefaultMetaService implements MetaData {
@Override
public List<Schema> schemas(Connection connection, String databaseName) {
return SQLExecutor.getInstance().schemas(connection, databaseName, null);
List<Schema> schemas = SQLExecutor.getInstance().schemas(connection, databaseName, null);
if(StringUtils.isNotBlank(databaseName) && CollectionUtils.isNotEmpty(schemas)){
for ( Schema schema : schemas) {
if(StringUtils.isBlank(schema.getDatabaseName())){
schema.setDatabaseName(databaseName);
}
}
}
return schemas;
}
@Override
@ -123,6 +132,8 @@ public class DefaultMetaService implements MetaData {
return Arrays.stream(names).filter(name -> StringUtils.isNotBlank(name)).collect(Collectors.joining("."));
}
@Override
public ValueHandler getValueHandler() {
return new DefaultValueHandler();
}
}

View File

@ -0,0 +1,82 @@
package ai.chat2db.spi.jdbc;
import ai.chat2db.server.tools.common.util.I18nUtils;
import ai.chat2db.spi.ValueHandler;
import cn.hutool.core.io.unit.DataSizeUtil;
import lombok.extern.slf4j.Slf4j;
import java.math.BigDecimal;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.ResultSet;
import java.sql.SQLException;
@Slf4j
public class DefaultValueHandler implements ValueHandler {
private static final long MAX_RESULT_SIZE = 256 * 1024;
@Override
public String getString(ResultSet rs, int index, boolean limitSize) throws SQLException {
Object obj = rs.getObject(index);
if (obj == null) {
return null;
}
try {
if (obj instanceof BigDecimal bigDecimal) {
return bigDecimal.toPlainString();
} else if (obj instanceof Double d) {
return BigDecimal.valueOf(d).toPlainString();
} else if (obj instanceof Float f) {
return BigDecimal.valueOf(f).toPlainString();
} else if (obj instanceof Clob) {
return largeString(rs, index, limitSize);
} else if (obj instanceof byte[]) {
return largeString(rs, index, limitSize);
} else if (obj instanceof Blob blob) {
return largeStringBlob(blob, limitSize);
}
return rs.getString(index);
} catch (Exception e) {
log.warn("解析数失败:{},{}", index, obj, e);
return obj.toString();
}
}
private String largeStringBlob(Blob blob, boolean limitSize) throws SQLException {
if (blob == null) {
return null;
}
int length = Math.toIntExact(blob.length());
if (limitSize && length > MAX_RESULT_SIZE) {
length = Math.toIntExact(MAX_RESULT_SIZE);
}
byte[] data = blob.getBytes(1, length);
String result = new String(data);
if (length > MAX_RESULT_SIZE) {
return "[ " + DataSizeUtil.format(MAX_RESULT_SIZE) + " of " + DataSizeUtil.format(length)
+ " ,"
+ I18nUtils.getMessage("execute.exportCsv") + " ] " + result;
}
return result;
}
private static String largeString(ResultSet rs, int index, boolean limitSize) throws SQLException {
String result = rs.getString(index);
if (result == null) {
return null;
}
if (!limitSize) {
return result;
}
if (result.length() > MAX_RESULT_SIZE) {
return "[ " + DataSizeUtil.format(MAX_RESULT_SIZE) + " of " + DataSizeUtil.format(result.length()) + " ,"
+ I18nUtils.getMessage("execute.exportCsv") + " ] " + result.substring(0,
Math.toIntExact(MAX_RESULT_SIZE));
}
return result;
}
}

View File

@ -23,7 +23,17 @@ public class KeyValue implements Serializable {
/**
* 属性值
*/
private Object value;
private String value;
/**
* 是否必填
*/
private boolean required;
/**
* 选项
*/
private List<String> choices;
public static Map<String, Object> toMap(List<KeyValue> keyValues) {
if (CollectionUtils.isEmpty(keyValues)) {

View File

@ -24,12 +24,12 @@ public class Schema implements Serializable {
/**
* databaseName
*/
@JsonAlias({"TABLE_CATALOG"})
@JsonAlias({"TABLE_CATALOG","table_catalog"})
private String databaseName;
/**
* 数据名字
*/
@JsonAlias({"TABLE_SCHEM"})
@JsonAlias({"TABLE_SCHEM","table_schem"})
private String name;

View File

@ -16,6 +16,7 @@ import java.net.URL;
import java.net.URLClassLoader;
import java.sql.Connection;
import java.sql.Driver;
import java.sql.DriverPropertyInfo;
import java.sql.SQLException;
import java.util.Map;
import java.util.Objects;
@ -40,7 +41,7 @@ public class IDriverManager {
}
public static Connection getConnection(String url, String user, String password, DriverConfig driver)
throws SQLException {
throws SQLException {
Properties info = new Properties();
if (user != null) {
info.put("user", user);
@ -54,8 +55,8 @@ public class IDriverManager {
}
public static Connection getConnection(String url, String user, String password, DriverConfig driver,
Map<String, Object> properties)
throws SQLException {
Map<String, Object> properties)
throws SQLException {
Properties info = new Properties();
if (StringUtils.isNotEmpty(user)) {
info.put("user", user);
@ -88,6 +89,7 @@ public class IDriverManager {
try (Connection connection = driverEntry.getDriver().connect(url, info)) {
if (Objects.isNull(connection)) {
throw new SQLException(String.format("driver.connect return null , No suitable driver found for url %s", url), SQL_STATE_CODE);
}
return connection;
} catch (SQLException sqlException) {
@ -102,8 +104,26 @@ public class IDriverManager {
}
}
public static DriverPropertyInfo[] getProperty(DriverConfig driver)
throws SQLException {
if (driver == null) {
return null;
}
DriverEntry driverEntry = DRIVER_ENTRY_MAP.get(driver.getJdbcDriver());
if (driverEntry == null) {
driverEntry = getJDBCDriver(driver);
}
try {
String url = driver.getUrl() == null ? "" : driver.getUrl();
return driverEntry.getDriver().getPropertyInfo(url, null);
} catch (Exception var7) {
return null;
}
}
private static Connection tryConnectionAgain(DriverEntry driverEntry, String url,
Properties info) throws SQLException {
Properties info) throws SQLException {
if (url.contains("mysql")) {
if (!info.containsKey("useSSL")) {
info.put("useSSL", "false");
@ -114,14 +134,14 @@ public class IDriverManager {
}
private static DriverEntry getJDBCDriver(DriverConfig driver)
throws SQLException {
throws SQLException {
synchronized (driver) {
try {
if (DRIVER_ENTRY_MAP.containsKey(driver.getJdbcDriver())) {
return DRIVER_ENTRY_MAP.get(driver.getJdbcDriver());
}
ClassLoader cl = getClassLoader(driver);
Driver d = (Driver)cl.loadClass(driver.getJdbcDriverClass()).newInstance();
Driver d = (Driver) cl.loadClass(driver.getJdbcDriverClass()).newInstance();
DriverEntry driverEntry = DriverEntry.builder().driverConfig(driver).driver(d).build();
DRIVER_ENTRY_MAP.put(driver.getJdbcDriver(), driverEntry);
return driverEntry;

View File

@ -12,14 +12,16 @@ import java.util.stream.Collectors;
import ai.chat2db.server.tools.base.constant.EasyToolsConstant;
import ai.chat2db.server.tools.common.util.I18nUtils;
import ai.chat2db.spi.ValueHandler;
import ai.chat2db.spi.jdbc.DefaultValueHandler;
import ai.chat2db.spi.model.*;
import ai.chat2db.spi.util.JdbcUtils;
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;
/**
@ -92,12 +94,12 @@ public class SQLExecutor {
}
public void executeSql(Connection connection, String sql, Consumer<List<Header>> headerConsumer,
Consumer<List<String>> rowConsumer) {
executeSql(connection, sql, headerConsumer, rowConsumer, true);
Consumer<List<String>> rowConsumer,ValueHandler valueHandler) {
executeSql(connection, sql, headerConsumer, rowConsumer, true,valueHandler);
}
public void executeSql(Connection connection, String sql, Consumer<List<Header>> headerConsumer,
Consumer<List<String>> rowConsumer, boolean limitSize) {
Consumer<List<String>> rowConsumer, boolean limitSize,ValueHandler valueHandler) {
Assert.notNull(sql, "SQL must not be null");
log.info("execute:{}", sql);
try (Statement stmt = connection.createStatement();) {
@ -115,7 +117,7 @@ public class SQLExecutor {
List<Header> headerList = Lists.newArrayListWithExpectedSize(col);
for (int i = 1; i <= col; i++) {
headerList.add(Header.builder()
.dataType(ai.chat2db.spi.util.JdbcUtils.resolveDataType(
.dataType(JdbcUtils.resolveDataType(
resultSetMetaData.getColumnTypeName(i), resultSetMetaData.getColumnType(i)).getCode())
.name(ResultSetUtils.getColumnName(resultSetMetaData, i))
.build());
@ -125,7 +127,7 @@ public class SQLExecutor {
while (rs.next()) {
List<String> row = Lists.newArrayListWithExpectedSize(col);
for (int i = 1; i <= col; i++) {
row.add(ai.chat2db.spi.util.JdbcUtils.getResultSetValue(rs, i, limitSize));
row.add(valueHandler.getString(rs, i, limitSize));
}
rowConsumer.accept(row);
}
@ -145,8 +147,8 @@ public class SQLExecutor {
* @return
* @throws SQLException
*/
public ExecuteResult execute(final String sql, Connection connection) throws SQLException {
return execute(sql, connection, true, null, null);
public ExecuteResult execute(final String sql, Connection connection,ValueHandler valueHandler) throws SQLException {
return execute(sql, connection, true, null, null,valueHandler);
}
public ExecuteResult executeUpdate(final String sql, Connection connection, int n)
@ -160,7 +162,7 @@ public class SQLExecutor {
if (affectedRows != n) {
executeResult.setSuccess(false);
executeResult.setMessage("Update error " + sql + " update affectedRows = " + affectedRows + ", Each SQL statement should update no more than one record. Please use a unique key for updates.");
connection.rollback();
// connection.rollback();
}
}
return executeResult;
@ -178,11 +180,10 @@ public class SQLExecutor {
* @throws SQLException
*/
public ExecuteResult execute(final String sql, Connection connection, boolean limitRowSize, Integer offset,
Integer count)
Integer count, ValueHandler valueHandler)
throws SQLException {
Assert.notNull(sql, "SQL must not be null");
log.info("execute:{}", sql);
ExecuteResult executeResult = ExecuteResult.builder().sql(sql).success(Boolean.TRUE).build();
try (Statement stmt = connection.createStatement()) {
stmt.setFetchSize(EasyToolsConstant.MAX_PAGE_SIZE);
@ -214,7 +215,7 @@ public class SQLExecutor {
chat2dbAutoRowIdIndex = i;
continue;
}
String dataType = ai.chat2db.spi.util.JdbcUtils.resolveDataType(
String dataType = JdbcUtils.resolveDataType(
resultSetMetaData.getColumnTypeName(i), resultSetMetaData.getColumnType(i)).getCode();
headerList.add(Header.builder()
.dataType(dataType)
@ -241,7 +242,7 @@ public class SQLExecutor {
if (chat2dbAutoRowIdIndex == i) {
continue;
}
row.add(ai.chat2db.spi.util.JdbcUtils.getResultSetValue(rs, i, limitRowSize));
row.add(valueHandler.getString(rs, i, limitRowSize));
}
if (count != null && count > 0 && rowCount++ >= count) {
break;
@ -260,6 +261,7 @@ public class SQLExecutor {
return executeResult;
}
/**
* 执行sql
*
@ -268,8 +270,12 @@ public class SQLExecutor {
* @return
* @throws SQLException
*/
public ExecuteResult execute(Connection connection, String sql,ValueHandler valueHandler) throws SQLException {
return execute(sql, connection, true, null, null,valueHandler);
}
public ExecuteResult execute(Connection connection, String sql) throws SQLException {
return execute(sql, connection, true, null, null);
return execute(sql, connection, true, null, null,new DefaultValueHandler());
}
/**
@ -455,7 +461,6 @@ public class SQLExecutor {
return dbVersion;
} catch (Exception e) {
log.error("get db version error", e);
//throw new RuntimeException(e);
}
return "";
}

View File

@ -0,0 +1,21 @@
package ai.chat2db.spi.util;
import ai.chat2db.spi.config.DBConfig;
import com.fasterxml.jackson.databind.ObjectMapper;
import java.io.IOException;
public class FileUtils {
public static <T> T readJsonValue(Class<?> loaderClass, String path, Class<T> clazz) {
ObjectMapper mapper = new ObjectMapper();
T value = null;
try {
value = mapper.readValue(loaderClass.getResourceAsStream(path), clazz);
// 使用obj中的数据
} catch (IOException e) {
return null;
}
return value;
}
}

View File

@ -1,27 +1,25 @@
package ai.chat2db.spi.util;
import java.math.BigDecimal;
import java.sql.Blob;
import java.sql.Clob;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Map;
import java.sql.*;
import java.text.Collator;
import java.util.*;
import ai.chat2db.spi.model.KeyValue;
import com.alibaba.druid.DbType;
import ai.chat2db.server.tools.common.util.I18nUtils;
import ai.chat2db.spi.config.DriverConfig;
import ai.chat2db.spi.enums.DataTypeEnum;
import ai.chat2db.spi.model.DataSourceConnect;
import ai.chat2db.spi.model.SSHInfo;
import ai.chat2db.spi.sql.IDriverManager;
import ai.chat2db.spi.ssh.SSHManager;
import cn.hutool.core.io.unit.DataSizeUtil;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.jcraft.jsch.Session;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.lang.Nullable;
/**
* jdbc工具类
@ -132,77 +130,6 @@ public class JdbcUtils {
return type;
}
/**
* 获取一个返回值
*
* @param rs
* @param index
* @return
* @throws SQLException
*/
public static String getResultSetValue(ResultSet rs, int index, boolean limitSize) throws SQLException {
Object obj = rs.getObject(index);
if (obj == null) {
return null;
}
try {
if (obj instanceof BigDecimal bigDecimal) {
return bigDecimal.toPlainString();
} else if (obj instanceof Double d) {
return BigDecimal.valueOf(d).toPlainString();
} else if (obj instanceof Float f) {
return BigDecimal.valueOf(f).toPlainString();
} else if (obj instanceof Clob) {
return largeString(rs, index, limitSize);
} else if (obj instanceof byte[]) {
return largeString(rs, index, limitSize);
} else if (obj instanceof Blob blob) {
return largeStringBlob(blob, limitSize);
}
return rs.getString(index);
} catch (Exception e) {
log.warn("解析数失败:{},{}", index, obj, e);
return obj.toString();
}
}
private static String largeStringBlob(Blob blob, boolean limitSize) throws SQLException {
if (blob == null) {
return null;
}
int length = Math.toIntExact(blob.length());
if (limitSize && length > MAX_RESULT_SIZE) {
length = Math.toIntExact(MAX_RESULT_SIZE);
}
byte[] data = blob.getBytes(1, length);
String result = new String(data);
if (length > MAX_RESULT_SIZE) {
return "[ " + DataSizeUtil.format(MAX_RESULT_SIZE) + " of " + DataSizeUtil.format(length)
+ " ,"
+ I18nUtils.getMessage("execute.exportCsv") + " ] " + result;
}
return result;
}
private static String largeString(ResultSet rs, int index, boolean limitSize) throws SQLException {
String result = rs.getString(index);
if (result == null) {
return null;
}
if (!limitSize) {
return result;
}
if (result.length() > MAX_RESULT_SIZE) {
return "[ " + DataSizeUtil.format(MAX_RESULT_SIZE) + " of " + DataSizeUtil.format(result.length()) + " ,"
+ I18nUtils.getMessage("execute.exportCsv") + " ] " + result.substring(0,
Math.toIntExact(MAX_RESULT_SIZE));
}
return result;
}
/**
* 测试数据库连接
*
@ -213,11 +140,11 @@ public class JdbcUtils {
* @return
*/
public static DataSourceConnect testConnect(String url, String host, String port,
String userName, String password, String dbType,
DriverConfig driverConfig, SSHInfo ssh, Map<String, Object> properties) {
String userName, String password, String dbType,
DriverConfig driverConfig, SSHInfo ssh, Map<String, Object> properties) {
DataSourceConnect dataSourceConnect = DataSourceConnect.builder()
.success(Boolean.TRUE)
.build();
.success(Boolean.TRUE)
.build();
Session session = null;
Connection connection = null;
// 加载驱动
@ -230,7 +157,7 @@ public class JdbcUtils {
}
// 创建连接
connection = IDriverManager.getConnection(url, userName, password,
driverConfig, properties);
driverConfig, properties);
} catch (Exception e) {
log.error("connection fail:", e);
dataSourceConnect.setSuccess(Boolean.FALSE);
@ -265,4 +192,109 @@ public class JdbcUtils {
return dataSourceConnect;
}
public static void closeResultSet(@Nullable ResultSet rs) {
if (rs != null) {
try {
rs.close();
} catch (SQLException var2) {
log.trace("Could not close JDBC ResultSet", var2);
} catch (Throwable var3) {
log.trace("Unexpected exception on closing JDBC ResultSet", var3);
}
}
}
public static void setDriverDefaultProperty(DriverConfig driverConfig) {
if(driverConfig == null){
return;
}
List<KeyValue> defaultKeyValues = driverConfig.getExtendInfo();
Map<String, KeyValue> valueMap = Maps.newHashMap();
if (!CollectionUtils.isEmpty(defaultKeyValues)) {
for (KeyValue keyValue : defaultKeyValues) {
if (keyValue == null || StringUtils.isBlank(keyValue.getKey())) {
continue;
}
valueMap.put(keyValue.getKey(), keyValue);
}
}
try {
DriverPropertyInfo[] propertyInfos = IDriverManager.getProperty(driverConfig);
if (propertyInfos == null) {
return;
}
for (int i = 0; i < propertyInfos.length; i++) {
DriverPropertyInfo propertyInfo = propertyInfos[i];
if (propertyInfo == null) {
continue;
}
KeyValue keyValue = valueMap.get(propertyInfo.name);
if (keyValue != null) {
String[] choices = propertyInfo.choices;
if (CollectionUtils.isEmpty(keyValue.getChoices()) && choices != null && choices.length > 0) {
keyValue.setChoices(Lists.newArrayList(choices));
}
} else {
keyValue = new KeyValue();
keyValue.setKey(propertyInfo.name);
keyValue.setValue(propertyInfo.value);
keyValue.setRequired(propertyInfo.required);
String[] choices = propertyInfo.choices;
if (choices != null && choices.length > 0) {
keyValue.setChoices(Lists.newArrayList(choices));
}
valueMap.put(keyValue.getKey(), keyValue);
}
}
if (!valueMap.isEmpty()) {
Comparator comparator = Collator.getInstance(Locale.ENGLISH);
List<KeyValue> result = new ArrayList<>(valueMap.values());
Collections.sort(result, (o1, o2) -> comparator.compare(o1.getKey(), o2.getKey()));
driverConfig.setExtendInfo(result);
}
} catch (SQLException e) {
log.error("get property error:", e);
}
}
public static void removePropertySameAsDefault(DriverConfig driverConfig) {
if(driverConfig == null){
return;
}
List<KeyValue> customValue = driverConfig.getExtendInfo();
if (CollectionUtils.isEmpty(customValue)) {
return ;
}
Map<String, String> map = Maps.newHashMap();
List<KeyValue> result = new ArrayList<>();
try {
DriverPropertyInfo[] propertyInfos = IDriverManager.getProperty(driverConfig);
if (propertyInfos == null) {
return ;
}
for (int i = 0; i < propertyInfos.length; i++) {
DriverPropertyInfo propertyInfo = propertyInfos[i];
if (propertyInfo == null) {
continue;
}
map.put(propertyInfo.name, propertyInfo.value);
}
for (KeyValue keyValue : customValue) {
if (keyValue == null || StringUtils.isBlank(keyValue.getKey())) {
continue;
}
String value = map.get(keyValue.getKey());
if (!StringUtils.equals(value, keyValue.getValue())) {
result.add(keyValue);
}
}
Comparator comparator = Collator.getInstance(Locale.ENGLISH);
Collections.sort(result, (o1, o2) -> comparator.compare(o1.getKey(), o2.getKey()));
driverConfig.setExtendInfo(result);
} catch (SQLException e) {
}
}
}

View File

@ -9,11 +9,11 @@ import java.util.List;
import java.util.Map;
import com.fasterxml.jackson.databind.DeserializationFeature;
import com.fasterxml.jackson.databind.MapperFeature;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.PropertyNamingStrategies;
import com.google.common.collect.Lists;
import static ai.chat2db.spi.util.JdbcUtils.getResultSetValue;
/**
* @author jipengfei
@ -22,28 +22,6 @@ import static ai.chat2db.spi.util.JdbcUtils.getResultSetValue;
public class ResultSetUtils {
public static <T> T toObject(ResultSet rs, Class<T> clazz) {
try {
if (rs == null || clazz == null) {
return null;
}
ResultSetMetaData resultSetMetaData = rs.getMetaData();
int col = resultSetMetaData.getColumnCount();
List<String> headerList = getRsHeader(rs);
Map<String, Object> map = new HashMap<>();
for (int i = 1; i <= col; i++) {
map.put(headerList.get(i), getResultSetValue(rs, i, true));
}
ObjectMapper mapper = new ObjectMapper();
mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
//mapper.configure(DeserializationFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
return mapper.convertValue(map, clazz);
} catch (SQLException e) {
throw new RuntimeException(e);
}
}
private static List<String> getRsHeader(ResultSet rs) {
try {
@ -78,6 +56,7 @@ public class ResultSetUtils {
ObjectMapper mapper = new ObjectMapper();
mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE);
mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
mapper.configure(MapperFeature.ACCEPT_CASE_INSENSITIVE_PROPERTIES, true);
while (rs.next()) {
Map<String, Object> map = new HashMap<>();
for (int i = 1; i <= col; i++) {

View File

@ -14,6 +14,7 @@ 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.CCJSqlParser;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.Statements;
@ -35,7 +36,12 @@ public class SqlUtils {
public static void buildCanEditResult(String sql, DbType dbType, ExecuteResult executeResult) {
try {
Statement statement = CCJSqlParserUtil.parse(sql);
Statement statement ;
if (DbType.sqlserver.equals(dbType)) {
statement = CCJSqlParserUtil.parse(sql, ccjSqlParser -> ccjSqlParser.withSquareBracketQuotation(true));
} else {
statement = CCJSqlParserUtil.parse(sql);
}
if (statement instanceof Select) {
Select select = (Select) statement;
PlainSelect plainSelect = (PlainSelect) select.getSelectBody();
@ -56,7 +62,8 @@ public class SqlUtils {
// 检查函数是否为 "COUNT"
if ("COUNT".equalsIgnoreCase(function.getName())) {
executeResult.setCanEdit(false);
return; }
return;
}
}
}
}
@ -68,11 +75,12 @@ public class SqlUtils {
sqlSelectStatement.getSelect().getFirstQueryBlock().getFrom());
executeResult.setTableName(getMetaDataTableName(sqlExprTableSource.getCatalog(), sqlExprTableSource.getSchema(), sqlExprTableSource.getTableName()));
}
}else {
} else {
executeResult.setCanEdit(false);
}
}
} catch (Exception e) {
e.printStackTrace();
executeResult.setCanEdit(false);
}
}
@ -121,13 +129,13 @@ public class SqlUtils {
return list;
}
private static final String DEFAULT_VALUE = "CHAT2DB_UPDATE_TABLE_DATA_USER_FILLED_DEFAULT";
private static final String DEFAULT_VALUE = "CHAT2DB_UPDATE_TABLE_DATA_USER_FILLED_DEFAULT";
public static String getSqlValue(String value, String dataType) {
if (value == null) {
return null;
}
if(DEFAULT_VALUE.equals(value)){
if (DEFAULT_VALUE.equals(value)) {
return "DEFAULT";
}
DataTypeEnum dataTypeEnum = DataTypeEnum.getByCode(dataType);

View File

@ -0,0 +1,20 @@
package ai.chat2db.spi.util;
import ai.chat2db.spi.model.Table;
import ai.chat2db.spi.model.TableColumn;
import org.apache.commons.collections4.CollectionUtils;
public class TableUtils {
public static TableColumn getTableColumn(Table table,String columnName) {
if(table == null || CollectionUtils.isEmpty(table.getColumnList())){
return null ;
}
for (TableColumn tableColumn : table.getColumnList()) {
if(tableColumn.getName().equalsIgnoreCase(columnName)){
return tableColumn ;
}
}
return null;
}
}