Mybatis-PageHelper icon indicating copy to clipboard operation
Mybatis-PageHelper copied to clipboard

无法解析中括号的问题

Open yechtop opened this issue 4 years ago • 5 comments

  • [x] 我已在 issues 搜索类似问题,并且不存在相同的问题.

异常模板

使用环境

  • PageHelper 版本:pagehelper-spring-boot-starter:1.3.0
  • 数据库类型和版本: Microsoft SQL Server 2014 (SP2) (KB3171021) - 12.0.5000.0 (X64)
  • JDBC_URL: jdbc:jtds:sqlserver:///;useLOBs=false

SQL 解析错误

分页参数

page = PageHelper.startPage(pageNo, pageSize, count);

原 SQL

SELECT [ID] AS [ComsnCountID] FROM B_ComsnCount ;

期望的结果:

能解析成功

完整异常信息


### Error querying database.  Cause: java.sql.SQLException: 除非另外还指定了 TOP、OFFSET 或 FOR XML,否则,ORDER BY 子句在视图、内联函数、派生表、子查询和公用表表达式中无效。
### The error may exist in file [C:\IJProject\marketing\dao\target\classes\mapper\SellCommissionMapper.xml]
### The error may involve com.xkw.marketing.dao.mapper.SellCommissionMapper.queryCommissionCountList-Inline
### The error occurred while setting parameters
### Cause: java.sql.SQLException: 除非另外还指定了 TOP、OFFSET 或 FOR XML,否则,ORDER BY 子句在视图、内联函数、派生表、子查询和公用表表达式中无效。
; 除非另外还指定了 TOP、OFFSET 或 FOR XML,否则,ORDER BY 子句在视图、内联函数、派生表、子查询和公用表表达式中无效。; nested exception is java.sql.SQLException: 除非另外还指定了 TOP、OFFSET 或 FOR XML,否则,ORDER BY 子句在视图、内联函数、派生表、子查询和公用表表达式中无效。]

其他类型的错误

我看了源码,是在CountSqlParser的第180行,无法正常解析中括号,所以使用默认的getSimpleCountSql方法,但这个方法只是单纯的加一个count(0),没有去除 order by。

        try {
            stmt = CCJSqlParserUtil.parse(sql);
        } catch (Throwable e) {
            //无法解析的用一般方法返回count语句
            return getSimpleCountSql(sql, name);
        }

但我使用这个SQL就能正常输出 SELECT ID AS ComsnCountID FROM B_ComsnCount ; 所以我觉得是因为新版本无法正常解析中括号导致的,我使用1.2.12版本就能正常解析

功能建议

建议优化 getSimpleCountSql 方法,或者排查CCJSqlParserUtil.parse(sql)中不能正常解析中括号的原因

yechtop avatar Nov 13 '20 08:11 yechtop

1. 功能修改建议

com.github.pagehelper.parser.SqlServerParser

/**
 * 转换为分页语句
 *
 * @param sql
 * @param offset
 * @param limit
 * @return
 */
public String convertToPageSql(String sql, Integer offset, Integer limit) {
    //解析SQL
    Statement stmt;
    try {
        stmt = CCJSqlParserUtil.parse(sql);
    } catch (Throwable e) {
        throw new PageException("不支持该SQL转换为分页查询!", e);
    }
    if (!(stmt instanceof Select)) {
        throw new PageException("分页语句必须是Select查询!");
    }
    //获取分页查询的select
    Select pageSelect = getPageSelect((Select) stmt);
    String pageSql = pageSelect.toString();
    //缓存移到外面了,所以不替换参数
    if (offset != null) {
        pageSql = pageSql.replace(START_ROW, String.valueOf(offset));
    }
    if (limit != null) {
        pageSql = pageSql.replace(PAGE_SIZE, String.valueOf(limit));
    }
    return pageSql;
}

订正方法:

    /**
     * Parses an sql statement while allowing via consumer to configure the used parser before.
     * 
     * For instance to activate SQLServer bracket quotation on could use:
     * 
     * {@code 
     * CCJSqlParserUtil.parse("select * from [mytable]", parser -> parser.withSquareBracketQuotation(true));
     * }
     * 
     * @param sql
     * @param consumer
     * @return
     * @throws JSQLParserException 
     */
    public static Statement parse(String sql, Consumer<CCJSqlParser> consumer) throws JSQLParserException {
        CCJSqlParser parser = new CCJSqlParser(new StringProvider(sql));
        if (consumer != null) {
            consumer.accept(parser);
        }
        try {
            return parser.Statement();
        } catch (Exception ex) {
            throw new JSQLParserException(ex);
        }
    }

matebase avatar Nov 23 '20 02:11 matebase

@pagehelper 应该是升级 jsqlparser 导致的: https://stackoverflow.com/questions/59135053/how-to-handle-characters-on-jsqlparser

iTanken avatar Dec 30 '20 03:12 iTanken

等后续大版本升级jdk8时会解决上面的问题。

abel533 avatar Jun 06 '21 13:06 abel533

计划什么时候升级了, 项目还能赶得上吗 ?

majinding avatar Jun 29 '21 03:06 majinding

这样就可以了 Select select = (Select) CCJSqlParserUtil.parse(sql,parser->parser.withSquareBracketQuotation(true));

gstsgy avatar Jul 01 '22 07:07 gstsgy

sqlParser:配置 JSqlParser 解析器,注意是 com.github.pagehelper.JSqlParser 接口,用于支持 sqlserver 等需要额外配置的情况。

abel533 avatar Sep 18 '22 12:09 abel533