diff --git a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java index 0555512bfc..dab220cbc1 100644 --- a/src/main/java/com/alibaba/druid/pool/DruidDataSource.java +++ b/src/main/java/com/alibaba/druid/pool/DruidDataSource.java @@ -1955,6 +1955,7 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat public void run() { initedLatch.countDown(); + long lastDiscardCount = 0; int errorCount = 0; for (;;) { // addLast @@ -1964,10 +1965,14 @@ public class DruidDataSource extends DruidAbstractDataSource implements DruidDat break; } + long discardCount = DruidDataSource.this.discardCount; + boolean discardChanged = discardCount - lastDiscardCount > 0; + lastDiscardCount = discardCount; + try { boolean emptyWait = true; - if (createError != null && poolingCount == 0) { + if (createError != null && poolingCount == 0 && !discardChanged) { emptyWait = false; } diff --git a/src/main/java/com/alibaba/druid/sql/PagerUtils.java b/src/main/java/com/alibaba/druid/sql/PagerUtils.java index ede6dcf47c..8bb312ecff 100644 --- a/src/main/java/com/alibaba/druid/sql/PagerUtils.java +++ b/src/main/java/com/alibaba/druid/sql/PagerUtils.java @@ -45,7 +45,6 @@ import com.alibaba.druid.sql.ast.SQLLimit; import com.alibaba.druid.sql.dialect.odps.ast.OdpsSelectQueryBlock; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectQueryBlock; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock; -import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.PGLimit; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerTop; import com.alibaba.druid.util.JdbcConstants; @@ -129,7 +128,7 @@ public class PagerUtils { throw new IllegalArgumentException("limit already exists."); } - PGLimit limit = new PGLimit(); + SQLLimit limit = new SQLLimit(); if (offset > 0) { limit.setOffset(new SQLIntegerExpr(offset)); } @@ -487,7 +486,8 @@ public class PagerUtils { } if (query instanceof OdpsSelectQueryBlock) { - SQLExpr rowCountExpr = ((OdpsSelectQueryBlock) query).getLimit(); + SQLLimit limit = ((OdpsSelectQueryBlock) query).getLimit(); + SQLExpr rowCountExpr = limit != null ? limit.getRowCount() : null; if (rowCountExpr instanceof SQLNumericLiteralExpr) { int rowCount = ((SQLNumericLiteralExpr) rowCountExpr).getNumber().intValue(); diff --git a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectQueryBlock.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectQueryBlock.java index a46646f329..67caa9f7bc 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectQueryBlock.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLSelectQueryBlock.java @@ -19,6 +19,7 @@ import java.util.ArrayList; import java.util.List; import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.ast.SQLLimit; import com.alibaba.druid.sql.ast.SQLObjectImpl; import com.alibaba.druid.sql.ast.SQLOrderBy; import com.alibaba.druid.sql.visitor.SQLASTVisitor; @@ -37,8 +38,8 @@ public class SQLSelectQueryBlock extends SQLObjectImpl implements SQLSelectQuery protected boolean forUpdate = false; protected boolean noWait = false; protected SQLExpr waitTime; - protected SQLExpr first; - protected SQLExpr offset; + + protected SQLLimit limit; public SQLSelectQueryBlock(){ @@ -150,27 +151,45 @@ public class SQLSelectQueryBlock extends SQLObjectImpl implements SQLSelectQuery this.waitTime = waitTime; } + public SQLLimit getLimit() { + return limit; + } + + public void setLimit(SQLLimit limit) { + if (limit != null) { + limit.setParent(this); + } + this.limit = limit; + } public SQLExpr getFirst() { - return first; + if (limit == null) { + return null; + } + + return limit.getRowCount(); } public void setFirst(SQLExpr first) { - if (first != null) { - first.setParent(this); + if (limit == null) { + limit = new SQLLimit(); } - this.first = first; + this.limit.setRowCount(first); } public SQLExpr getOffset() { - return offset; + if (limit == null) { + return null; + } + + return limit.getOffset(); } public void setOffset(SQLExpr offset) { - if (offset != null) { - offset.setParent(this); + if (limit == null) { + limit = new SQLLimit(); } - this.offset = offset; + this.limit.setOffset(offset); } @Override diff --git a/src/main/java/com/alibaba/druid/sql/builder/impl/SQLSelectBuilderImpl.java b/src/main/java/com/alibaba/druid/sql/builder/impl/SQLSelectBuilderImpl.java index 73d7ca3433..19d389d580 100644 --- a/src/main/java/com/alibaba/druid/sql/builder/impl/SQLSelectBuilderImpl.java +++ b/src/main/java/com/alibaba/druid/sql/builder/impl/SQLSelectBuilderImpl.java @@ -40,7 +40,6 @@ import com.alibaba.druid.sql.dialect.odps.ast.OdpsSelectQueryBlock; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelect; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectQueryBlock; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock; -import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.PGLimit; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelect; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerTop; @@ -256,7 +255,7 @@ public class SQLSelectBuilderImpl implements SQLSelectBuilder { if (queryBlock instanceof PGSelectQueryBlock) { PGSelectQueryBlock pgQueryBlock = (PGSelectQueryBlock) queryBlock; - PGLimit limit = new PGLimit(); + SQLLimit limit = new SQLLimit(); if (offset > 0) { limit.setOffset(new SQLIntegerExpr(offset)); } @@ -299,7 +298,7 @@ public class SQLSelectBuilderImpl implements SQLSelectBuilder { throw new UnsupportedOperationException("not support offset"); } - odpsQueryBlock.setLimit(new SQLIntegerExpr(rowCount)); + odpsQueryBlock.setLimit(new SQLLimit(new SQLIntegerExpr(rowCount))); return this; } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/db2/ast/stmt/DB2SelectQueryBlock.java b/src/main/java/com/alibaba/druid/sql/dialect/db2/ast/stmt/DB2SelectQueryBlock.java index 77c0e4fd2a..84aa362fec 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/db2/ast/stmt/DB2SelectQueryBlock.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/db2/ast/stmt/DB2SelectQueryBlock.java @@ -48,7 +48,7 @@ public class DB2SelectQueryBlock extends SQLSelectQueryBlock implements DB2Objec acceptChild(visitor, this.from); acceptChild(visitor, this.where); acceptChild(visitor, this.groupBy); - acceptChild(visitor, this.first); + acceptChild(visitor, this.getFirst()); } visitor.endVisit(this); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/db2/visitor/DB2OutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/db2/visitor/DB2OutputVisitor.java index 1b435b6d99..453fc864f1 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/db2/visitor/DB2OutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/db2/visitor/DB2OutputVisitor.java @@ -23,15 +23,17 @@ import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; import com.alibaba.druid.sql.dialect.db2.ast.stmt.DB2SelectQueryBlock; import com.alibaba.druid.sql.dialect.db2.ast.stmt.DB2ValuesStatement; import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor; +import com.alibaba.druid.util.JdbcConstants; public class DB2OutputVisitor extends SQLASTOutputVisitor implements DB2ASTVisitor { public DB2OutputVisitor(Appendable appender){ - super(appender); + super(appender, JdbcConstants.DB2); } public DB2OutputVisitor(Appendable appender, boolean parameterized){ super(appender, parameterized); + this.dbType = JdbcConstants.DB2; } @Override diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlSelectQueryBlock.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlSelectQueryBlock.java index d52c3af03d..7bbd687d98 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlSelectQueryBlock.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/ast/statement/MySqlSelectQueryBlock.java @@ -35,8 +35,6 @@ public class MySqlSelectQueryBlock extends SQLSelectQueryBlock implements MySqlO private Boolean cache; private boolean calcFoundRows; - private SQLLimit limit; - private SQLName procedureName; private List procedureArgumentList; @@ -150,17 +148,6 @@ public class MySqlSelectQueryBlock extends SQLSelectQueryBlock implements MySqlO this.calcFoundRows = calcFoundRows; } - public SQLLimit getLimit() { - return limit; - } - - public void setLimit(SQLLimit limit) { - if (limit != null) { - limit.setParent(this); - } - this.limit = limit; - } - @Override public int hashCode() { final int prime = 31; diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java index d754bfe64f..cbfcf038ff 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlExprParser.java @@ -728,30 +728,6 @@ public class MySqlExprParser extends SQLExprParser { return super.nameRest(name); } - public SQLLimit parseLimit() { - if (lexer.token() == Token.LIMIT) { - lexer.nextToken(); - - SQLLimit limit = new SQLLimit(); - - SQLExpr temp = this.expr(); - if (lexer.token() == (Token.COMMA)) { - limit.setOffset(temp); - lexer.nextToken(); - limit.setRowCount(this.expr()); - } else if (identifierEquals("OFFSET")) { - limit.setRowCount(temp); - lexer.nextToken(); - limit.setOffset(this.expr()); - } else { - limit.setRowCount(temp); - } - return limit; - } - - return null; - } - @Override public MySqlPrimaryKey parsePrimaryKey() { accept(Token.PRIMARY); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlSelectIntoParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlSelectIntoParser.java index e8050ba2c5..465ffde799 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlSelectIntoParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlSelectIntoParser.java @@ -157,7 +157,7 @@ public class MySqlSelectIntoParser extends SQLSelectParser { queryBlock.setOrderBy(this.exprParser.parseOrderBy()); if (lexer.token() == Token.LIMIT) { - queryBlock.setLimit(parseLimit()); + queryBlock.setLimit(this.exprParser.parseLimit()); } if (lexer.token() == Token.PROCEDURE) { @@ -344,14 +344,10 @@ public class MySqlSelectIntoParser extends SQLSelectParser { public SQLUnionQuery unionRest(SQLUnionQuery union) { if (lexer.token() == Token.LIMIT) { MySqlUnionQuery mysqlUnionQuery = (MySqlUnionQuery) union; - mysqlUnionQuery.setLimit(parseLimit()); + mysqlUnionQuery.setLimit(this.exprParser.parseLimit()); } return super.unionRest(union); } - - public SQLLimit parseLimit() { - return ((MySqlExprParser) this.exprParser).parseLimit(); - } public MySqlExprParser getExprParser() { return (MySqlExprParser) exprParser; diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlSelectParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlSelectParser.java index 2347b3e129..c002413543 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlSelectParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlSelectParser.java @@ -163,7 +163,7 @@ public class MySqlSelectParser extends SQLSelectParser { queryBlock.setOrderBy(this.exprParser.parseOrderBy()); if (lexer.token() == Token.LIMIT) { - queryBlock.setLimit(parseLimit()); + queryBlock.setLimit(this.exprParser.parseLimit()); } if (lexer.token() == Token.PROCEDURE) { @@ -304,7 +304,7 @@ public class MySqlSelectParser extends SQLSelectParser { } update.setOrderBy(this.exprParser.parseOrderBy()); - update.setLimit(parseLimit()); + update.setLimit(this.exprParser.parseLimit()); return update; } @@ -445,15 +445,11 @@ public class MySqlSelectParser extends SQLSelectParser { public SQLUnionQuery unionRest(SQLUnionQuery union) { if (lexer.token() == Token.LIMIT) { MySqlUnionQuery mysqlUnionQuery = (MySqlUnionQuery) union; - mysqlUnionQuery.setLimit(parseLimit()); + mysqlUnionQuery.setLimit(this.exprParser.parseLimit()); } return super.unionRest(union); } - public SQLLimit parseLimit() { - return ((MySqlExprParser) this.exprParser).parseLimit(); - } - public MySqlExprParser getExprParser() { return (MySqlExprParser) exprParser; } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java index d488da462f..353945fcde 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java @@ -324,7 +324,7 @@ public class MySqlStatementParser extends SQLStatementParser { deleteStatement.setOrderBy(orderBy); } - deleteStatement.setLimit(parseLimit()); + deleteStatement.setLimit(this.exprParser.parseLimit()); return deleteStatement; } @@ -865,7 +865,7 @@ public class MySqlStatementParser extends SQLStatementParser { lexer.nextToken(); MySqlShowErrorsStatement stmt = new MySqlShowErrorsStatement(); - stmt.setLimit(parseLimit()); + stmt.setLimit(this.exprParser.parseLimit()); return stmt; } @@ -998,7 +998,7 @@ public class MySqlStatementParser extends SQLStatementParser { stmt.setFrom(this.exprParser.expr()); } - stmt.setLimit(parseLimit()); + stmt.setLimit(this.exprParser.parseLimit()); return stmt; } @@ -1341,7 +1341,7 @@ public class MySqlStatementParser extends SQLStatementParser { stmt.setForQuery(this.exprParser.primary()); } - stmt.setLimit(this.parseLimit()); + stmt.setLimit(this.exprParser.parseLimit()); return stmt; } @@ -1361,7 +1361,7 @@ public class MySqlStatementParser extends SQLStatementParser { stmt.setFrom(this.exprParser.primary()); } - stmt.setLimit(this.parseLimit()); + stmt.setLimit(this.exprParser.parseLimit()); return stmt; } @@ -1381,7 +1381,7 @@ public class MySqlStatementParser extends SQLStatementParser { stmt.setFrom(this.exprParser.primary()); } - stmt.setLimit(this.parseLimit()); + stmt.setLimit(this.exprParser.parseLimit()); return stmt; } @@ -1488,7 +1488,7 @@ public class MySqlStatementParser extends SQLStatementParser { private MySqlShowWarningsStatement parseShowWarnings() { MySqlShowWarningsStatement stmt = new MySqlShowWarningsStatement(); - stmt.setLimit(parseLimit()); + stmt.setLimit(this.exprParser.parseLimit()); return stmt; } @@ -2322,10 +2322,6 @@ public class MySqlStatementParser extends SQLStatementParser { } } - public SQLLimit parseLimit() { - return ((MySqlExprParser) this.exprParser).parseLimit(); - } - public SQLStatement parseAlter() { accept(Token.ALTER); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/odps/ast/OdpsSelectQueryBlock.java b/src/main/java/com/alibaba/druid/sql/dialect/odps/ast/OdpsSelectQueryBlock.java index d7bb59b204..c06c58dfa9 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/odps/ast/OdpsSelectQueryBlock.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/odps/ast/OdpsSelectQueryBlock.java @@ -31,8 +31,6 @@ public class OdpsSelectQueryBlock extends SQLSelectQueryBlock { private SQLOrderBy orderBy; - private SQLExpr limit; - protected List hints; protected List distributeBy = new ArrayList(); @@ -58,17 +56,6 @@ public class OdpsSelectQueryBlock extends SQLSelectQueryBlock { return sortBy; } - public SQLExpr getLimit() { - return limit; - } - - public void setLimit(SQLExpr limit) { - if (limit != null) { - limit.setParent(this); - } - this.limit = limit; - } - @Override public int hashCode() { final int prime = 31; diff --git a/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsSelectParser.java b/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsSelectParser.java index 6386abef9d..2c74cd3578 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsSelectParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsSelectParser.java @@ -16,6 +16,7 @@ package com.alibaba.druid.sql.dialect.odps.parser; import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.ast.SQLLimit; import com.alibaba.druid.sql.ast.SQLOrderingSpecification; import com.alibaba.druid.sql.ast.SQLSetQuantifier; import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr; @@ -117,7 +118,7 @@ public class OdpsSelectParser extends SQLSelectParser { if (lexer.token() == Token.LIMIT) { lexer.nextToken(); - queryBlock.setLimit(this.expr()); + queryBlock.setLimit(new SQLLimit(this.expr())); } return queryRest(queryBlock); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/odps/visitor/OdpsOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/odps/visitor/OdpsOutputVisitor.java index 3b31a2e5b3..e96efc145b 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/odps/visitor/OdpsOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/odps/visitor/OdpsOutputVisitor.java @@ -526,7 +526,6 @@ public class OdpsOutputVisitor extends SQLASTOutputVisitor implements OdpsASTVis if (x.getLimit() != null) { println(); - print0(ucase ? "LIMIT " : "limit "); x.getLimit().accept(this); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGSelectQueryBlock.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGSelectQueryBlock.java index 24833b213a..6294dc9530 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGSelectQueryBlock.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/ast/stmt/PGSelectQueryBlock.java @@ -32,7 +32,6 @@ public class PGSelectQueryBlock extends SQLSelectQueryBlock { private PGWithClause with; private List distinctOn = new ArrayList(2); - private PGLimit limit; private WindowClause window; private SQLOrderBy orderBy; @@ -107,14 +106,6 @@ public class PGSelectQueryBlock extends SQLSelectQueryBlock { this.with = with; } - public PGLimit getLimit() { - return limit; - } - - public void setLimit(PGLimit limit) { - this.limit = limit; - } - public SQLOrderBy getOrderBy() { return orderBy; } @@ -123,21 +114,6 @@ public class PGSelectQueryBlock extends SQLSelectQueryBlock { this.orderBy = orderBy; } - public SQLExpr getOffset() { - if (limit != null) { - return limit.offset; - } - return null; - } - - public void setOffset(SQLExpr offset) { - if (limit == null) { - limit = new PGLimit(); - limit.setParent(this); - } - limit.setOffset(offset); - } - public List getDistinctOn() { return distinctOn; } @@ -255,51 +231,6 @@ public class PGSelectQueryBlock extends SQLSelectQueryBlock { } } - public static class PGLimit extends SQLObjectImpl implements SQLExpr, PGSQLObject { - public PGLimit(){ - - } - - private SQLExpr rowCount; - private SQLExpr offset; - - public SQLExpr getRowCount() { - return rowCount; - } - - public void setRowCount(SQLExpr rowCount) { - if (rowCount != null) { - rowCount.setParent(this); - } - this.rowCount = rowCount; - } - - public SQLExpr getOffset() { - return offset; - } - - public void setOffset(SQLExpr offset) { - if (offset != null) { - offset.setParent(this); - } - this.offset = offset; - } - - @Override - protected void accept0(SQLASTVisitor visitor) { - accept0((PGASTVisitor) visitor); - } - - @Override - public void accept0(PGASTVisitor visitor) { - if (visitor.visit(this)) { - acceptChild(visitor, offset); - acceptChild(visitor, rowCount); - } - visitor.endVisit(this); - } - - } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSelectParser.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSelectParser.java index b76fa7176c..fbce292269 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSelectParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSelectParser.java @@ -18,6 +18,7 @@ package com.alibaba.druid.sql.dialect.postgresql.parser; import java.util.List; import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.ast.SQLLimit; import com.alibaba.druid.sql.ast.SQLParameter; import com.alibaba.druid.sql.ast.SQLSetQuantifier; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; @@ -28,7 +29,6 @@ import com.alibaba.druid.sql.ast.statement.SQLTableSource; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGFunctionTableSource; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.IntoOption; -import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.PGLimit; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGValuesQuery; import com.alibaba.druid.sql.parser.ParserException; import com.alibaba.druid.sql.parser.SQLExprParser; @@ -159,7 +159,7 @@ public class PGSelectParser extends SQLSelectParser { for (;;) { if (lexer.token() == Token.LIMIT) { - PGLimit limit = new PGLimit(); + SQLLimit limit = new SQLLimit(); lexer.nextToken(); if (lexer.token() == Token.ALL) { @@ -171,9 +171,9 @@ public class PGSelectParser extends SQLSelectParser { queryBlock.setLimit(limit); } else if (lexer.token() == Token.OFFSET) { - PGLimit limit = queryBlock.getLimit(); + SQLLimit limit = queryBlock.getLimit(); if (limit == null) { - limit = new PGLimit(); + limit = new SQLLimit(); queryBlock.setLimit(limit); } lexer.nextToken(); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGASTVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGASTVisitor.java index e1371e25fa..a5d5764a71 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGASTVisitor.java @@ -39,10 +39,6 @@ import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGValuesQuery; import com.alibaba.druid.sql.visitor.SQLASTVisitor; public interface PGASTVisitor extends SQLASTVisitor { - - boolean visit(PGSelectQueryBlock.PGLimit x); - - void endVisit(PGSelectQueryBlock.PGLimit x); void endVisit(PGSelectQueryBlock x); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGASTVisitorAdapter.java index 0164ad9702..f8b663bb1a 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGASTVisitorAdapter.java @@ -34,7 +34,6 @@ import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGInsertStatement; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.FetchClause; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.ForClause; -import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.PGLimit; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.WindowClause; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectStatement; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGShowStatement; @@ -158,16 +157,6 @@ public class PGASTVisitorAdapter extends SQLASTVisitorAdapter implements PGASTVi public boolean visit(PGFunctionTableSource x) { return true; } - - @Override - public boolean visit(PGLimit x) { - return true; - } - - @Override - public void endVisit(PGLimit x) { - - } @Override public boolean visit(PGTypeCastExpr x) { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGOutputVisitor.java index f04fdcb657..f5b14a01bf 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGOutputVisitor.java @@ -15,6 +15,7 @@ */ package com.alibaba.druid.sql.dialect.postgresql.visitor; +import com.alibaba.druid.sql.ast.SQLLimit; import com.alibaba.druid.sql.ast.SQLSetQuantifier; import com.alibaba.druid.sql.ast.expr.SQLBinaryExpr; import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; @@ -38,7 +39,6 @@ import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGInsertStatement; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.FetchClause; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.ForClause; -import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.PGLimit; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.WindowClause; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectStatement; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGShowStatement; @@ -233,7 +233,6 @@ public class PGOutputVisitor extends SQLASTOutputVisitor implements PGASTVisitor if (x.getLimit() != null) { println(); - print0(ucase ? "LIMIT " : "limit "); x.getLimit().accept(this); } @@ -459,21 +458,6 @@ public class PGOutputVisitor extends SQLASTOutputVisitor implements PGASTVisitor } - @Override - public boolean visit(PGLimit x) { - x.getRowCount().accept(this); - if (x.getOffset() != null) { - print0(ucase ? " OFFSET " : " offset "); - x.getOffset().accept(this); - } - return false; - } - - @Override - public void endVisit(PGLimit x) { - - } - @Override public void endVisit(PGTypeCastExpr x) { @@ -643,4 +627,17 @@ public class PGOutputVisitor extends SQLASTOutputVisitor implements PGASTVisitor x.getExpr().accept(this); return false; } + + public boolean visit(SQLLimit x) { + print0(ucase ? "LIMIT " : "limit "); + + x.getRowCount().accept(this); + + if (x.getOffset() != null) { + print0(ucase ? " OFFSET " : " offset "); + x.getOffset().accept(this); + } + + return false; + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGSchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGSchemaStatVisitor.java index 78bde57eb7..9db0e53f86 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGSchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/visitor/PGSchemaStatVisitor.java @@ -40,7 +40,6 @@ import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGInsertStatement; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.FetchClause; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.ForClause; -import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.PGLimit; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock.WindowClause; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectStatement; import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGShowStatement; @@ -271,16 +270,6 @@ public class PGSchemaStatVisitor extends SchemaStatVisitor implements PGASTVisit public boolean visit(PGFunctionTableSource x) { return true; } - - @Override - public boolean visit(PGLimit x) { - return false; - } - - @Override - public void endVisit(PGLimit x) { - - } @Override public boolean visit(PGTypeCastExpr x) { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerOutputVisitor.java index 417f915a64..29db0305ce 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerOutputVisitor.java @@ -35,15 +35,17 @@ import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerSetTransactionI import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerUpdateStatement; import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerWaitForStatement; import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor; +import com.alibaba.druid.util.JdbcConstants; public class SQLServerOutputVisitor extends SQLASTOutputVisitor implements SQLServerASTVisitor { public SQLServerOutputVisitor(Appendable appender){ - super(appender); + super(appender, JdbcConstants.SQL_SERVER); } public SQLServerOutputVisitor(Appendable appender, boolean parameterized){ super(appender, parameterized); + this.dbType = JdbcConstants.SQL_SERVER; } public boolean visit(SQLServerSelectQueryBlock x) { diff --git a/src/main/java/com/alibaba/druid/sql/parser/Keywords.java b/src/main/java/com/alibaba/druid/sql/parser/Keywords.java index f125b4a3d7..5ed914439a 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Keywords.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Keywords.java @@ -27,6 +27,8 @@ public class Keywords { public final static Keywords DEFAULT_KEYWORDS; + public final static Keywords SQLITE_KEYWORDS; + static { Map map = new HashMap(); @@ -152,6 +154,13 @@ public class Keywords { map.put("INOUT", Token.INOUT); DEFAULT_KEYWORDS = new Keywords(map); + + Map sqlitemap = new HashMap(); + + sqlitemap.putAll(Keywords.DEFAULT_KEYWORDS.getKeywords()); + + sqlitemap.put("LIMIT", Token.LIMIT); + SQLITE_KEYWORDS = new Keywords(sqlitemap); } public boolean containsValue(Token token) { diff --git a/src/main/java/com/alibaba/druid/sql/parser/Lexer.java b/src/main/java/com/alibaba/druid/sql/parser/Lexer.java index b6fcf8b410..d313278e75 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Lexer.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Lexer.java @@ -102,6 +102,10 @@ public class Lexer { this(input, true); this.commentHandler = commentHandler; this.dbType = dbType; + + if (JdbcConstants.SQLITE.equals(dbType)) { + this.keywods = Keywords.SQLITE_KEYWORDS; + } } public boolean isKeepComments() { diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java index 2f0c80885f..54f85999ca 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java @@ -20,16 +20,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; -import com.alibaba.druid.sql.ast.SQLCommentHint; -import com.alibaba.druid.sql.ast.SQLDataType; -import com.alibaba.druid.sql.ast.SQLDataTypeImpl; -import com.alibaba.druid.sql.ast.SQLExpr; -import com.alibaba.druid.sql.ast.SQLName; -import com.alibaba.druid.sql.ast.SQLObject; -import com.alibaba.druid.sql.ast.SQLOrderBy; -import com.alibaba.druid.sql.ast.SQLOrderingSpecification; -import com.alibaba.druid.sql.ast.SQLOver; -import com.alibaba.druid.sql.ast.SQLPartitionValue; +import com.alibaba.druid.sql.ast.*; import com.alibaba.druid.sql.ast.expr.*; import com.alibaba.druid.sql.ast.statement.SQLNotNullConstraint; import com.alibaba.druid.sql.ast.statement.SQLNullConstraint; @@ -2202,4 +2193,28 @@ public class SQLExprParser extends SQLParser { } return false; } + + public SQLLimit parseLimit() { + if (lexer.token() == Token.LIMIT) { + lexer.nextToken(); + + SQLLimit limit = new SQLLimit(); + + SQLExpr temp = this.expr(); + if (lexer.token() == (Token.COMMA)) { + limit.setOffset(temp); + lexer.nextToken(); + limit.setRowCount(this.expr()); + } else if (identifierEquals("OFFSET")) { + limit.setRowCount(temp); + lexer.nextToken(); + limit.setOffset(this.expr()); + } else { + limit.setRowCount(temp); + } + return limit; + } + + return null; + } } diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLParser.java index 27406d607e..815d860efa 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLParser.java @@ -22,7 +22,7 @@ public class SQLParser { protected String dbType; public SQLParser(String sql, String dbType){ - this(new Lexer(sql), dbType); + this(new Lexer(sql, null, dbType), dbType); this.lexer.nextToken(); } diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java index 3cf9c5333f..25971e855d 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java @@ -17,10 +17,7 @@ package com.alibaba.druid.sql.parser; import java.util.List; -import com.alibaba.druid.sql.ast.SQLExpr; -import com.alibaba.druid.sql.ast.SQLOrderBy; -import com.alibaba.druid.sql.ast.SQLOrderingSpecification; -import com.alibaba.druid.sql.ast.SQLSetQuantifier; +import com.alibaba.druid.sql.ast.*; import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource; @@ -206,6 +203,8 @@ public class SQLSelectParser extends SQLParser { parseGroupBy(queryBlock); + parseFetchClause(queryBlock); + return queryRest(queryBlock); } @@ -555,6 +554,12 @@ public class SQLSelectParser extends SQLParser { } public void parseFetchClause(SQLSelectQueryBlock queryBlock) { + if (lexer.token() == Token.LIMIT) { + SQLLimit limit = this.exprParser.parseLimit(); + queryBlock.setLimit(limit); + return; + } + if (identifierEquals("OFFSET") || lexer.token() == Token.OFFSET) { lexer.nextToken(); SQLExpr offset = this.exprParser.primary(); diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java index e107379034..8c3a5713d0 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -992,12 +992,16 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet } protected void printFetchFirst(SQLSelectQueryBlock x) { - SQLExpr offset = x.getOffset(); - SQLExpr first = x.getFirst(); + SQLLimit limit = x.getLimit(); + if (limit == null) { + return; + } - boolean informix = JdbcConstants.INFORMIX.equals(dbType); - if (first != null) { - if (informix) { + SQLExpr offset = limit.getOffset(); + SQLExpr first = limit.getRowCount(); + + if (limit != null) { + if (JdbcConstants.INFORMIX.equals(dbType)) { if (offset != null) { print0(ucase ? "SKIP " : "skip "); offset.accept(this); @@ -1006,7 +1010,9 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet print0(ucase ? " FIRST " : " first "); first.accept(this); print(' '); - } else { + } else if (JdbcConstants.DB2.equals(dbType) + || JdbcConstants.ORACLE.equals(dbType) + || JdbcConstants.SQL_SERVER.equals(dbType)) { //order by 语句必须在FETCH FIRST ROWS ONLY之前 SQLObject parent = x.getParent(); if (parent instanceof SQLSelect) { @@ -1028,6 +1034,9 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet print0(ucase ? "FETCH FIRST " : "fetch first "); first.accept(this); print0(ucase ? " ROWS ONLY" : " rows only"); + } else { + println(); + limit.accept(this); } } } diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java index f89375616a..a0b0a48392 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SchemaStatVisitor.java @@ -53,12 +53,15 @@ import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; import com.alibaba.druid.sql.ast.expr.SQLSequenceExpr; import com.alibaba.druid.sql.ast.statement.*; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlExpr; +import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlASTVisitorAdapter; import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleExpr; +import com.alibaba.druid.sql.dialect.postgresql.visitor.PGASTVisitorAdapter; import com.alibaba.druid.stat.TableStat; import com.alibaba.druid.stat.TableStat.Column; import com.alibaba.druid.stat.TableStat.Condition; import com.alibaba.druid.stat.TableStat.Mode; import com.alibaba.druid.stat.TableStat.Relationship; +import com.alibaba.druid.util.JdbcConstants; public class SchemaStatVisitor extends SQLASTVisitorAdapter { @@ -235,7 +238,55 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { return oldMode; } - public class OrderByStatVisitor extends SQLASTVisitorAdapter { + private boolean visitOrderBy(SQLIdentifierExpr x) { + if (containsSubQuery(currentTable)) { + return false; + } + + String identName = x.getName(); + if (aliasMap != null && aliasMap.containsKey(identName) && aliasMap.get(identName) == null) { + return false; + } + + if (currentTable != null) { + orderByAddColumn(currentTable, identName, x); + } else { + orderByAddColumn("UNKOWN", identName, x); + } + return false; + } + + private boolean visitOrderBy(SQLPropertyExpr x) { + if (x.getOwner() instanceof SQLIdentifierExpr) { + String owner = ((SQLIdentifierExpr) x.getOwner()).getName(); + + if (containsSubQuery(owner)) { + return false; + } + + owner = aliasWrap(owner); + + if (owner != null) { + orderByAddColumn(owner, x.getName(), x); + } + } + + return false; + } + + private void orderByAddColumn(String table, String columnName, SQLObject expr) { + Column column = new Column(table, columnName); + + SQLObject parent = expr.getParent(); + if (parent instanceof SQLSelectOrderByItem) { + SQLOrderingSpecification type = ((SQLSelectOrderByItem) parent).getType(); + column.getAttributes().put("orderBy.type", type); + } + + orderByColumns.add(column); + } + + protected class OrderByStatVisitor extends SQLASTVisitorAdapter { private final SQLOrderBy orderBy; @@ -251,56 +302,89 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { } public boolean visit(SQLIdentifierExpr x) { - if (containsSubQuery(currentTable)) { - return false; - } - - String identName = x.getName(); - if (aliasMap != null && aliasMap.containsKey(identName) && aliasMap.get(identName) == null) { - return false; - } - - if (currentTable != null) { - addOrderByColumn(currentTable, identName, x); - } else { - addOrderByColumn("UNKOWN", identName, x); - } - return false; + return visitOrderBy(x); } public boolean visit(SQLPropertyExpr x) { - if (x.getOwner() instanceof SQLIdentifierExpr) { - String owner = ((SQLIdentifierExpr) x.getOwner()).getName(); + return visitOrderBy(x); + } + } - if (containsSubQuery(owner)) { - return false; - } + protected class MySqlOrderByStatVisitor extends MySqlASTVisitorAdapter { - owner = aliasWrap(owner); + private final SQLOrderBy orderBy; - if (owner != null) { - addOrderByColumn(owner, x.getName(), x); - } + public MySqlOrderByStatVisitor(SQLOrderBy orderBy){ + this.orderBy = orderBy; + for (SQLSelectOrderByItem item : orderBy.getItems()) { + item.getExpr().setParent(item); } - - return false; } - public void addOrderByColumn(String table, String columnName, SQLObject expr) { - Column column = new Column(table, columnName); + public SQLOrderBy getOrderBy() { + return orderBy; + } - SQLObject parent = expr.getParent(); - if (parent instanceof SQLSelectOrderByItem) { - SQLOrderingSpecification type = ((SQLSelectOrderByItem) parent).getType(); - column.getAttributes().put("orderBy.type", type); + public boolean visit(SQLIdentifierExpr x) { + return visitOrderBy(x); + } + + public boolean visit(SQLPropertyExpr x) { + return visitOrderBy(x); + } + } + + protected class PGOrderByStatVisitor extends PGASTVisitorAdapter { + + private final SQLOrderBy orderBy; + + public PGOrderByStatVisitor(SQLOrderBy orderBy){ + this.orderBy = orderBy; + for (SQLSelectOrderByItem item : orderBy.getItems()) { + item.getExpr().setParent(item); } + } - orderByColumns.add(column); + public SQLOrderBy getOrderBy() { + return orderBy; + } + + public boolean visit(SQLIdentifierExpr x) { + return visitOrderBy(x); + } + + public boolean visit(SQLPropertyExpr x) { + return visitOrderBy(x); + } + } + + protected class OracleOrderByStatVisitor extends PGASTVisitorAdapter { + + private final SQLOrderBy orderBy; + + public OracleOrderByStatVisitor(SQLOrderBy orderBy){ + this.orderBy = orderBy; + for (SQLSelectOrderByItem item : orderBy.getItems()) { + item.getExpr().setParent(item); + } + } + + public SQLOrderBy getOrderBy() { + return orderBy; + } + + public boolean visit(SQLIdentifierExpr x) { + return visitOrderBy(x); + } + + public boolean visit(SQLPropertyExpr x) { + return visitOrderBy(x); } } public boolean visit(SQLOrderBy x) { - OrderByStatVisitor orderByVisitor = new OrderByStatVisitor(x); + final SQLASTVisitor orderByVisitor = createOrderByVisitor(x); + SQLSelectQueryBlock query = null; if (x.getParent() instanceof SQLSelectQueryBlock) { query = (SQLSelectQueryBlock) x.getParent(); @@ -323,6 +407,20 @@ public class SchemaStatVisitor extends SQLASTVisitorAdapter { return true; } + protected SQLASTVisitor createOrderByVisitor(SQLOrderBy x) { + final SQLASTVisitor orderByVisitor; + if (JdbcConstants.MYSQL.equals(getDbType())) { + orderByVisitor = new MySqlOrderByStatVisitor(x); + } else if (JdbcConstants.POSTGRESQL.equals(getDbType())) { + orderByVisitor = new PGOrderByStatVisitor(x); + } else if (JdbcConstants.ORACLE.equals(getDbType())) { + orderByVisitor = new OracleOrderByStatVisitor(x); + } else { + orderByVisitor = new OrderByStatVisitor(x); + } + return orderByVisitor; + } + public Set getRelationships() { return relationships; } diff --git a/src/main/java/com/alibaba/druid/util/JdbcConstants.java b/src/main/java/com/alibaba/druid/util/JdbcConstants.java index dc87915e50..04ef40ce8a 100644 --- a/src/main/java/com/alibaba/druid/util/JdbcConstants.java +++ b/src/main/java/com/alibaba/druid/util/JdbcConstants.java @@ -91,4 +91,7 @@ public interface JdbcConstants { public static final String ENTERPRISEDB = "edb"; public static final String ENTERPRISEDB_DRIVER = "com.edb.Driver"; + + public static final String SQLITE = "sqlite"; + public static final String SQLITE_DRIVER = "org.sqlite.JDBC"; } diff --git a/src/main/java/com/alibaba/druid/util/JdbcUtils.java b/src/main/java/com/alibaba/druid/util/JdbcUtils.java index 8fb9bbf64a..d7cf0f58bf 100644 --- a/src/main/java/com/alibaba/druid/util/JdbcUtils.java +++ b/src/main/java/com/alibaba/druid/util/JdbcUtils.java @@ -405,7 +405,7 @@ public final class JdbcUtils implements JdbcConstants { } else if (rawUrl.startsWith("jdbc:db2:")) { return DB2_DRIVER; } else if (rawUrl.startsWith("jdbc:sqlite:")) { - return "org.sqlite.JDBC"; + return SQLITE_DRIVER; } else if (rawUrl.startsWith("jdbc:ingres:")) { return "com.ingres.jdbc.IngresDriver"; } else if (rawUrl.startsWith("jdbc:h2:")) { @@ -490,7 +490,7 @@ public final class JdbcUtils implements JdbcConstants { } else if (rawUrl.startsWith("jdbc:db2:")) { return DB2; } else if (rawUrl.startsWith("jdbc:sqlite:")) { - return "sqlite"; + return SQLITE; } else if (rawUrl.startsWith("jdbc:ingres:")) { return "ingres"; } else if (rawUrl.startsWith("jdbc:h2:") || rawUrl.startsWith("jdbc:log4jdbc:h2:")) { diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/visitor/MySqlSchemaStatVisitorTest6.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/visitor/MySqlSchemaStatVisitorTest6.java new file mode 100644 index 0000000000..b2e1dd130c --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/visitor/MySqlSchemaStatVisitorTest6.java @@ -0,0 +1,56 @@ +/* + * Copyright 1999-2101 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.bvt.sql.mysql.visitor; + +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; +import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor; +import junit.framework.TestCase; +import org.junit.Assert; + +import java.util.List; + +public class MySqlSchemaStatVisitorTest6 extends TestCase { + + public void test_0() throws Exception { + String sql = "select * from t order by trim(trim(INTERVAL 3 YEAR))"; + +// sql = "select columnName from table1 where id in (select id from table3 where name = ?)"; + MySqlStatementParser parser = new MySqlStatementParser(sql); + List statementList = parser.parseStatementList(); + SQLStatement stmt = statementList.get(0); + + Assert.assertEquals(1, statementList.size()); + + MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor(); + stmt.accept(visitor); + + System.out.println(sql); + System.out.println("Tables : " + visitor.getTables()); + System.out.println("fields : " + visitor.getColumns()); + + Assert.assertEquals(1, visitor.getTables().size()); + Assert.assertEquals(true, visitor.containsTable("t")); + + Assert.assertEquals(1, visitor.getColumns().size()); + // Assert.assertEquals(true, visitor.getFields().contains(new + // Column("users", "id"))); + // Assert.assertEquals(true, visitor.getFields().contains(new + // Column("users", "name"))); + + } + +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/sqlite/SQLite_SelectTest_0.java b/src/test/java/com/alibaba/druid/bvt/sql/sqlite/SQLite_SelectTest_0.java new file mode 100644 index 0000000000..aa889d934b --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/sqlite/SQLite_SelectTest_0.java @@ -0,0 +1,60 @@ +/* + * Copyright 1999-2101 Alibaba Group Holding Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package com.alibaba.druid.bvt.sql.sqlite; + +import com.alibaba.druid.sql.MysqlTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; +import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor; +import com.alibaba.druid.sql.parser.SQLStatementParser; +import com.alibaba.druid.sql.visitor.SchemaStatVisitor; +import com.alibaba.druid.stat.TableStat; +import com.alibaba.druid.stat.TableStat.Column; +import com.alibaba.druid.util.JdbcConstants; +import org.junit.Assert; + +import java.util.List; + +public class SQLite_SelectTest_0 extends MysqlTest { + + public void test_0() throws Exception { + String sql = "select first_name, last_name from mytable limit 3, 4"; + + List statementList = SQLUtils.parseStatements(sql, JdbcConstants.SQLITE); + SQLStatement statemen = statementList.get(0); + print(statementList); + + Assert.assertEquals(1, statementList.size()); + + SchemaStatVisitor visitor = new MySqlSchemaStatVisitor(); + statemen.accept(visitor); + +// System.out.println("Tables : " + visitor.getTables()); +// System.out.println("fields : " + visitor.getColumns()); +// System.out.println("coditions : " + visitor.getConditions()); +// System.out.println("orderBy : " + visitor.getOrderByColumns()); + + Assert.assertEquals(1, visitor.getTables().size()); + Assert.assertEquals(2, visitor.getColumns().size()); + Assert.assertEquals(0, visitor.getConditions().size()); + + Assert.assertTrue(visitor.getTables().containsKey(new TableStat.Name("mytable"))); + + Assert.assertTrue(visitor.getColumns().contains(new Column("mytable", "last_name"))); + Assert.assertTrue(visitor.getColumns().contains(new Column("mytable", "first_name"))); + } +}