From b0e7926e2281af756f6592d9658e02d11e120d03 Mon Sep 17 00:00:00 2001 From: jj <1558143046@qq.com> Date: Thu, 17 Aug 2023 11:37:05 +0800 Subject: [PATCH 01/16] Update README_CN.md --- README_CN.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README_CN.md b/README_CN.md index 110885dc..1647a09f 100644 --- a/README_CN.md +++ b/README_CN.md @@ -29,6 +29,9 @@ Languages: 中文 [English](README.md) +如果觉得 Chat2DB 对您有帮助的话,请帮忙github star +的右上角点个⭐ Star 和 Fork,您的支持是 Chat2DB 变得更好最大的动力 + ## 案例视频 https://github.com/chat2db/Chat2DB/assets/22975773/b58db908-5768-4a71-aa30-135d202e505f From f57d73c5701d47064b0c98c93d19a03118571776 Mon Sep 17 00:00:00 2001 From: jj <1558143046@qq.com> Date: Thu, 17 Aug 2023 11:39:05 +0800 Subject: [PATCH 02/16] Update README_CN.md --- README_CN.md | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/README_CN.md b/README_CN.md index 1647a09f..97c0ad11 100644 --- a/README_CN.md +++ b/README_CN.md @@ -12,21 +12,7 @@ [![GitHub Contributors](https://img.shields.io/github/contributors/chat2db/Chat2DB)](https://github.com/chat2db/Chat2DB/graphs/contributors) - -
-

分享 Chat2DB

-

- -Share on Telegram - -Share on Reddit - -

