先说一下现象,此处我使用是国产达梦6数据库,该处SQL在数据库客户端中
能正常执行
,且该错误对系统运行,目前没发现有何异常,但,看着该接口每次被调用后,都打出一堆Exception,也是很不爽的事。
此处报错日志异常如下(仅供参考):
11:11:47.031 [main] DEBUG c.r.p.t.s.m.S.searchSql - [debug,143] - ==> Preparing: SELECT TOP 3 * FROM XXXXXX WHERE XXXX ORDER BY XXX ASC
11:11:47.078 [main] ERROR c.a.d.f.s.StatFilter - [mergeSql,149] - merge sql error, dbType null, druid-1.1.14, sql : SELECT TOP 3 * FROM XXXX WHERE XXX ORDER BY XXX ASC
com.alibaba.druid.sql.parser.ParserException: syntax error, error in :' TOP 3 * FROM XXX', expect LITERAL_INT, actual LITERAL_INT pos 12, line 1, column 12, token LITERAL_INT
at com.alibaba.druid.sql.parser.SQLParser.printError(SQLParser.java:287)
at com.alibaba.druid.sql.parser.SQLStatementParser.parseStatementList(SQLStatementParser.java:532)
at com.alibaba.druid.sql.parser.SQLStatementParser.parseStatementList(SQLStatementParser.java:171)
at com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils.parameterize(ParameterizedOutputVisitorUtils.java:98)
at com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils.parameterize(ParameterizedOutputVisitorUtils.java:81)
at com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils.parameterize(ParameterizedOutputVisitorUtils.java:54)
at com.alibaba.druid.filter.stat.StatFilter.mergeSql(StatFilter.java:147)
at com.alibaba.druid.filter.stat.StatFilter.createSqlStat(StatFilter.java:648)
at com.alibaba.druid.filter.stat.StatFilter.statementPrepareAfter(StatFilter.java:311)
at com.alibaba.druid.filter.FilterEventAdapter.connection_prepareStatement(FilterEventAdapter.java:124)
at com.alibaba.druid.filter.FilterChainImpl.connection_prepareStatement(FilterChainImpl.java:568)
at com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl.prepareStatement(ConnectionProxyImpl.java:341)
at com.alibaba.druid.pool.DruidPooledConnection.prepareStatement(DruidPooledConnection.java:348)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.apache.ibatis.logging.jdbc.ConnectionLogger.invoke(ConnectionLogger.java:55)
经常使用druid,还是觉得挺好用的,但是源代码没仔细跟过,乘着此次异常,研究了研究。
于是在
com.alibaba.druid.sql.parser.Token
中发现了TOP
作为了关键字
package com.alibaba.druid.sql.parser;
public enum Token
{
SELECT("SELECT"), DELETE("DELETE"), INSERT("INSERT"), UPDATE("UPDATE"), FROM("FROM"), HAVING("HAVING"), WHERE("WHERE"), ORDER("ORDER"), BY("BY"), GROUP("GROUP"), INTO("INTO"), AS("AS"), CREATE("CREATE"), ALTER("ALTER"), DROP("DROP"), SET("SET"), NULL("NULL"), NOT("NOT"), DISTINCT("DISTINCT"), TABLE("TABLE"), TABLESPACE("TABLESPACE"), VIEW("VIEW"), SEQUENCE("SEQUENCE"), TRIGGER("TRIGGER"), USER("USER"), INDEX("INDEX"), SESSION("SESSION"), PROCEDURE("PROCEDURE"), FUNCTION("FUNCTION"), PRIMARY("PRIMARY"), KEY("KEY"), DEFAULT("DEFAULT"), CONSTRAINT("CONSTRAINT"), CHECK("CHECK"), UNIQUE("UNIQUE"), FOREIGN("FOREIGN"), REFERENCES("REFERENCES"), EXPLAIN("EXPLAIN"), FOR("FOR"), IF("IF"), SORT("SORT"), ALL("ALL"), UNION("UNION"), EXCEPT("EXCEPT"), INTERSECT("INTERSECT"), MINUS("MINUS"), INNER("INNER"), LEFT("LEFT"), RIGHT("RIGHT"), FULL("FULL"), OUTER("OUTER"), JOIN("JOIN"), ON("ON"), SCHEMA("SCHEMA"), CAST("CAST"), COLUMN("COLUMN"), USE("USE"), DATABASE("DATABASE"), TO("TO"), AND("AND"), OR("OR"), XOR("XOR"), CASE("CASE"), WHEN("WHEN"), THEN("THEN"), ELSE("ELSE"), ELSIF("ELSIF"), END("END"), EXISTS("EXISTS"), IN("IN"), CONTAINS("CONTAINS"), RLIKE("RLIKE"), FULLTEXT("FULLTEXT"), NEW("NEW"), ASC("ASC"), DESC("DESC"), IS("IS"), LIKE("LIKE"), ESCAPE("ESCAPE"), BETWEEN("BETWEEN"), VALUES("VALUES"), INTERVAL("INTERVAL"), LOCK("LOCK"), SOME("SOME"), ANY("ANY"), TRUNCATE("TRUNCATE"), RETURN("RETURN"), TRUE("TRUE"), FALSE("FALSE"), LIMIT("LIMIT"), KILL("KILL"), IDENTIFIED("IDENTIFIED"), PASSWORD("PASSWORD"), ALGORITHM("ALGORITHM"), DUAL("DUAL"), BINARY("BINARY"), SHOW("SHOW"), REPLACE("REPLACE"), BITS, WHILE("WHILE"), DO("DO"), LEAVE("LEAVE"), ITERATE("ITERATE"), REPEAT("REPEAT"), UNTIL("UNTIL"), OPEN("OPEN"), CLOSE("CLOSE"), OUT("OUT"), INOUT("INOUT"), EXIT("EXIT"), UNDO("UNDO"), SQLSTATE("SQLSTATE"), CONDITION("CONDITION"), DIV("DIV"), WINDOW("WINDOW"), OFFSET("OFFSET"), ROW("ROW"), ROWS("ROWS"), ONLY("ONLY"), FIRST("FIRST"), NEXT("NEXT"), FETCH("FETCH"), OF("OF"), SHARE("SHARE"), NOWAIT("NOWAIT"), RECURSIVE("RECURSIVE"), TEMPORARY("TEMPORARY"), TEMP("TEMP"), UNLOGGED("UNLOGGED"), RESTART("RESTART"), IDENTITY("IDENTITY"), CONTINUE("CONTINUE"), CASCADE("CASCADE"), RESTRICT("RESTRICT"), USING("USING"), CURRENT("CURRENT"), RETURNING("RETURNING"), COMMENT("COMMENT"), OVER("OVER"), TYPE("TYPE"), ILIKE("ILIKE"), START("START"), PRIOR("PRIOR"), CONNECT("CONNECT"), WITH("WITH"), EXTRACT("EXTRACT"), CURSOR("CURSOR"), MODEL("MODEL"), MERGE("MERGE"), MATCHED("MATCHED"), ERRORS("ERRORS"), REJECT("REJECT"), UNLIMITED("UNLIMITED"), BEGIN("BEGIN"), EXCLUSIVE("EXCLUSIVE"), MODE("MODE"), WAIT("WAIT"), ADVISE("ADVISE"), SYSDATE("SYSDATE"), DECLARE("DECLARE"), EXCEPTION("EXCEPTION"), GRANT("GRANT"), REVOKE("REVOKE"), LOOP("LOOP"), GOTO("GOTO"), COMMIT("COMMIT"), SAVEPOINT("SAVEPOINT"), CROSS("CROSS"), PCTFREE("PCTFREE"), INITRANS("INITRANS"), MAXTRANS("MAXTRANS"), INITIALLY("INITIALLY"), ENABLE("ENABLE"), DISABLE("DISABLE"), SEGMENT("SEGMENT"), CREATION("CREATION"), IMMEDIATE("IMMEDIATE"), DEFERRED("DEFERRED"), STORAGE("STORAGE"), MINEXTENTS("MINEXTENTS"), MAXEXTENTS("MAXEXTENTS"), MAXSIZE("MAXSIZE"), PCTINCREASE("PCTINCREASE"), FLASH_CACHE("FLASH_CACHE"), CELL_FLASH_CACHE("CELL_FLASH_CACHE"), NONE("NONE"), LOB("LOB"), STORE("STORE"), CHUNK("CHUNK"), CACHE("CACHE"), NOCACHE("NOCACHE"), LOGGING("LOGGING"), NOCOMPRESS("NOCOMPRESS"), KEEP_DUPLICATES("KEEP_DUPLICATES"), EXCEPTIONS("EXCEPTIONS"), PURGE("PURGE"), COMPUTE("COMPUTE"), ANALYZE("ANALYZE"), OPTIMIZE("OPTIMIZE"), TOP("TOP"), ARRAY("ARRAY"), DISTRIBUTE("DISTRIBUTE"), EOF, ERROR, IDENTIFIER, HINT, VARIANT, LITERAL_INT, LITERAL_FLOAT, LITERAL_HEX, LITERAL_CHARS, LITERAL_NCHARS, LITERAL_ALIAS, LINE_COMMENT, MULTI_LINE_COMMENT, BINARY_FLOAT, BINARY_DOUBLE, PARTITION, PARTITIONED, OVERWRITE, SEL("SEL"), LOCKING("LOCKING"), ACCESS("ACCESS"), VOLATILE("VOLATILE"), MULTISET("MULTISET"), POSITION("POSITION"), RANGE_N("RANGE_N"), FORMAT("FORMAT"), QUALIFY("QUALIFY"), MOD("MOD"), CONCAT("CONCAT"), UPSERT("UPSERT"), LPAREN("("), RPAREN(")"), LBRACE("{"), RBRACE("}"), LBRACKET("["), RBRACKET("]"), SEMI(";"), COMMA(","), DOT("."), DOTDOT(".."), DOTDOTDOT("..,"), EQ("="), GT(">"), LT("<"), LT_SUB_GT("<->"), BANG("!"), BANGBANG("!!"), BANG_TILDE("!~"), BANG_TILDE_STAR("!~*"), TILDE("~"), TILDE_STAR("~*"), TILDE_EQ("~="), QUES("?"), QUESQUES("??"), QUESBAR("?|"), QUESAMP("?&"), COLON(":"), COLONCOLON("::"), COLONEQ(":="), EQEQ("=="), EQGT("=>"), LTEQ("<="), LTEQGT("<=>"), LTGT("<>"), GTEQ(">="), BANGEQ("!="), BANGGT("!>"), BANGLT("!<"), AMPAMP("&&"), BARBAR("||"), BARBARSLASH("||/"), BARSLASH("|/"), PLUS("+"), SUB("-"), SUBGT("->"), SUBGTGT("->>"), STAR("*"), SLASH("/"), AMP("&"), BAR("|"), CARET("^"), CARETEQ("^="), PERCENT("%"), LTLT("<<"), GTGT(">>"), MONKEYS_AT("@"), MONKEYS_AT_AT("@@"), POUND("#"), POUNDGT("#>"), POUNDGTGT("#>>"), MONKEYS_AT_GT("@>"), LT_MONKEYS_AT("<@");
public final String name;
private Token()
{
this(null);
}
private Token(String name)
{
this.name = name;
}
}
而在方言处理中并没有关于达梦数据库的写法:
这就不难解释了,估计是druid
自己也不知道怎么处理,然后就直接放行了,然后又怕会有不可预料的结果,于是也抛出了该异常!!
当然,如果是常规保留字冲突,在mapper中文件或者SQL 引起来就能解决(达梦是""、MySql是使用 ``)
。
可是此处却是使用TOP
功能,使用引号视乎解决不了问题,还好我的诉求是取前3条数据,于是我试下使用另一个关键字 LIMIT
,然后问题解决了
源SQL : SELECT TOP 3 * FROM XXXXXX WHERE XXXX ORDER BY XXX ASC
改成 : SELECT * FROM XXXXXX WHERE XXXX ORDER BY XXX ASC LIMIT 3