diff --git a/CHANGELOG.md b/CHANGELOG.md index 4474466a10..d0e0810166 100755 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -2,7 +2,7 @@ # 🚀Changelog ------------------------------------------------------------------------------------------------------------- -# 5.8.41(2025-09-08) +# 5.8.41(2025-09-11) ### 🐣新特性 * 【core 】 增加`WeakKeyValueConcurrentMap`及其关联类,同时废弃`WeakConcurrentMap`并替换(issue#4039@Github) @@ -22,6 +22,7 @@ * 【core 】 修复`IoUtil`的`closeIfPosible`拼写错误,新建一个`closeIfPossible`方法,原方法标记deprecated(issue#4047@Github) * 【http 】 修复`HttpRequest.sendRedirectIfPossible`未对308做判断问题。(issue#4053@Github) * 【cron 】 修复`CronPatternUtil.nextDateAfter`当日为L时计算错误问题。(issue#4056@Github) +* 【cron 】 修复`DialectRunner.count`方法中,去除包含多字段order by子句的SQL语句时错误问题(issue#4066@Github) ------------------------------------------------------------------------------------------------------------- # 5.8.40(2025-08-26) diff --git a/hutool-db/src/main/java/cn/hutool/db/DialectRunner.java b/hutool-db/src/main/java/cn/hutool/db/DialectRunner.java index ea9dfd9523..e36d69a62a 100644 --- a/hutool-db/src/main/java/cn/hutool/db/DialectRunner.java +++ b/hutool-db/src/main/java/cn/hutool/db/DialectRunner.java @@ -1,7 +1,6 @@ package cn.hutool.db; import cn.hutool.core.lang.Assert; -import cn.hutool.core.lang.PatternPool; import cn.hutool.core.map.MapUtil; import cn.hutool.core.util.ArrayUtil; import cn.hutool.core.util.StrUtil; @@ -9,18 +8,12 @@ import cn.hutool.db.dialect.Dialect; import cn.hutool.db.dialect.DialectFactory; import cn.hutool.db.handler.NumberHandler; import cn.hutool.db.handler.RsHandler; -import cn.hutool.db.sql.Query; -import cn.hutool.db.sql.SqlBuilder; -import cn.hutool.db.sql.SqlExecutor; -import cn.hutool.db.sql.SqlUtil; -import cn.hutool.db.sql.Wrapper; +import cn.hutool.db.sql.*; import java.io.Serializable; import java.sql.Connection; import java.sql.PreparedStatement; import java.sql.SQLException; -import java.util.regex.Matcher; -import java.util.regex.Pattern; /** * 提供基于方言的原始增删改查执行封装 @@ -275,14 +268,8 @@ public class DialectRunner implements Serializable { public long count(Connection conn, SqlBuilder sqlBuilder) throws SQLException { checkConn(conn); - String selectSql = sqlBuilder.build(); - // 去除order by 子句 - final Pattern pattern = PatternPool.get("(.*?)[\\s]order[\\s]by[\\s][^\\s]+\\s(asc|desc)?", Pattern.CASE_INSENSITIVE); - final Matcher matcher = pattern.matcher(selectSql); - if (matcher.matches()) { - selectSql = matcher.group(1); - } + final String selectSql = SqlUtil.removeOuterOrderBy(sqlBuilder.build()); return SqlExecutor.queryAndClosePs(dialect.psForCount(conn, SqlBuilder.of(selectSql).addParams(sqlBuilder.getParamValueArray())), diff --git a/hutool-db/src/main/java/cn/hutool/db/sql/SqlUtil.java b/hutool-db/src/main/java/cn/hutool/db/sql/SqlUtil.java index 7bd02948b6..ba35e4e992 100644 --- a/hutool-db/src/main/java/cn/hutool/db/sql/SqlUtil.java +++ b/hutool-db/src/main/java/cn/hutool/db/sql/SqlUtil.java @@ -1,7 +1,9 @@ package cn.hutool.db.sql; import cn.hutool.core.io.IoUtil; +import cn.hutool.core.lang.PatternPool; import cn.hutool.core.util.CharsetUtil; +import cn.hutool.core.util.ReUtil; import cn.hutool.core.util.StrUtil; import cn.hutool.db.DbRuntimeException; import cn.hutool.db.Entity; @@ -11,13 +13,10 @@ import java.io.InputStream; import java.io.OutputStream; import java.io.Reader; import java.nio.charset.Charset; -import java.sql.Blob; -import java.sql.Clob; -import java.sql.Connection; -import java.sql.RowId; -import java.sql.SQLException; +import java.sql.*; import java.util.List; import java.util.Map.Entry; +import java.util.regex.Pattern; /** * SQL相关工具类,包括相关SQL语句拼接等 @@ -27,6 +26,11 @@ import java.util.Map.Entry; */ public class SqlUtil { + /** + * 创建SQL中的order by语句的正则 + */ + private static final Pattern PATTERN_ORDER_BY = PatternPool.get("(.*)\\s+order\\s+by\\s+[^\\s]+", Pattern.CASE_INSENSITIVE); + /** * 构件相等条件的where语句
* 如果没有条件语句,泽返回空串,表示没有条件 @@ -252,4 +256,16 @@ public class SqlUtil { public static java.sql.Timestamp toSqlTimestamp(java.util.Date date) { return new java.sql.Timestamp(date.getTime()); } + + /** + * 移除 SQL中的 ORDER BY 子句 + * + * @param selectSql 原始 SQL + * @return 移除 ORDER BY 子句后的 SQL + * @since 5.8.41 + */ + public static String removeOuterOrderBy(final String selectSql) { + // 去除order by 子句 + return ReUtil.getGroup1(PATTERN_ORDER_BY, selectSql); + } } diff --git a/hutool-db/src/test/java/cn/hutool/db/sql/Issue4066Test.java b/hutool-db/src/test/java/cn/hutool/db/sql/Issue4066Test.java new file mode 100644 index 0000000000..54587fb128 --- /dev/null +++ b/hutool-db/src/test/java/cn/hutool/db/sql/Issue4066Test.java @@ -0,0 +1,31 @@ +package cn.hutool.db.sql; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +public class Issue4066Test { + /** + * 基础测试:简单的 ORDER BY 语句 + */ + @Test + public void removeOuterOrderByTest1() { + // 测试基本的ORDER BY移除 + final String sql = "SELECT * FROM users ORDER BY name"; + final String result = SqlUtil.removeOuterOrderBy(sql); + + assertEquals("SELECT * FROM users", result); + } + + /** + * 多字段 ORDER BY 测试:包含多个排序字段的复杂 ORDER BY语句 + */ + @Test + public void removeOuterOrderByTest2() { + // 测试多字段ORDER BY移除 + final String sql = "SELECT id, name, age FROM users WHERE status = 'active' ORDER BY name ASC, age DESC, created_date"; + final String result = SqlUtil.removeOuterOrderBy(sql); + + assertEquals("SELECT id, name, age FROM users WHERE status = 'active'", result); + } +}