- -**许可说明**: Chat2DB 开源内容仅供个人免费使用,如想将该项目用于商业用途,请先联系该项目作者。 - Languages: 中文 [English](README.md) -
如果觉得 Chat2DB 对您有帮助的话,请帮忙github star From 2028d017f6d9c2e1fab8671740363ca022b4fffb Mon Sep 17 00:00:00 2001 From: jj <1558143046@qq.com> Date: Thu, 17 Aug 2023 11:39:56 +0800 Subject: [PATCH 03/16] Update README_CN.md --- README_CN.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README_CN.md b/README_CN.md index 97c0ad11..8b1d0c9e 100644 --- a/README_CN.md +++ b/README_CN.md @@ -12,6 +12,8 @@ [![GitHub Contributors](https://img.shields.io/github/contributors/chat2db/Chat2DB)](https://github.com/chat2db/Chat2DB/graphs/contributors) + +
Languages: 中文 [English](README.md)
From 39447d37ea9cbab4cf0890c4f5d6885760e61055 Mon Sep 17 00:00:00 2001 From: jj <1558143046@qq.com> Date: Thu, 17 Aug 2023 11:43:20 +0800 Subject: [PATCH 04/16] Update README_CN.md --- README_CN.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/README_CN.md b/README_CN.md index 8b1d0c9e..749357b5 100644 --- a/README_CN.md +++ b/README_CN.md @@ -14,11 +14,14 @@
-Languages: 中文 [English](README.md) -
+ Languages: 中文 [English](README.md) + 如果觉得 Chat2DB 对您有帮助的话,请帮忙github star 的右上角点个⭐ Star 和 Fork,您的支持是 Chat2DB 变得更好最大的动力 + + + ## 案例视频 From 4d84d095c9a7dc0370fefa17bb7b2b24c77feaee Mon Sep 17 00:00:00 2001 From: robinji0 <137188352+robinji0@users.noreply.github.com> Date: Sat, 26 Aug 2023 17:34:25 +0800 Subject: [PATCH 05/16] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index ea6cc509..075ae300 100644 --- a/README.md +++ b/README.md @@ -192,6 +192,8 @@ Follow our WeChat public account. +discord server + ## ❤️ Acknowledgements Thanks to all the students who contributed to Chat2DB~ From c07ef4381d379210a5d583d90f19a4f7f715c63b Mon Sep 17 00:00:00 2001 From: robinji0 <137188352+robinji0@users.noreply.github.com> Date: Sat, 26 Aug 2023 17:36:39 +0800 Subject: [PATCH 06/16] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 075ae300..ba1562cc 100644 --- a/README.md +++ b/README.md @@ -192,7 +192,7 @@ Follow our WeChat public account. -discord server + Click and join discord server ## ❤️ Acknowledgements From 656cd3a33838e4809f8736ddf3486f5641767fc2 Mon Sep 17 00:00:00 2001 From: SwallowGG <1558143046@qq.com> Date: Tue, 29 Aug 2023 21:52:53 +0800 Subject: [PATCH 07/16] fix dm function bug --- .../src/main/java/ai/chat2db/plugin/dm/DMMetaData.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chat2db-server/chat2db-plugins/chat2db-dm/src/main/java/ai/chat2db/plugin/dm/DMMetaData.java b/chat2db-server/chat2db-plugins/chat2db-dm/src/main/java/ai/chat2db/plugin/dm/DMMetaData.java index 009d12e1..f6555f64 100644 --- a/chat2db-server/chat2db-plugins/chat2db-dm/src/main/java/ai/chat2db/plugin/dm/DMMetaData.java +++ b/chat2db-server/chat2db-plugins/chat2db-dm/src/main/java/ai/chat2db/plugin/dm/DMMetaData.java @@ -34,7 +34,7 @@ public class DMMetaData extends DefaultMetaService implements MetaData { } private static String ROUTINES_SQL - = "SELECT OWNER, NAME, TEXT FROM ALL_SOURCE WHERE TYPE = '%s' AND NAME = '%s' AND NAME = '%s' ORDER BY LINE"; + = "SELECT OWNER, NAME, TEXT FROM ALL_SOURCE WHERE TYPE = '%s' AND OWNER = '%s' AND NAME = '%s' ORDER BY LINE"; @Override public Function function(Connection connection, @NotEmpty String databaseName, String schemaName, From 9b659016f681797bba05defae8229ea0ac1fee89 Mon Sep 17 00:00:00 2001 From: SwallowGG <1558143046@qq.com> Date: Tue, 29 Aug 2023 23:38:24 +0800 Subject: [PATCH 08/16] Fix bug with invalid schema specification --- .../domain/core/impl/DatabaseServiceImpl.java | 34 ++- .../tools/common/util/EasyIntegerUtils.java | 25 +++ .../controller/rdb/request/ColumnRequest.java | 2 +- .../web/api/controller/rdb/vo/ColumnVO.java | 2 +- .../chat2db/spi/jdbc/DefaultMetaService.java | 19 +- .../java/ai/chat2db/spi/model/Database.java | 2 + .../java/ai/chat2db/spi/model/Function.java | 7 + .../java/ai/chat2db/spi/model/Procedure.java | 9 + .../java/ai/chat2db/spi/model/Schema.java | 3 + .../main/java/ai/chat2db/spi/model/Table.java | 8 + .../ai/chat2db/spi/model/TableColumn.java | 23 +- .../chat2db/spi/model/TableIndexColumn.java | 14 +- .../java/ai/chat2db/spi/sql/SQLExecutor.java | 207 ++++++------------ .../ai/chat2db/spi/util/ResultSetUtils.java | 144 ++++++------ .../java/ai/chat2db/spi/util/SqlUtils.java | 11 +- 15 files changed, 269 insertions(+), 241 deletions(-) create mode 100644 chat2db-server/chat2db-server-tools/chat2db-server-tools-common/src/main/java/ai/chat2db/server/tools/common/util/EasyIntegerUtils.java diff --git a/chat2db-server/chat2db-server-domain/chat2db-server-domain-core/src/main/java/ai/chat2db/server/domain/core/impl/DatabaseServiceImpl.java b/chat2db-server/chat2db-server-domain/chat2db-server-domain-core/src/main/java/ai/chat2db/server/domain/core/impl/DatabaseServiceImpl.java index bdf1cf8b..589bbc7f 100644 --- a/chat2db-server/chat2db-server-domain/chat2db-server-domain-core/src/main/java/ai/chat2db/server/domain/core/impl/DatabaseServiceImpl.java +++ b/chat2db-server/chat2db-server-domain/chat2db-server-domain-core/src/main/java/ai/chat2db/server/domain/core/impl/DatabaseServiceImpl.java @@ -87,12 +87,42 @@ public class DatabaseServiceImpl implements DatabaseService { (key) -> param.isRefresh(), (key) -> { Connection connection = param.getConnection() == null ? Chat2DBContext.getConnection() : param.getConnection(); - MetaData metaData = Chat2DBContext.getMetaData(); - return metaData.schemas(connection, param.getDataBaseName()); + return getSchemaList(param.getDataBaseName(), connection); }); return ListResult.of(schemas); } + + private List getSchemaList(String databaseName, Connection connection) { + MetaData metaData = Chat2DBContext.getMetaData(); + List schemas = metaData.schemas(connection,databaseName); + sortSchema(schemas,connection); + return schemas; + } + + private void sortSchema(List schemas,Connection connection) { + if (CollectionUtils.isEmpty(schemas)) { + 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 < schemas.size(); i++) { + if (StringUtils.isNotBlank(ulr) && ulr.contains(schemas.get(i).getName())) { + num = i; + break; + } + } + if (num != -1 && num != 0) { + Collections.swap(schemas, num, 0); + } + } + @Override public DataResult queryDatabaseSchema(MetaDataQueryParam param) { MetaSchema metaSchema = new MetaSchema(); diff --git a/chat2db-server/chat2db-server-tools/chat2db-server-tools-common/src/main/java/ai/chat2db/server/tools/common/util/EasyIntegerUtils.java b/chat2db-server/chat2db-server-tools/chat2db-server-tools-common/src/main/java/ai/chat2db/server/tools/common/util/EasyIntegerUtils.java new file mode 100644 index 00000000..1e64099d --- /dev/null +++ b/chat2db-server/chat2db-server-tools/chat2db-server-tools-common/src/main/java/ai/chat2db/server/tools/common/util/EasyIntegerUtils.java @@ -0,0 +1,25 @@ +package ai.chat2db.server.tools.common.util; + +public class EasyIntegerUtils { + + /** + * 判断2个布尔值是否相同 + * + * @param b1 + * @param b2 + * @param defaultValue 默认值 ,假设b1 b2为空的情况下 取哪个默认值 + * @return + */ + public static boolean equals(Integer b1, Integer b2, Integer defaultValue) { + if (b1 == b2) { + return true; + } + if (b1 == null) { + b1 = defaultValue; + } + if (b2 == null) { + b2 = defaultValue; + } + return b1 == b2; + } +} diff --git a/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/rdb/request/ColumnRequest.java b/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/rdb/request/ColumnRequest.java index d0c30cd4..308faf17 100644 --- a/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/rdb/request/ColumnRequest.java +++ b/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/rdb/request/ColumnRequest.java @@ -35,7 +35,7 @@ public class ColumnRequest { /** * 是否为空 */ - private Boolean nullable; + private Integer nullable; /** * 是否主键 diff --git a/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/rdb/vo/ColumnVO.java b/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/rdb/vo/ColumnVO.java index a6f4b90b..c8757b6f 100644 --- a/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/rdb/vo/ColumnVO.java +++ b/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/rdb/vo/ColumnVO.java @@ -38,7 +38,7 @@ public class ColumnVO { /** * 是否为空 */ - private Boolean nullable; + private Integer nullable; /** * 是否主键 diff --git a/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/jdbc/DefaultMetaService.java b/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/jdbc/DefaultMetaService.java index e37b9189..002af04c 100644 --- a/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/jdbc/DefaultMetaService.java +++ b/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/jdbc/DefaultMetaService.java @@ -3,7 +3,6 @@ package ai.chat2db.spi.jdbc; import java.sql.Connection; import java.util.List; import java.util.Map; -import java.util.stream.Collectors; import ai.chat2db.spi.MetaData; import ai.chat2db.spi.model.Database; @@ -15,7 +14,6 @@ import ai.chat2db.spi.model.TableColumn; import ai.chat2db.spi.model.TableIndex; import ai.chat2db.spi.model.Trigger; import ai.chat2db.spi.sql.SQLExecutor; -import org.apache.commons.beanutils.BeanUtils; /** * @author jipengfei @@ -24,25 +22,12 @@ import org.apache.commons.beanutils.BeanUtils; public class DefaultMetaService implements MetaData { @Override public List databases(Connection connection) { - List dataBases = SQLExecutor.getInstance().databases(connection); - return dataBases.stream().map(str -> Database.builder().name(str).build()).collect(Collectors.toList()); - + return SQLExecutor.getInstance().databases(connection); } @Override public List schemas(Connection connection,String databaseName) { - List> maps = SQLExecutor.getInstance().schemas(connection, databaseName, null); - return maps.stream().map(map -> map2Schema(map)).collect(Collectors.toList()); - - } - - private Schema map2Schema(Map map) { - Schema schema = new Schema(); - try { - BeanUtils.populate(schema, map); - } catch (Exception e) { - } - return schema; + return SQLExecutor.getInstance().schemas(connection, databaseName, null); } @Override diff --git a/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/model/Database.java b/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/model/Database.java index ffc434f9..02e23ef1 100644 --- a/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/model/Database.java +++ b/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/model/Database.java @@ -4,6 +4,7 @@ import java.io.Serializable; import java.util.List; import ai.chat2db.server.tools.base.constant.EasyToolsConstant; +import com.fasterxml.jackson.annotation.JsonAlias; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -23,6 +24,7 @@ public class Database implements Serializable { /** * 数据库名字 */ + @JsonAlias({"TABLE_CAT"}) private String name; /** diff --git a/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/model/Function.java b/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/model/Function.java index 13876e75..b111ed8f 100644 --- a/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/model/Function.java +++ b/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/model/Function.java @@ -1,6 +1,7 @@ package ai.chat2db.spi.model; +import com.fasterxml.jackson.annotation.JsonAlias; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -26,16 +27,22 @@ public class Function { //SPECIFIC_NAME String => the name which uniquely identifies this function within its schema. This is a user specified, or DBMS generated, name that may be different then the FUNCTION_NAME for example with overload functions // + @JsonAlias({"FUNCTION_CAT"}) private String databaseName; + @JsonAlias({"FUNCTION_SCHEM"}) private String schemaName; + @JsonAlias({"FUNCTION_NAME"}) private String functionName; + @JsonAlias({"REMARKS"}) private String remarks; + @JsonAlias({"FUNCTION_TYPE"}) private Short functionType; + @JsonAlias({"SPECIFIC_NAME"}) private String specificName; private String functionBody; diff --git a/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/model/Procedure.java b/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/model/Procedure.java index 97c4986f..3c48489d 100644 --- a/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/model/Procedure.java +++ b/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/model/Procedure.java @@ -1,6 +1,7 @@ package ai.chat2db.spi.model; +import com.fasterxml.jackson.annotation.JsonAlias; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -26,16 +27,24 @@ public class Procedure { //SPECIFIC_NAME String => the name which uniquely identifies this procedure within its schema. This is a user specified, or DBMS generated, name that may be different then the PROCEDURE_NAME for example with overload procedures // + @JsonAlias({"PROCEDURE_CAT"}) private String databaseName; + @JsonAlias({"PROCEDURE_SCHEM"}) + private String schemaName; + @JsonAlias({"PROCEDURE_NAME"}) private String procedureName; + @JsonAlias({"REMARKS"}) private String remarks; + @JsonAlias({"PROCEDURE_TYPE"}) + private Short procedureType; + @JsonAlias({"SPECIFIC_NAME"}) private String specificName; private String procedureBody; diff --git a/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/model/Schema.java b/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/model/Schema.java index c72e3dfb..a54b927a 100644 --- a/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/model/Schema.java +++ b/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/model/Schema.java @@ -4,6 +4,7 @@ package ai.chat2db.spi.model; import java.io.Serializable; import ai.chat2db.server.tools.base.constant.EasyToolsConstant; +import com.fasterxml.jackson.annotation.JsonAlias; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -23,9 +24,11 @@ public class Schema implements Serializable { /** * databaseName */ + @JsonAlias({"TABLE_CATALOG"}) private String databaseName; /** * 数据名字 */ + @JsonAlias({"TABLE_SCHEM"}) private String name; } \ No newline at end of file diff --git a/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/model/Table.java b/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/model/Table.java index 188c5d82..bbd3dcb2 100644 --- a/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/model/Table.java +++ b/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/model/Table.java @@ -3,6 +3,7 @@ package ai.chat2db.spi.model; import java.util.List; +import com.fasterxml.jackson.annotation.JsonAlias; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -22,16 +23,21 @@ public class Table { /** * 表名 */ + @JsonAlias({"TABLE_NAME"}) private String name; /** * 描述 */ + @JsonAlias({"REMARKS"}) + private String comment; /** * DB 名 */ + @JsonAlias({"TABLE_SCHEM"}) + private String schemaName; /** @@ -52,11 +58,13 @@ public class Table { /** * 数据库名 */ + @JsonAlias("TABLE_CAT") private String databaseName; /** * 表类型 */ + @JsonAlias("TABLE_TYPE") private String type; /** diff --git a/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/model/TableColumn.java b/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/model/TableColumn.java index 530654ba..7d58d1d5 100644 --- a/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/model/TableColumn.java +++ b/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/model/TableColumn.java @@ -1,5 +1,6 @@ package ai.chat2db.spi.model; +import com.fasterxml.jackson.annotation.JsonAlias; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -24,6 +25,7 @@ public class TableColumn { /** * 列名 */ + @JsonAlias({"COLUMN_NAME"}) private String name; /** @@ -35,18 +37,24 @@ public class TableColumn { * 列的类型 * 比如 varchar(100) ,double(10,6) */ + + @JsonAlias({"TYPE_NAME"}) private String columnType; /** * 列的数据类型 * 比如 varchar ,double */ + + @JsonAlias({"DATA_TYPE"}) private Integer dataType; /** * 默认值 */ + + @JsonAlias({"COLUMN_DEF"}) private String defaultValue; /** @@ -58,6 +66,7 @@ public class TableColumn { /** * 注释 */ + @JsonAlias({"REMARKS"}) private String comment; /** @@ -68,11 +77,13 @@ public class TableColumn { /** * 空间名 */ + @JsonAlias({"TABLE_SCHEM"}) private String schemaName; /** * 数据库名 */ + @JsonAlias({"TABLE_CAT"}) private String databaseName; /** @@ -83,6 +94,8 @@ public class TableColumn { /** * column size. */ + + @JsonAlias({"COLUMN_SIZE"}) private Integer columnSize; /** @@ -93,11 +106,15 @@ public class TableColumn { /** * the number of fractional digits. Null is returned for data types where DECIMAL_DIGITS is not applicable. */ + + @JsonAlias({"DECIMAL_DIGITS"}) private Integer decimalDigits; /** * Radix (typically either 10 or 2) */ + + @JsonAlias({"NUM_PREC_RADIX"}) private Integer numPrecRadix; /** @@ -127,12 +144,16 @@ public class TableColumn { /** * index of column in table (starting at 1) */ + + @JsonAlias({"ORDINAL_POSITION"}) private Integer ordinalPosition; /** * ISO rules are used to determine the nullability for a column. */ - private Boolean nullable; + + @JsonAlias({"NULLABLE"}) + private Integer nullable; /** * String => Indicates whether this is a generated column diff --git a/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/model/TableIndexColumn.java b/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/model/TableIndexColumn.java index 810f8e37..091e9cd2 100644 --- a/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/model/TableIndexColumn.java +++ b/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/model/TableIndexColumn.java @@ -1,6 +1,7 @@ package ai.chat2db.spi.model; +import com.fasterxml.jackson.annotation.JsonAlias; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; @@ -20,11 +21,13 @@ public class TableIndexColumn { /** * 索引名称 */ + @JsonAlias({"INDEX_NAME"}) private String indexName; /** * 表名 */ + @JsonAlias ({"TABLE_NAME"}) private String tableName; /** @@ -42,17 +45,18 @@ public class TableIndexColumn { /** * 列名 */ + @JsonAlias({"COLUMN_NAME"}) private String columnName; /** * 顺序 */ + @JsonAlias({"ORDINAL_POSITION"}) private Short ordinalPosition; /** * 排序 * - * @see CollationEnum */ private String collation; @@ -60,41 +64,49 @@ public class TableIndexColumn { /** * 索引所属schema */ + @JsonAlias({"TABLE_SCHEM"}) private String schemaName; /** * 数据库名 */ + @JsonAlias({"TABLE_CAT"}) private String databaseName; /** * 是否唯一 */ + @JsonAlias({"NON_UNIQUE"}) private Boolean nonUnique; /** * index catalog (may be null); null when TYPE is tableIndexStatistic */ + @JsonAlias({"INDEX_QUALIFIER"}) private String indexQualifier; /** * ASC_OR_DESC String => column sort sequence, "A" => ascending, "D" => descending, may be null if sort sequence is not supported; null when TYPE is tableIndexStatistic */ + @JsonAlias({"ASC_OR_DESC"}) private String ascOrDesc; /** * CARDINALITY long => When TYPE is tableIndexStatistic, then this is the number of rows in the table; otherwise, it is the number of unique values in the index. */ + @JsonAlias({"CARDINALITY"}) private Long cardinality; /** * When TYPE is tableIndexStatistic then this is the number of pages used for the table, otherwise it is the number of pages used for the current index. */ + @JsonAlias({"PAGES"}) private Long pages; /** * Filter condition, if any. (may be null) */ + @JsonAlias({"FILTER_CONDITION"}) private String filterCondition; } diff --git a/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/sql/SQLExecutor.java b/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/sql/SQLExecutor.java index a109cf40..0bcd0e22 100644 --- a/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/sql/SQLExecutor.java +++ b/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/sql/SQLExecutor.java @@ -5,22 +5,14 @@ import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; -import java.util.HashMap; import java.util.List; -import java.util.Map; import java.util.function.Consumer; import java.util.function.Function; 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.model.ExecuteResult; -import ai.chat2db.spi.model.Header; -import ai.chat2db.spi.model.Procedure; -import ai.chat2db.spi.model.Table; -import ai.chat2db.spi.model.TableColumn; -import ai.chat2db.spi.model.TableIndex; -import ai.chat2db.spi.model.TableIndexColumn; +import ai.chat2db.spi.model.*; import ai.chat2db.spi.util.ResultSetUtils; import cn.hutool.core.date.TimeInterval; import com.google.common.collect.Lists; @@ -29,18 +21,10 @@ import org.apache.commons.lang3.StringUtils; import org.springframework.jdbc.support.JdbcUtils; import org.springframework.util.Assert; -import static ai.chat2db.spi.util.ResultSetUtils.buildColumn; -import static ai.chat2db.spi.util.ResultSetUtils.buildFunction; -import static ai.chat2db.spi.util.ResultSetUtils.buildProcedure; -import static ai.chat2db.spi.util.ResultSetUtils.buildTable; -import static ai.chat2db.spi.util.ResultSetUtils.buildTableIndexColumn; /** * Dbhub 统一数据库连接管理 - * TODO 长时间不用连接可以关闭,待优化 - * * @author jipengfei - * @version : DbhubDataSource.java */ @Slf4j public class SQLExecutor { @@ -56,9 +40,6 @@ public class SQLExecutor { return INSTANCE; } - //public Connection connection throws SQLException { - // return Chat2DBContext.connection; - //} public void close() { } @@ -72,7 +53,7 @@ public class SQLExecutor { * @return */ - public R executeSql(Connection connection, String sql, Function function) { + public R executeSql(Connection connection, String sql, Function function) { if (StringUtils.isBlank(sql)) { return null; } @@ -111,12 +92,12 @@ public class SQLExecutor { } public void executeSql(Connection connection, String sql, Consumer> headerConsumer, - Consumer> rowConsumer) { + Consumer> rowConsumer) { executeSql(connection, sql, headerConsumer, rowConsumer, true); } public void executeSql(Connection connection, String sql, Consumer> headerConsumer, - Consumer> rowConsumer, boolean limitSize) { + Consumer> rowConsumer, boolean limitSize) { Assert.notNull(sql, "SQL must not be null"); log.info("execute:{}", sql); try (Statement stmt = connection.createStatement();) { @@ -134,10 +115,10 @@ public class SQLExecutor { List
headerList = Lists.newArrayListWithExpectedSize(col); for (int i = 1; i <= col; i++) { headerList.add(Header.builder() - .dataType(ai.chat2db.spi.util.JdbcUtils.resolveDataType( - resultSetMetaData.getColumnTypeName(i), resultSetMetaData.getColumnType(i)).getCode()) - .name(ResultSetUtils.getColumnName(resultSetMetaData, i)) - .build()); + .dataType(ai.chat2db.spi.util.JdbcUtils.resolveDataType( + resultSetMetaData.getColumnTypeName(i), resultSetMetaData.getColumnType(i)).getCode()) + .name(ResultSetUtils.getColumnName(resultSetMetaData, i)) + .build()); } headerConsumer.accept(headerList); @@ -199,10 +180,10 @@ public class SQLExecutor { executeResult.setHeaderList(headerList); for (int i = 1; i <= col; i++) { headerList.add(Header.builder() - .dataType(ai.chat2db.spi.util.JdbcUtils.resolveDataType( - resultSetMetaData.getColumnTypeName(i), resultSetMetaData.getColumnType(i)).getCode()) - .name(ResultSetUtils.getColumnName(resultSetMetaData, i)) - .build()); + .dataType(ai.chat2db.spi.util.JdbcUtils.resolveDataType( + resultSetMetaData.getColumnTypeName(i), resultSetMetaData.getColumnType(i)).getCode()) + .name(ResultSetUtils.getColumnName(resultSetMetaData, i)) + .build()); } // 获取数据信息 @@ -249,58 +230,43 @@ public class SQLExecutor { * @param connection * @return */ - public List databases(Connection connection) { - List tables = Lists.newArrayList(); + public List databases(Connection connection) { try (ResultSet resultSet = connection.getMetaData().getCatalogs();) { - if (resultSet != null) { - while (resultSet.next()) { - tables.add(resultSet.getString("TABLE_CAT")); - } - } + return ResultSetUtils.toObjectList(resultSet, Database.class); } catch (SQLException e) { throw new RuntimeException(e); } - return tables; } /** - * 获取所有的schema - * - * @param connection - * @param databaseName - * @param schemaName - * @return + * Retrieves the schema names available in this database. The results are ordered by TABLE_CATALOG and TABLE_SCHEM. + * The schema columns are: + * TABLE_SCHEM String => schema name + * TABLE_CATALOG String => catalog name (may be null) + * Params: + * catalog – a catalog name; must match the catalog name as it is stored in the database;"" retrieves those without a catalog; null means catalog name should not be used to narrow down the search. schemaPattern – a schema name; must match the schema name as it is stored in the database; null means schema name should not be used to narrow down the search. + * Returns: + * a ResultSet object in which each row is a schema description + * Throws: + * SQLException – if a database access error occurs + * Since: + * 1.6 + * See Also: + * getSearchStringEscape */ - public List> schemas(Connection connection, String databaseName, String schemaName) { - List> schemaList = Lists.newArrayList(); + public List schemas(Connection connection, String databaseName, String schemaName) { if (StringUtils.isEmpty(databaseName) && StringUtils.isEmpty(schemaName)) { try (ResultSet resultSet = connection.getMetaData().getSchemas()) { - if (resultSet != null) { - while (resultSet.next()) { - Map map = new HashMap<>(); - map.put("name", resultSet.getString("TABLE_SCHEM")); - map.put("databaseName", resultSet.getString("TABLE_CATALOG")); - schemaList.add(map); - } - } + return ResultSetUtils.toObjectList(resultSet, Schema.class); } catch (SQLException e) { throw new RuntimeException("Get schemas error", e); } - return schemaList; } try (ResultSet resultSet = connection.getMetaData().getSchemas(databaseName, schemaName)) { - if (resultSet != null) { - while (resultSet.next()) { - Map map = new HashMap<>(); - map.put("name", resultSet.getString("TABLE_SCHEM")); - map.put("databaseName", resultSet.getString("TABLE_CATALOG")); - schemaList.add(map); - } - } + return ResultSetUtils.toObjectList(resultSet, Schema.class); } catch (SQLException e) { throw new RuntimeException("Get schemas error", e); } - return schemaList; } /** @@ -314,24 +280,13 @@ public class SQLExecutor { * @return */ public List tables(Connection connection, String databaseName, String schemaName, String tableName, - String types[]) { - List
tables = Lists.newArrayList(); - int n = 0; + String types[]) { try (ResultSet resultSet = connection.getMetaData().getTables(databaseName, schemaName, tableName, - types)) { - if (resultSet != null) { - while (resultSet.next()) { - n++; - tables.add(buildTable(resultSet)); - if (n >= 1000) {// 最多只取1000条 - break; - } - } - } + types)) { + return ResultSetUtils.toObjectList(resultSet, Table.class); } catch (SQLException e) { throw new RuntimeException(e); } - return tables; } /** @@ -345,99 +300,81 @@ public class SQLExecutor { * @return */ public List columns(Connection connection, String databaseName, String schemaName, String tableName, - String columnName) { - List tableColumns = Lists.newArrayList(); + String columnName) { try (ResultSet resultSet = connection.getMetaData().getColumns(databaseName, schemaName, tableName, - columnName)) { - if (resultSet != null) { - while (resultSet.next()) { - tableColumns.add(buildColumn(resultSet)); - } - } + columnName)) { + return ResultSetUtils.toObjectList(resultSet, TableColumn.class); } catch (Exception e) { throw new RuntimeException(e); } - return tableColumns; } /** - * 获取所有的数据库表索引 + * get all table index info * - * @param connection - * @param databaseName - * @param schemaName - * @param tableName - * @return + * @param connection connection + * @param databaseName databaseName of the index + * @param schemaName schemaName of the index + * @param tableName tableName of the index + * @return List table index list */ public List indexes(Connection connection, String databaseName, String schemaName, String tableName) { List tableIndices = Lists.newArrayList(); try (ResultSet resultSet = connection.getMetaData().getIndexInfo(databaseName, schemaName, tableName, - false, - false)) { - List tableIndexColumns = Lists.newArrayList(); - - while (resultSet != null && resultSet.next()) { - tableIndexColumns.add(buildTableIndexColumn(resultSet)); - } - + false, + false)) { + List tableIndexColumns = ResultSetUtils.toObjectList(resultSet, TableIndexColumn.class); tableIndexColumns.stream().filter(c -> c.getIndexName() != null).collect( - Collectors.groupingBy(TableIndexColumn::getIndexName)).entrySet() - .stream().forEach(entry -> { - TableIndex tableIndex = new TableIndex(); - TableIndexColumn column = entry.getValue().get(0); - tableIndex.setName(entry.getKey()); - tableIndex.setTableName(column.getTableName()); - tableIndex.setSchemaName(column.getSchemaName()); - tableIndex.setDatabaseName(column.getDatabaseName()); - tableIndex.setUnique(!column.getNonUnique()); - tableIndex.setColumnList(entry.getValue()); - tableIndices.add(tableIndex); - }); + Collectors.groupingBy(TableIndexColumn::getIndexName)).entrySet() + .stream().forEach(entry -> { + TableIndex tableIndex = new TableIndex(); + TableIndexColumn column = entry.getValue().get(0); + tableIndex.setName(entry.getKey()); + tableIndex.setTableName(column.getTableName()); + tableIndex.setSchemaName(column.getSchemaName()); + tableIndex.setDatabaseName(column.getDatabaseName()); + tableIndex.setUnique(!column.getNonUnique()); + tableIndex.setColumnList(entry.getValue()); + tableIndices.add(tableIndex); + }); } catch (SQLException e) { throw new RuntimeException(e); } return tableIndices; } + /** - * 获取所有的函数 + * Get all functions available in a catalog. * - * @param connection - * @param databaseName - * @param schemaName - * @return + * @param connection connection + * @param databaseName databaseName of the function + * @param schemaName schemaName of the function + * @return List */ public List functions(Connection connection, String databaseName, - String schemaName) { - List functions = Lists.newArrayList(); + String schemaName) { try (ResultSet resultSet = connection.getMetaData().getFunctions(databaseName, schemaName, null);) { - while (resultSet != null && resultSet.next()) { - functions.add(buildFunction(resultSet)); - } + return ResultSetUtils.toObjectList(resultSet, ai.chat2db.spi.model.Function.class); } catch (Exception e) { throw new RuntimeException(e); } - return functions; } /** - * 获取所有的存储过程 + * procedure list * - * @param connection - * @param databaseName - * @param schemaName - * @return + * @param connection connection + * @param databaseName databaseName + * @param schemaName schemaName + * @return List */ public List procedures(Connection connection, String databaseName, String schemaName) { - List procedures = Lists.newArrayList(); try (ResultSet resultSet = connection.getMetaData().getProcedures(databaseName, schemaName, null)) { - while (resultSet != null && resultSet.next()) { - procedures.add(buildProcedure(resultSet)); - } + return ResultSetUtils.toObjectList(resultSet, Procedure.class); } catch (Exception e) { throw new RuntimeException(e); } - return procedures; } } diff --git a/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/util/ResultSetUtils.java b/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/util/ResultSetUtils.java index f26a446d..76c1fce9 100644 --- a/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/util/ResultSetUtils.java +++ b/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/util/ResultSetUtils.java @@ -4,8 +4,16 @@ package ai.chat2db.spi.util; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; +import java.util.HashMap; +import java.util.List; +import java.util.Map; -import ai.chat2db.spi.model.*; +import com.fasterxml.jackson.databind.DeserializationFeature; +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 @@ -13,99 +21,79 @@ import ai.chat2db.spi.model.*; */ public class ResultSetUtils { - public static ai.chat2db.spi.model.Function buildFunction(ResultSet resultSet) { - ai.chat2db.spi.model.Function function - = new ai.chat2db.spi.model.Function(); + + public static T toObject(ResultSet rs, Class clazz) { try { - function.setDatabaseName(getString(resultSet, "FUNCTION_CAT")); - function.setSchemaName(getString(resultSet, "FUNCTION_SCHEM")); - function.setFunctionName(getString(resultSet, "FUNCTION_NAME")); - function.setRemarks(getString(resultSet, "REMARKS")); - function.setFunctionType(resultSet.getShort("FUNCTION_TYPE")); - function.setSpecificName(getString(resultSet, "SPECIFIC_NAME")); + if (rs == null || clazz == null) { + return null; + } + ResultSetMetaData resultSetMetaData = rs.getMetaData(); + int col = resultSetMetaData.getColumnCount(); + List headerList = getRsHeader(rs); + Map 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); } - return function; } - public static Procedure buildProcedure(ResultSet resultSet) { - Procedure procedure = new Procedure(); + private static List getRsHeader(ResultSet rs) { try { - procedure.setDatabaseName(getString(resultSet, "PROCEDURE_CAT")); - procedure.setSchemaName(getString(resultSet, "PROCEDURE_SCHEM")); - procedure.setProcedureName(getString(resultSet, "PROCEDURE_NAME")); - procedure.setRemarks(getString(resultSet, "REMARKS")); - procedure.setProcedureType(resultSet.getShort("PROCEDURE_TYPE")); - procedure.setSpecificName(getString(resultSet, "SPECIFIC_NAME")); + ResultSetMetaData resultSetMetaData = rs.getMetaData(); + int col = resultSetMetaData.getColumnCount(); + List headerList = Lists.newArrayListWithExpectedSize(col); + for (int i = 1; i <= col; i++) { + headerList.add(getColumnName(resultSetMetaData, i)); + } + return headerList; } catch (SQLException e) { throw new RuntimeException(e); } - return procedure; } - - public static TableIndexColumn buildTableIndexColumn(ResultSet resultSet) throws SQLException { - TableIndexColumn tableIndexColumn = new TableIndexColumn(); - tableIndexColumn.setColumnName(getString(resultSet, "COLUMN_NAME")); - tableIndexColumn.setIndexName(getString(resultSet, "INDEX_NAME")); - tableIndexColumn.setAscOrDesc(getString(resultSet, "ASC_OR_DESC")); - tableIndexColumn.setCardinality(resultSet.getLong("CARDINALITY")); - tableIndexColumn.setPages(resultSet.getLong("PAGES")); - tableIndexColumn.setFilterCondition(getString(resultSet, "FILTER_CONDITION")); - tableIndexColumn.setIndexQualifier(getString(resultSet, "INDEX_QUALIFIER")); - // tableIndexColumn.setIndexType(resultSet.getShort("TYPE")); - tableIndexColumn.setNonUnique(resultSet.getBoolean("NON_UNIQUE")); - tableIndexColumn.setOrdinalPosition(resultSet.getShort("ORDINAL_POSITION")); - tableIndexColumn.setDatabaseName(getString(resultSet, "TABLE_CAT")); - tableIndexColumn.setSchemaName(getString(resultSet, "TABLE_SCHEM")); - tableIndexColumn.setTableName(getString(resultSet, "TABLE_NAME")); - return tableIndexColumn; - } - - public static TableColumn buildColumn(ResultSet resultSet) throws SQLException { - TableColumn tableColumn = new TableColumn(); - tableColumn.setDatabaseName(getString(resultSet, "TABLE_CAT")); - tableColumn.setSchemaName(getString(resultSet, "TABLE_SCHEM")); - tableColumn.setTableName(getString(resultSet, "TABLE_NAME")); - tableColumn.setName(getString(resultSet, "COLUMN_NAME")); - tableColumn.setComment(getString(resultSet, "REMARKS")); - tableColumn.setDefaultValue(getString(resultSet, "COLUMN_DEF")); - tableColumn.setColumnType(getString(resultSet, "TYPE_NAME")); - tableColumn.setColumnSize(resultSet.getInt("COLUMN_SIZE")); - tableColumn.setDataType(resultSet.getInt("DATA_TYPE")); - tableColumn.setNullable(resultSet.getInt("NULLABLE") == 1); - tableColumn.setOrdinalPosition(resultSet.getInt("ORDINAL_POSITION")); - //tableColumn.setAutoIncrement("YES".equals(getString,resultSet,"IS_AUTOINCREMENT"))); - //tableColumn.setGeneratedColumn("YES".equals(getString,resultSet,"IS_GENERATEDCOLUMN"))); - tableColumn.setOrdinalPosition(resultSet.getInt("ORDINAL_POSITION")); - tableColumn.setDecimalDigits(resultSet.getInt("DECIMAL_DIGITS")); - tableColumn.setNumPrecRadix(resultSet.getInt("NUM_PREC_RADIX")); - tableColumn.setCharOctetLength(resultSet.getInt("CHAR_OCTET_LENGTH")); - return tableColumn; - } - - public static Table buildTable(ResultSet resultSet) throws SQLException { - Table table = new Table(); - table.setName(getString(resultSet, "TABLE_NAME")); - table.setComment(getString(resultSet, "REMARKS")); - table.setDatabaseName(getString(resultSet, "TABLE_CAT")); - table.setSchemaName(getString(resultSet, "TABLE_SCHEM")); - table.setType(getString(resultSet, "TABLE_TYPE")); - return table; - } - - private static String getString(ResultSet resultSet, String name) { - if (resultSet == null) { - return null; - } + /** + * + * @param rs + * @param clazz + * @return + * @param + */ + public static List toObjectList(ResultSet rs, Class clazz) { try { - return resultSet.getString(name); - } catch (Exception e) { - return null; + if (rs == null || clazz == null) { + return Lists.newArrayList(); + } + List list = Lists.newArrayList(); + ResultSetMetaData rsMetaData = rs.getMetaData(); + int col = rsMetaData.getColumnCount(); + List headerList = getRsHeader(rs); + ObjectMapper mapper = new ObjectMapper(); + mapper.setPropertyNamingStrategy(PropertyNamingStrategies.SNAKE_CASE); + mapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); + while (rs.next()) { + Map map = new HashMap<>(); + for (int i = 1; i <= col; i++) { + map.put(headerList.get(i-1), rs.getObject(i)); + } + T obj = mapper.convertValue(map, clazz); + + list.add(obj); + } + return list; + } catch (SQLException e) { + throw new RuntimeException(e); } } + public static String getColumnName(ResultSetMetaData resultSetMetaData, int column) throws SQLException { String columnLabel = resultSetMetaData.getColumnLabel(column); if (columnLabel != null) { diff --git a/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/util/SqlUtils.java b/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/util/SqlUtils.java index bf58ca34..851dc75b 100644 --- a/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/util/SqlUtils.java +++ b/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/util/SqlUtils.java @@ -8,6 +8,7 @@ import java.util.Objects; import java.util.Set; import java.util.stream.Collectors; +import ai.chat2db.server.tools.common.util.EasyIntegerUtils; import com.alibaba.druid.DbType; import com.alibaba.druid.sql.SQLUtils; import com.alibaba.druid.sql.ast.SQLDataTypeImpl; @@ -85,7 +86,7 @@ public class SqlUtils { mySqlCreateTableStatement.addColumn(sqlColumnDefinition); sqlColumnDefinition.setName(tableColumn.getName()); sqlColumnDefinition.setDataType(new SQLDataTypeImpl(tableColumn.getColumnType())); - if (BooleanUtils.isNotFalse(tableColumn.getNullable())) { + if (tableColumn.getNullable()==1) { sqlColumnDefinition.addConstraint(new SQLNullConstraint()); } else { sqlColumnDefinition.addConstraint(new SQLNotNullConstraint()); @@ -221,7 +222,7 @@ public class SqlUtils { sqlAlterTableAddColumn.addColumn(sqlColumnDefinition); sqlColumnDefinition.setName(newTableColumn.getName()); sqlColumnDefinition.setDataType(new SQLDataTypeImpl(newTableColumn.getColumnType())); - if (BooleanUtils.isNotTrue(newTableColumn.getNullable())) { + if (newTableColumn.getNullable()!=1) { sqlColumnDefinition.addConstraint(new SQLNotNullConstraint()); } if (!Objects.isNull(newTableColumn.getDefaultValue())) { @@ -236,7 +237,7 @@ public class SqlUtils { // 代表可能修改字段 或者没变 boolean hasChange = !StringUtils.equals(oldTableColumn.getName(), newTableColumn.getName()) || !StringUtils.equals(oldTableColumn.getColumnType(), newTableColumn.getColumnType()) - || !EasyBooleanUtils.equals(oldTableColumn.getNullable(), newTableColumn.getNullable(), Boolean.TRUE) + || !EasyIntegerUtils.equals(oldTableColumn.getNullable(), newTableColumn.getNullable(), 1) || !StringUtils.equals(oldTableColumn.getDefaultValue(), newTableColumn.getDefaultValue()) || !EasyBooleanUtils.equals(oldTableColumn.getAutoIncrement(), newTableColumn.getAutoIncrement(), Boolean.FALSE) @@ -256,7 +257,7 @@ public class SqlUtils { mySqlAlterTableChangeColumn.setNewColumnDefinition(sqlColumnDefinition); sqlColumnDefinition.setName(newTableColumn.getName()); sqlColumnDefinition.setDataType(new SQLDataTypeImpl(newTableColumn.getColumnType())); - if (BooleanUtils.isNotTrue(newTableColumn.getNullable())) { + if (newTableColumn.getNullable()!=1) { sqlColumnDefinition.addConstraint(new SQLNotNullConstraint()); } if (!Objects.isNull(newTableColumn.getDefaultValue())) { @@ -274,7 +275,7 @@ public class SqlUtils { mySqlAlterTableModifyColumn.setNewColumnDefinition(sqlColumnDefinition); sqlColumnDefinition.setName(newTableColumn.getName()); sqlColumnDefinition.setDataType(new SQLDataTypeImpl(newTableColumn.getColumnType())); - if (BooleanUtils.isNotTrue(newTableColumn.getNullable())) { + if (newTableColumn.getNullable()!=1) { sqlColumnDefinition.addConstraint(new SQLNotNullConstraint()); } if (!Objects.isNull(newTableColumn.getDefaultValue())) { From 7985ffcaa0ff011fd5dc3888f7fe4979d8227ee0 Mon Sep 17 00:00:00 2001 From: JiaJu Zhuang <5152853@qq.com> Date: Sun, 3 Sep 2023 13:11:36 +0800 Subject: [PATCH 09/16] Modify pagination logic --- .../core/impl/DlTemplateServiceImpl.java | 51 +++----- .../java/ai/chat2db/spi/sql/SQLExecutor.java | 116 ++++++++++-------- 2 files changed, 85 insertions(+), 82 deletions(-) diff --git a/chat2db-server/chat2db-server-domain/chat2db-server-domain-core/src/main/java/ai/chat2db/server/domain/core/impl/DlTemplateServiceImpl.java b/chat2db-server/chat2db-server-domain/chat2db-server-domain-core/src/main/java/ai/chat2db/server/domain/core/impl/DlTemplateServiceImpl.java index 0ed82aa4..c61644bc 100644 --- a/chat2db-server/chat2db-server-domain/chat2db-server-domain-core/src/main/java/ai/chat2db/server/domain/core/impl/DlTemplateServiceImpl.java +++ b/chat2db-server/chat2db-server-domain/chat2db-server-domain-core/src/main/java/ai/chat2db/server/domain/core/impl/DlTemplateServiceImpl.java @@ -34,7 +34,6 @@ import ai.chat2db.spi.util.SqlUtils; import com.google.common.collect.Lists; import lombok.extern.slf4j.Slf4j; import org.apache.commons.collections4.CollectionUtils; -import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.stereotype.Service; @@ -67,7 +66,7 @@ public class DlTemplateServiceImpl implements DlTemplateService { ListResult listResult = ListResult.of(result); // 执行sql for (String originalSql : sqlList) { - ExecuteResult executeResult = executeSQL(originalSql,dbType,param); + ExecuteResult executeResult = executeSQL(originalSql, dbType, param); result.add(executeResult); if (!executeResult.getSuccess()) { listResult.setSuccess(false); @@ -78,53 +77,44 @@ public class DlTemplateServiceImpl implements DlTemplateService { return listResult; } - private ExecuteResult executeSQL(String originalSql,DbType dbType,DlExecuteParam param) { - String sql = originalSql; - int pageNo = 0; + private ExecuteResult executeSQL(String originalSql, DbType dbType, DlExecuteParam param) { + int pageNo = 1; int pageSize = 0; + Integer offset = null; + Integer count = null; String sqlType = SqlTypeEnum.UNKNOWN.getCode(); // 解析sql分页 SQLStatement sqlStatement; - boolean autoLimit = false; try { - sqlStatement = SQLUtils.parseSingleStatement(sql, dbType); + sqlStatement = SQLUtils.parseSingleStatement(originalSql, dbType); // 是否需要代码帮忙分页 if (sqlStatement instanceof SQLSelectStatement) { - // 不是查询全部数据 而且 用户自己没有传分页 - autoLimit = BooleanUtils.isNotTrue(param.getPageSizeAll()) && SQLUtils.getLimit(sqlStatement, - dbType) - == null; - if (autoLimit) { - pageNo = Optional.ofNullable(param.getPageNo()).orElse(1); - pageSize = Optional.ofNullable(param.getPageSize()).orElse(EasyToolsConstant.MAX_PAGE_SIZE); - int offset = (pageNo - 1) * pageSize; - try { - sql = PagerUtils.limit(sql, dbType, offset, pageSize); - } catch (Exception e) { - autoLimit = false; - } - } + pageNo = Optional.ofNullable(param.getPageNo()).orElse(1); + pageSize = Optional.ofNullable(param.getPageSize()).orElse(EasyToolsConstant.MAX_PAGE_SIZE); + offset = (pageNo - 1) * pageSize; + count = pageSize; sqlType = SqlTypeEnum.SELECT.getCode(); } } catch (ParserException e) { - log.warn("解析sql失败:{}", sql, e); + log.warn("解析sql失败:{}", originalSql, e); } - ExecuteResult executeResult = execute(sql); + ExecuteResult executeResult = execute(originalSql, offset, count); executeResult.setSqlType(sqlType); executeResult.setOriginalSql(originalSql); - // 自动分页 - if (autoLimit) { + + if (SqlTypeEnum.SELECT.getCode().equals(sqlType)) { executeResult.setPageNo(pageNo); executeResult.setPageSize(pageSize); executeResult.setHasNextPage( CollectionUtils.size(executeResult.getDataList()) >= executeResult.getPageSize()); } else { - executeResult.setPageNo(1); + executeResult.setPageNo(pageNo); executeResult.setPageSize(CollectionUtils.size(executeResult.getDataList())); executeResult.setHasNextPage(Boolean.FALSE); } + // Splice row numbers List
newHeaderList = new ArrayList<>(); newHeaderList.add(Header.builder() @@ -150,9 +140,6 @@ public class DlTemplateServiceImpl implements DlTemplateService { return executeResult; } - - - private String calculateFuzzyTotal(int pageNo, int pageSize, ExecuteResult executeResult) { int dataSize = CollectionUtils.size(executeResult.getDataList()); if (pageSize <= 0) { @@ -179,7 +166,7 @@ public class DlTemplateServiceImpl implements DlTemplateService { throw new BusinessException("dataSource.sqlAnalysisError"); } sql = PagerUtils.count(sql, dbType); - ExecuteResult executeResult = execute(sql); + ExecuteResult executeResult = execute(sql, null, null); List> dataList = executeResult.getDataList(); if (CollectionUtils.isEmpty(dataList)) { @@ -194,10 +181,10 @@ public class DlTemplateServiceImpl implements DlTemplateService { return DataResult.of(Long.valueOf(count)); } - private ExecuteResult execute(String sql) { + private ExecuteResult execute(String sql, Integer offset, Integer count) { ExecuteResult executeResult; try { - executeResult = SQLExecutor.getInstance().execute(Chat2DBContext.getConnection(), sql); + executeResult = SQLExecutor.getInstance().execute(sql, Chat2DBContext.getConnection(), true, offset, count); } catch (SQLException e) { log.warn("执行sql:{}异常", sql, e); executeResult = ExecuteResult.builder() diff --git a/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/sql/SQLExecutor.java b/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/sql/SQLExecutor.java index 0bcd0e22..06f1fc6d 100644 --- a/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/sql/SQLExecutor.java +++ b/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/sql/SQLExecutor.java @@ -21,9 +21,9 @@ import org.apache.commons.lang3.StringUtils; import org.springframework.jdbc.support.JdbcUtils; import org.springframework.util.Assert; - /** * Dbhub 统一数据库连接管理 + * * @author jipengfei */ @Slf4j @@ -40,7 +40,6 @@ public class SQLExecutor { return INSTANCE; } - public void close() { } @@ -53,7 +52,7 @@ public class SQLExecutor { * @return */ - public R executeSql(Connection connection, String sql, Function function) { + public R executeSql(Connection connection, String sql, Function function) { if (StringUtils.isBlank(sql)) { return null; } @@ -92,12 +91,12 @@ public class SQLExecutor { } public void executeSql(Connection connection, String sql, Consumer> headerConsumer, - Consumer> rowConsumer) { + Consumer> rowConsumer) { executeSql(connection, sql, headerConsumer, rowConsumer, true); } public void executeSql(Connection connection, String sql, Consumer> headerConsumer, - Consumer> rowConsumer, boolean limitSize) { + Consumer> rowConsumer, boolean limitSize) { Assert.notNull(sql, "SQL must not be null"); log.info("execute:{}", sql); try (Statement stmt = connection.createStatement();) { @@ -115,10 +114,10 @@ public class SQLExecutor { List
headerList = Lists.newArrayListWithExpectedSize(col); for (int i = 1; i <= col; i++) { headerList.add(Header.builder() - .dataType(ai.chat2db.spi.util.JdbcUtils.resolveDataType( - resultSetMetaData.getColumnTypeName(i), resultSetMetaData.getColumnType(i)).getCode()) - .name(ResultSetUtils.getColumnName(resultSetMetaData, i)) - .build()); + .dataType(ai.chat2db.spi.util.JdbcUtils.resolveDataType( + resultSetMetaData.getColumnTypeName(i), resultSetMetaData.getColumnType(i)).getCode()) + .name(ResultSetUtils.getColumnName(resultSetMetaData, i)) + .build()); } headerConsumer.accept(headerList); @@ -146,17 +145,23 @@ public class SQLExecutor { * @throws SQLException */ public ExecuteResult execute(final String sql, Connection connection) throws SQLException { - return execute(sql, connection, true); + return execute(sql, connection, true, null, null); } /** * 执行sql * * @param sql + * @param connection + * @param limitRowSize + * @param offset + * @param count * @return * @throws SQLException */ - public ExecuteResult execute(final String sql, Connection connection, boolean limitSize) throws SQLException { + public ExecuteResult execute(final String sql, Connection connection, boolean limitRowSize, Integer offset, + Integer count) + throws SQLException { Assert.notNull(sql, "SQL must not be null"); log.info("execute:{}", sql); @@ -180,23 +185,32 @@ public class SQLExecutor { executeResult.setHeaderList(headerList); for (int i = 1; i <= col; i++) { headerList.add(Header.builder() - .dataType(ai.chat2db.spi.util.JdbcUtils.resolveDataType( - resultSetMetaData.getColumnTypeName(i), resultSetMetaData.getColumnType(i)).getCode()) - .name(ResultSetUtils.getColumnName(resultSetMetaData, i)) - .build()); + .dataType(ai.chat2db.spi.util.JdbcUtils.resolveDataType( + resultSetMetaData.getColumnTypeName(i), resultSetMetaData.getColumnType(i)).getCode()) + .name(ResultSetUtils.getColumnName(resultSetMetaData, i)) + .build()); } // 获取数据信息 List> dataList = Lists.newArrayList(); executeResult.setDataList(dataList); - int n = 0; - while (rs.next() && n < EasyToolsConstant.MAX_PAGE_SIZE) { - n++; + if (offset == null || offset < 0) { + offset = 0; + } + int rowNumber = 0; + int rowCount = 1; + while (rs.next()) { + if (rowNumber++ < offset) { + continue; + } List row = Lists.newArrayListWithExpectedSize(col); dataList.add(row); for (int i = 1; i <= col; i++) { - row.add(ai.chat2db.spi.util.JdbcUtils.getResultSetValue(rs, i, limitSize)); + row.add(ai.chat2db.spi.util.JdbcUtils.getResultSetValue(rs, i, limitRowSize)); + } + if (count != null && count > 0 && rowCount++ >= count) { + break; } } executeResult.setDuration(timeInterval.interval()); @@ -221,7 +235,7 @@ public class SQLExecutor { * @throws SQLException */ public ExecuteResult execute(Connection connection, String sql) throws SQLException { - return execute(sql, connection, true); + return execute(sql, connection, true, null, null); } /** @@ -232,7 +246,7 @@ public class SQLExecutor { */ public List databases(Connection connection) { try (ResultSet resultSet = connection.getMetaData().getCatalogs();) { - return ResultSetUtils.toObjectList(resultSet, Database.class); + return ResultSetUtils.toObjectList(resultSet, Database.class); } catch (SQLException e) { throw new RuntimeException(e); } @@ -244,7 +258,10 @@ public class SQLExecutor { * TABLE_SCHEM String => schema name * TABLE_CATALOG String => catalog name (may be null) * Params: - * catalog – a catalog name; must match the catalog name as it is stored in the database;"" retrieves those without a catalog; null means catalog name should not be used to narrow down the search. schemaPattern – a schema name; must match the schema name as it is stored in the database; null means schema name should not be used to narrow down the search. + * catalog – a catalog name; must match the catalog name as it is stored in the database;"" retrieves those without + * a catalog; null means catalog name should not be used to narrow down the search. schemaPattern – a schema name; + * must match the schema name as it is stored in the database; null means schema name should not be used to narrow + * down the search. * Returns: * a ResultSet object in which each row is a schema description * Throws: @@ -280,9 +297,9 @@ public class SQLExecutor { * @return */ public List
tables(Connection connection, String databaseName, String schemaName, String tableName, - String types[]) { + String types[]) { try (ResultSet resultSet = connection.getMetaData().getTables(databaseName, schemaName, tableName, - types)) { + types)) { return ResultSetUtils.toObjectList(resultSet, Table.class); } catch (SQLException e) { throw new RuntimeException(e); @@ -300,9 +317,9 @@ public class SQLExecutor { * @return */ public List columns(Connection connection, String databaseName, String schemaName, String tableName, - String columnName) { + String columnName) { try (ResultSet resultSet = connection.getMetaData().getColumns(databaseName, schemaName, tableName, - columnName)) { + columnName)) { return ResultSetUtils.toObjectList(resultSet, TableColumn.class); } catch (Exception e) { throw new RuntimeException(e); @@ -312,48 +329,47 @@ public class SQLExecutor { /** * get all table index info * - * @param connection connection + * @param connection connection * @param databaseName databaseName of the index - * @param schemaName schemaName of the index - * @param tableName tableName of the index + * @param schemaName schemaName of the index + * @param tableName tableName of the index * @return List table index list */ public List indexes(Connection connection, String databaseName, String schemaName, String tableName) { List tableIndices = Lists.newArrayList(); try (ResultSet resultSet = connection.getMetaData().getIndexInfo(databaseName, schemaName, tableName, - false, - false)) { + false, + false)) { List tableIndexColumns = ResultSetUtils.toObjectList(resultSet, TableIndexColumn.class); tableIndexColumns.stream().filter(c -> c.getIndexName() != null).collect( - Collectors.groupingBy(TableIndexColumn::getIndexName)).entrySet() - .stream().forEach(entry -> { - TableIndex tableIndex = new TableIndex(); - TableIndexColumn column = entry.getValue().get(0); - tableIndex.setName(entry.getKey()); - tableIndex.setTableName(column.getTableName()); - tableIndex.setSchemaName(column.getSchemaName()); - tableIndex.setDatabaseName(column.getDatabaseName()); - tableIndex.setUnique(!column.getNonUnique()); - tableIndex.setColumnList(entry.getValue()); - tableIndices.add(tableIndex); - }); + Collectors.groupingBy(TableIndexColumn::getIndexName)).entrySet() + .stream().forEach(entry -> { + TableIndex tableIndex = new TableIndex(); + TableIndexColumn column = entry.getValue().get(0); + tableIndex.setName(entry.getKey()); + tableIndex.setTableName(column.getTableName()); + tableIndex.setSchemaName(column.getSchemaName()); + tableIndex.setDatabaseName(column.getDatabaseName()); + tableIndex.setUnique(!column.getNonUnique()); + tableIndex.setColumnList(entry.getValue()); + tableIndices.add(tableIndex); + }); } catch (SQLException e) { throw new RuntimeException(e); } return tableIndices; } - /** * Get all functions available in a catalog. * - * @param connection connection + * @param connection connection * @param databaseName databaseName of the function - * @param schemaName schemaName of the function + * @param schemaName schemaName of the function * @return List */ public List functions(Connection connection, String databaseName, - String schemaName) { + String schemaName) { try (ResultSet resultSet = connection.getMetaData().getFunctions(databaseName, schemaName, null);) { return ResultSetUtils.toObjectList(resultSet, ai.chat2db.spi.model.Function.class); } catch (Exception e) { @@ -362,11 +378,11 @@ public class SQLExecutor { } /** - * procedure list + * procedure list * - * @param connection connection + * @param connection connection * @param databaseName databaseName - * @param schemaName schemaName + * @param schemaName schemaName * @return List */ public List procedures(Connection connection, String databaseName, String schemaName) { From 90b5e6e6c3088542017af3e7f3b357a515468c00 Mon Sep 17 00:00:00 2001 From: JiaJu Zhuang <5152853@qq.com> Date: Sun, 3 Sep 2023 18:47:38 +0800 Subject: [PATCH 10/16] Modifying Oracle Query Blob Error --- .../java/ai/chat2db/spi/util/JdbcUtils.java | 50 +++++++++++++++---- 1 file changed, 39 insertions(+), 11 deletions(-) diff --git a/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/util/JdbcUtils.java b/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/util/JdbcUtils.java index e0b49966..368e038c 100644 --- a/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/util/JdbcUtils.java +++ b/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/util/JdbcUtils.java @@ -1,6 +1,7 @@ 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; @@ -144,24 +145,51 @@ public class JdbcUtils { if (obj == null) { return null; } - 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); + 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(); } - return rs.getString(index); + } + + 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; From 47a3f795ac20da0aef3d13ec66ff48c74d109fff Mon Sep 17 00:00:00 2001 From: JiaJu Zhuang <5152853@qq.com> Date: Sun, 3 Sep 2023 18:51:03 +0800 Subject: [PATCH 11/16] changelog --- CHANGELOG.md | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 74be1c2a..54f54053 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,15 +1,28 @@ +# 2.0.14 + +## 🐞 Bug Fixes + +- Fix the issue of 'Oracle' query 'Blob' reporting errors +- Modify the paging logic and fix some SQL queries that cannot be queried + +## 🐞 问题修复 + +- 修复 `Oracle` 查询 `Blob` 报错的问题 +- 修改分页逻辑,修复部分SQL无法查询 + # 2.0.12 ## ⭐ New Features -- 🔥Supports viewing views, functions, triggers, and procedures -- Support selected sql formatting +- 🔥Supports viewing views, functions, triggers, and procedures +- Support selected sql formatting - Added new dark themes ## 🐞 Bug Fixes - Fixed sql formatting failure issue -- Fixed an issue where locally stored theme colors and background colors are incompatible with the new version, causing page crashes +- Fixed an issue where locally stored theme colors and background colors are incompatible with the new version, causing + page crashes - Logs desensitize sensitive data - Fix the issue of 'CLOB' not displaying specific content [Issue #440](https://github.com/chat2db/Chat2DB/issues/440) - Fix the problem that non-Select does not display query results @@ -17,9 +30,6 @@ - Fix the problem of special type of SQL execution error reporting - Fix the problem that the test link is successful, but the error is reported when saving the link - - - ## ⭐ 新特性 - 🔥支持查看视图、函数、触发器、存储过程 From 33cd368db8ca4d82f0c185b05c147b2a81f2a154 Mon Sep 17 00:00:00 2001 From: robin <850379744@qq.com> Date: Tue, 5 Sep 2023 12:47:07 +0800 Subject: [PATCH 12/16] set larger timeout --- .../ai/chat2db/server/web/api/controller/ai/ChatController.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ai/ChatController.java b/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ai/ChatController.java index 634ac703..89ceb821 100644 --- a/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ai/ChatController.java +++ b/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ai/ChatController.java @@ -89,7 +89,7 @@ public class ChatController { /** * chat的超时时间 */ - private static final Long CHAT_TIMEOUT = Duration.ofMinutes(10).toMillis(); + private static final Long CHAT_TIMEOUT = Duration.ofMinutes(50).toMillis(); /** * 提示语最大token数 From 1af4d3f020035601cfd5d6361e8deee3e66f01b1 Mon Sep 17 00:00:00 2001 From: SwallowGG <1558143046@qq.com> Date: Wed, 6 Sep 2023 16:37:11 +0800 Subject: [PATCH 13/16] fix dm function bug --- .../plugin/sqlserver/SqlServerMetaData.java | 38 +++++++++++++++++-- .../ai/chat2db/spi/sql/IDriverManager.java | 7 +++- 2 files changed, 39 insertions(+), 6 deletions(-) diff --git a/chat2db-server/chat2db-plugins/chat2db-sqlserver/src/main/java/ai/chat2db/plugin/sqlserver/SqlServerMetaData.java b/chat2db-server/chat2db-plugins/chat2db-sqlserver/src/main/java/ai/chat2db/plugin/sqlserver/SqlServerMetaData.java index 35af5786..d83b3135 100644 --- a/chat2db-server/chat2db-plugins/chat2db-sqlserver/src/main/java/ai/chat2db/plugin/sqlserver/SqlServerMetaData.java +++ b/chat2db-server/chat2db-plugins/chat2db-sqlserver/src/main/java/ai/chat2db/plugin/sqlserver/SqlServerMetaData.java @@ -68,6 +68,10 @@ public class SqlServerMetaData extends DefaultMetaService implements MetaData { = "SELECT type_desc, OBJECT_NAME(object_id) AS FunctionName, OBJECT_DEFINITION(object_id) AS " + "definition FROM sys.objects WHERE type_desc IN(%s) and name = '%s' ;"; + + private static String OBJECT_SQL + = "SELECT name FROM sys.objects WHERE type = '%s' and SCHEMA_ID = SCHEMA_ID('%s');"; + @Override public Function function(Connection connection, @NotEmpty String databaseName, String schemaName, String functionName) { @@ -87,8 +91,22 @@ public class SqlServerMetaData extends DefaultMetaService implements MetaData { @Override public List functions(Connection connection, String databaseName, String schemaName) { - List functions = SQLExecutor.getInstance().functions(connection, databaseName, schemaName); - return functions.stream().map(function -> removeVersion(function)).collect(Collectors.toList()); + List functions = new ArrayList<>(); +// List functions = SQLExecutor.getInstance().functions(connection, databaseName, schemaName); +// return functions.stream().map(function -> removeVersion(function)).collect(Collectors.toList()); + String sql = String.format(OBJECT_SQL,"FN", schemaName); + return SQLExecutor.getInstance().execute(connection, sql, resultSet -> { + while (resultSet.next()) { + Function function = new Function(); + function.setDatabaseName(databaseName); + function.setSchemaName(schemaName); + if (resultSet.next()) { + function.setFunctionName(resultSet.getString("name")); + } + functions.add(function); + } + return functions; + }); } private Function removeVersion(Function function) { @@ -103,8 +121,20 @@ public class SqlServerMetaData extends DefaultMetaService implements MetaData { @Override public List procedures(Connection connection, String databaseName, String schemaName) { - List procedures = SQLExecutor.getInstance().procedures(connection, databaseName, schemaName); - return procedures.stream().map(procedure -> removeVersion(procedure)).collect(Collectors.toList()); + List procedures = new ArrayList<>(); + String sql = String.format(OBJECT_SQL,"P", schemaName); + return SQLExecutor.getInstance().execute(connection, sql, resultSet -> { + while (resultSet.next()) { + Procedure procedure = new Procedure(); + procedure.setDatabaseName(databaseName); + procedure.setSchemaName(schemaName); + if (resultSet.next()) { + procedure.setProcedureName(resultSet.getString("name")); + } + procedures.add(procedure); + } + return procedures; + }); } private Procedure removeVersion(Procedure procedure) { diff --git a/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/sql/IDriverManager.java b/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/sql/IDriverManager.java index 83ae4e2b..78f65c3f 100644 --- a/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/sql/IDriverManager.java +++ b/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/sql/IDriverManager.java @@ -78,13 +78,16 @@ public class IDriverManager { if (url == null) { throw new SQLException("The url cannot be null", "08001"); } - SQLException reason = null; DriverEntry driverEntry = DRIVER_ENTRY_MAP.get(driver.getJdbcDriver()); if (driverEntry == null) { driverEntry = getJDBCDriver(driver); } try { - return driverEntry.getDriver().connect(url, info); + Connection connection = driverEntry.getDriver().connect(url, info); + if(connection == null){ + throw new ConnectionException("driverEntry.getDriver().connect return null",null); + } + return connection; } catch (SQLException var7) { Connection con = tryConnectionAgain(driverEntry, url, info); if (con != null) { From a0fdfc582276fb289e656357f2f8ae9ae2b4deb6 Mon Sep 17 00:00:00 2001 From: SwallowGG <1558143046@qq.com> Date: Wed, 6 Sep 2023 17:10:31 +0800 Subject: [PATCH 14/16] fix dm function bug --- .../src/main/java/ai/chat2db/spi/sql/IDriverManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/sql/IDriverManager.java b/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/sql/IDriverManager.java index 78f65c3f..d841646a 100644 --- a/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/sql/IDriverManager.java +++ b/chat2db-server/chat2db-spi/src/main/java/ai/chat2db/spi/sql/IDriverManager.java @@ -85,7 +85,7 @@ public class IDriverManager { try { Connection connection = driverEntry.getDriver().connect(url, info); if(connection == null){ - throw new ConnectionException("driverEntry.getDriver().connect return null",null); + throw new SQLException("driver.connect return null , No suitable driver found for url " +url ,"08001"); } return connection; } catch (SQLException var7) { From 8341465f7f3d6a0dff1181ae7964cd66e6928798 Mon Sep 17 00:00:00 2001 From: JiaJu Zhuang <5152853@qq.com> Date: Sun, 3 Sep 2023 17:41:14 +0800 Subject: [PATCH 15/16] Add Publishing Branch --- .github/workflows/release_test.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.github/workflows/release_test.yml b/.github/workflows/release_test.yml index d71beff8..14867d07 100644 --- a/.github/workflows/release_test.yml +++ b/.github/workflows/release_test.yml @@ -7,6 +7,8 @@ on: push: branches: - "release_test" + - "release_test_2" + - "release_test_3" # Workflow's jobs # 一共需要3台电脑运行 From 1587792affc102c7bc620769ba089ec9a1a6fcfc Mon Sep 17 00:00:00 2001 From: robin <850379744@qq.com> Date: Wed, 6 Sep 2023 20:09:39 +0800 Subject: [PATCH 16/16] rest ai fix --- .../api/controller/ai/listener/RestAIEventSourceListener.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ai/listener/RestAIEventSourceListener.java b/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ai/listener/RestAIEventSourceListener.java index 8f6aa47d..657c458f 100644 --- a/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ai/listener/RestAIEventSourceListener.java +++ b/chat2db-server/chat2db-server-web/chat2db-server-web-api/src/main/java/ai/chat2db/server/web/api/controller/ai/listener/RestAIEventSourceListener.java @@ -54,7 +54,7 @@ public class RestAIEventSourceListener extends EventSourceListener { } Message message = new Message(); if (StringUtils.isNotBlank(data)) { - message.setContent(data); + message.setContent(data.replace("\"", "")); sseEmitter.send(SseEmitter.event() .id(id) .data(message)