diff --git a/src/main/java/com/alibaba/druid/sql/SQLUtils.java b/src/main/java/com/alibaba/druid/sql/SQLUtils.java index 5ca34e520e..beb1e4e0da 100644 --- a/src/main/java/com/alibaba/druid/sql/SQLUtils.java +++ b/src/main/java/com/alibaba/druid/sql/SQLUtils.java @@ -284,7 +284,12 @@ public class SQLUtils { visitor.setTableMapping(tableMapping); } - boolean printStmtSeperator = !JdbcConstants.ORACLE.equals(dbType); + boolean printStmtSeperator; + if (JdbcConstants.SQL_SERVER.equals(dbType)) { + printStmtSeperator = false; + } else { + printStmtSeperator = !JdbcConstants.ORACLE.equals(dbType); + } for (int i = 0, size = statementList.size(); i < size; i++) { SQLStatement stmt = statementList.get(i); diff --git a/src/main/java/com/alibaba/druid/sql/ast/SQLObjectImpl.java b/src/main/java/com/alibaba/druid/sql/ast/SQLObjectImpl.java index 52f4209040..ce01c50d2b 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/SQLObjectImpl.java +++ b/src/main/java/com/alibaba/druid/sql/ast/SQLObjectImpl.java @@ -168,6 +168,10 @@ public abstract class SQLObjectImpl implements SQLObject { @SuppressWarnings("unchecked") public void addAfterComment(List comments) { + if (comments == null) { + return; + } + if (attributes == null) { attributes = new HashMap(1); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OraclePLSQLCommitStatement.java b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLScriptCommitStatement.java similarity index 69% rename from src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OraclePLSQLCommitStatement.java rename to src/main/java/com/alibaba/druid/sql/ast/statement/SQLScriptCommitStatement.java index ff43f5e762..d5c203942b 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/stmt/OraclePLSQLCommitStatement.java +++ b/src/main/java/com/alibaba/druid/sql/ast/statement/SQLScriptCommitStatement.java @@ -13,17 +13,19 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package com.alibaba.druid.sql.dialect.oracle.ast.stmt; +package com.alibaba.druid.sql.ast.statement; +import com.alibaba.druid.sql.ast.SQLStatementImpl; import com.alibaba.druid.sql.dialect.oracle.visitor.OracleASTVisitor; +import com.alibaba.druid.sql.visitor.SQLASTVisitor; -public class OraclePLSQLCommitStatement extends OracleStatementImpl { +public class SQLScriptCommitStatement extends SQLStatementImpl { - public OraclePLSQLCommitStatement(){ + public SQLScriptCommitStatement(){ } - public void accept0(OracleASTVisitor visitor) { + public void accept0(SQLASTVisitor visitor) { visitor.visit(this); visitor.endVisit(this); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlLexer.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlLexer.java index 4ee3faadfb..a2aa0106d7 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlLexer.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlLexer.java @@ -144,18 +144,13 @@ public class MySqlLexer extends Lexer { } public void scanVariable() { - if (ch != '@' && ch != ':' && ch != '#' && ch != '$') { + if (ch != ':' && ch != '#' && ch != '$') { throw new ParserException("illegal variable. " + info()); } mark = pos; bufPos = 1; - if (charAt(pos + 1) == '@') { - ch = charAt(++pos); - bufPos++; - } - if (charAt(pos + 1) == '`') { ++pos; ++bufPos; @@ -221,6 +216,61 @@ public class MySqlLexer extends Lexer { token = Token.VARIANT; } + protected void scanVariable_at() { + if (ch != '@') { + throw new ParserException("illegal variable. " + info()); + } + + mark = pos; + bufPos = 1; + + if (charAt(pos + 1) == '@') { + ch = charAt(++pos); + bufPos++; + } + + if (charAt(pos + 1) == '`') { + ++pos; + ++bufPos; + char ch; + for (;;) { + ch = charAt(++pos); + + if (ch == '`') { + bufPos++; + ++pos; + break; + } else if (ch == EOI) { + throw new ParserException("illegal identifier. " + info()); + } + + bufPos++; + continue; + } + + this.ch = charAt(pos); + + stringVal = subString(mark, bufPos); + token = Token.VARIANT; + } else { + for (; ; ) { + ch = charAt(++pos); + + if (!isIdentifierChar(ch)) { + break; + } + + bufPos++; + continue; + } + } + + this.ch = charAt(pos); + + stringVal = subString(mark, bufPos); + token = Token.VARIANT; + } + public void scanIdentifier() { hash_lower = 0; hash = 0; @@ -342,6 +392,8 @@ public class MySqlLexer extends Lexer { } } + + protected final void scanString() { scanString2(); } 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 865f8a590c..61091fcd68 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 @@ -17,15 +17,7 @@ package com.alibaba.druid.sql.dialect.mysql.parser; import com.alibaba.druid.sql.ast.*; import com.alibaba.druid.sql.ast.SQLParameter.ParameterType; -import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr; -import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator; -import com.alibaba.druid.sql.ast.expr.SQLCharExpr; -import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; -import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr; -import com.alibaba.druid.sql.ast.expr.SQLLiteralExpr; -import com.alibaba.druid.sql.ast.expr.SQLNCharExpr; -import com.alibaba.druid.sql.ast.expr.SQLQueryExpr; -import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr; +import com.alibaba.druid.sql.ast.expr.*; import com.alibaba.druid.sql.ast.statement.*; import com.alibaba.druid.sql.ast.statement.SQLInsertStatement.ValuesClause; import com.alibaba.druid.sql.dialect.mysql.ast.MysqlForeignKey; @@ -65,7 +57,6 @@ public class MySqlStatementParser extends SQLStatementParser { private static final String GLOBAL = "GLOBAL"; private static final String VARIABLES = "VARIABLES"; private static final String STATUS = "STATUS"; - private static final String IGNORE = "IGNORE"; private static final String RESET = "RESET"; private static final String DESCRIBE = "DESCRIBE"; private static final String WRITE = "WRITE"; @@ -75,7 +66,6 @@ public class MySqlStatementParser extends SQLStatementParser { private static final String TEMPORARY = "TEMPORARY"; private static final String SPATIAL = "SPATIAL"; private static final String FULLTEXT = "FULLTEXT"; - private static final String DELAYED = "DELAYED"; private static final String LOW_PRIORITY = "LOW_PRIORITY"; private static final String CONNECTION = "CONNECTION"; private static final String EXTENDED = "EXTENDED"; @@ -151,7 +141,7 @@ public class MySqlStatementParser extends SQLStatementParser { this.getExprParser().parseHints(deleteStatement.getHints()); } - if (lexer.identifierEquals(LOW_PRIORITY)) { + if (lexer.identifierEquals(FnvHash.Constants.LOW_PRIORITY)) { deleteStatement.setLowPriority(true); lexer.nextToken(); } @@ -161,7 +151,7 @@ public class MySqlStatementParser extends SQLStatementParser { lexer.nextToken(); } - if (lexer.identifierEquals(IGNORE)) { + if (lexer.identifierEquals(FnvHash.Constants.IGNORE)) { deleteStatement.setIgnore(true); lexer.nextToken(); } @@ -607,7 +597,7 @@ public class MySqlStatementParser extends SQLStatementParser { } } else if (lexer.identifierEquals(WRITE)) { stmt.setLockType(LockType.WRITE); - } else if (lexer.identifierEquals(LOW_PRIORITY)) { + } else if (lexer.identifierEquals(FnvHash.Constants.LOW_PRIORITY)) { lexer.nextToken(); acceptIdentifier(WRITE); stmt.setLockType(LockType.LOW_PRIORITY_WRITE); @@ -1792,12 +1782,12 @@ public class MySqlStatementParser extends SQLStatementParser { lexer.nextToken(); } - if (lexer.identifierEquals(LOW_PRIORITY)) { + if (lexer.identifierEquals(FnvHash.Constants.LOW_PRIORITY)) { stmt.setLowPriority(true); lexer.nextToken(); } - if (lexer.identifierEquals(DELAYED)) { + if (lexer.identifierEquals(FnvHash.Constants.DELAYED)) { stmt.setDelayed(true); lexer.nextToken(); } @@ -1879,7 +1869,7 @@ public class MySqlStatementParser extends SQLStatementParser { MySqlLoadXmlStatement stmt = new MySqlLoadXmlStatement(); - if (lexer.identifierEquals(LOW_PRIORITY)) { + if (lexer.identifierEquals(FnvHash.Constants.LOW_PRIORITY)) { stmt.setLowPriority(true); lexer.nextToken(); } @@ -1904,7 +1894,7 @@ public class MySqlStatementParser extends SQLStatementParser { lexer.nextToken(); } - if (lexer.identifierEquals(IGNORE)) { + if (lexer.identifierEquals(FnvHash.Constants.IGNORE)) { stmt.setIgnore(true); lexer.nextToken(); } @@ -1936,7 +1926,7 @@ public class MySqlStatementParser extends SQLStatementParser { stmt.setRowsIdentifiedBy(rowsIdentifiedBy); } - if (lexer.identifierEquals(IGNORE)) { + if (lexer.identifierEquals(FnvHash.Constants.IGNORE)) { throw new ParserException("TODO. " + lexer.info()); } @@ -1953,7 +1943,7 @@ public class MySqlStatementParser extends SQLStatementParser { MySqlLoadDataInFileStatement stmt = new MySqlLoadDataInFileStatement(); - if (lexer.identifierEquals(LOW_PRIORITY)) { + if (lexer.identifierEquals(FnvHash.Constants.LOW_PRIORITY)) { stmt.setLowPriority(true); lexer.nextToken(); } @@ -1978,7 +1968,7 @@ public class MySqlStatementParser extends SQLStatementParser { lexer.nextToken(); } - if (lexer.identifierEquals(IGNORE)) { + if (lexer.identifierEquals(FnvHash.Constants.IGNORE)) { stmt.setIgnore(true); lexer.nextToken(); } @@ -2048,7 +2038,7 @@ public class MySqlStatementParser extends SQLStatementParser { } } - if (lexer.identifierEquals(IGNORE)) { + if (lexer.identifierEquals(FnvHash.Constants.IGNORE)) { lexer.nextToken(); stmt.setIgnoreLinesNumber(this.exprParser.expr()); acceptIdentifier("LINES"); @@ -2115,35 +2105,40 @@ public class MySqlStatementParser extends SQLStatementParser { lexer.nextToken(); for (; ; ) { - if (lexer.identifierEquals(LOW_PRIORITY)) { - insertStatement.setLowPriority(true); - lexer.nextToken(); - continue; + if (lexer.token() == Token.IDENTIFIER) { + long hash = lexer.hash_lower(); + + if (hash == FnvHash.Constants.LOW_PRIORITY) { + insertStatement.setLowPriority(true); + lexer.nextToken(); + continue; + } + + if (hash == FnvHash.Constants.DELAYED) { + insertStatement.setDelayed(true); + lexer.nextToken(); + continue; + } + + if (hash == FnvHash.Constants.HIGH_PRIORITY) { + insertStatement.setHighPriority(true); + lexer.nextToken(); + continue; + } + + if (hash == FnvHash.Constants.IGNORE) { + insertStatement.setIgnore(true); + lexer.nextToken(); + continue; + } + + if (hash == FnvHash.Constants.ROLLBACK_ON_FAIL) { + insertStatement.setRollbackOnFail(true); + lexer.nextToken(); + continue; + } } - if (lexer.identifierEquals(DELAYED)) { - insertStatement.setDelayed(true); - lexer.nextToken(); - continue; - } - - if (lexer.identifierEquals("HIGH_PRIORITY")) { - insertStatement.setHighPriority(true); - lexer.nextToken(); - continue; - } - - if (lexer.identifierEquals(IGNORE)) { - insertStatement.setIgnore(true); - lexer.nextToken(); - continue; - } - - if (lexer.identifierEquals("ROLLBACK_ON_FAIL")) { - insertStatement.setRollbackOnFail(true); - lexer.nextToken(); - continue; - } break; } @@ -2155,7 +2150,8 @@ public class MySqlStatementParser extends SQLStatementParser { SQLName tableName = this.exprParser.name(); insertStatement.setTableName(tableName); - if (lexer.token() == Token.IDENTIFIER && !lexer.identifierEquals("VALUE")) { + if (lexer.token() == Token.IDENTIFIER + && !lexer.identifierEquals(FnvHash.Constants.VALUE)) { insertStatement.setAlias(lexer.stringVal()); lexer.nextToken(); } @@ -2163,20 +2159,59 @@ public class MySqlStatementParser extends SQLStatementParser { } int columnSize = 0; - if (lexer.token() == (Token.LPAREN)) { + if (lexer.token() == Token.LPAREN) { lexer.nextToken(); - if (lexer.token() == (Token.SELECT)) { + if (lexer.token() == Token.SELECT) { SQLSelect select = this.exprParser.createSelectParser().select(); select.setParent(insertStatement); insertStatement.setQuery(select); } else { - this.exprParser.exprList(insertStatement.getColumns(), insertStatement); - columnSize = insertStatement.getColumns().size(); + List columns = insertStatement.getColumns(); + //this.exprParser.exprList(insertStatement.getColumns(), insertStatement); + + if (lexer.token() != Token.RPAREN) { + for (; ; ) { + String identName; + long hash; + + Token token = lexer.token(); + if (token == Token.IDENTIFIER) { + identName = lexer.stringVal(); + hash = lexer.hash_lower(); + } else if (token == Token.LITERAL_CHARS) { + identName = '\'' + lexer.stringVal() + '\''; + hash = 0; + } else { + identName = lexer.stringVal(); + hash = 0; + } + lexer.nextTokenComma(); + SQLExpr expr = new SQLIdentifierExpr(identName, hash); + while (lexer.token() == Token.DOT) { + lexer.nextToken(); + String propertyName = lexer.stringVal(); + lexer.nextToken(); + expr = new SQLPropertyExpr(expr, propertyName); + } + + expr.setParent(insertStatement); + columns.add(expr); + columnSize++; + + if (lexer.token() == Token.COMMA) { + lexer.nextToken(); + continue; + } + + break; + } + columnSize = insertStatement.getColumns().size(); + } } accept(Token.RPAREN); } - if (lexer.token() == Token.VALUES || lexer.identifierEquals("VALUE")) { + if (lexer.token() == Token.VALUES || lexer.identifierEquals(FnvHash.Constants.VALUE)) { lexer.nextTokenLParen(); parseValueClause(insertStatement.getValuesList(), columnSize, insertStatement); } else if (lexer.token() == Token.SET) { @@ -2472,7 +2507,7 @@ public class MySqlStatementParser extends SQLStatementParser { boolean ignore = false; - if (lexer.identifierEquals(IGNORE)) { + if (lexer.identifierEquals(FnvHash.Constants.IGNORE)) { ignore = true; lexer.nextToken(); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java index 92e849a5af..b78ec59701 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java @@ -1072,7 +1072,7 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV print0(ucase ? "INTO " : "into "); - printExpr(x.getTableName()); + printTableSourceExpr(x.getTableName()); List columns = x.getColumns(); if (columns.size() > 0) { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/OracleToMySqlOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/OracleToMySqlOutputVisitor.java index a364803ec5..0f50643b8c 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/OracleToMySqlOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/OracleToMySqlOutputVisitor.java @@ -15,6 +15,7 @@ */ package com.alibaba.druid.sql.dialect.mysql.visitor; +import com.alibaba.druid.sql.ast.statement.SQLScriptCommitStatement; import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalDay; import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalYear; import com.alibaba.druid.sql.dialect.oracle.ast.clause.*; @@ -34,10 +35,6 @@ public class OracleToMySqlOutputVisitor extends MySqlOutputVisitor implements Or super(appender, parameterized); } - @Override - public void endVisit(OraclePLSQLCommitStatement astNode) { - - } @Override public void endVisit(OracleAnalytic x) { @@ -109,11 +106,6 @@ public class OracleToMySqlOutputVisitor extends MySqlOutputVisitor implements Or } - @Override - public boolean visit(OraclePLSQLCommitStatement astNode) { - return false; - } - @Override public boolean visit(OracleAnalytic x) { return false; diff --git a/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsExprParser.java index 15d4677c3f..c8404c76a2 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsExprParser.java @@ -153,24 +153,6 @@ public class OdpsExprParser extends SQLExprParser { return super.primaryRest(expr); } - public SQLExpr equalityRest(SQLExpr expr) { - if (lexer.token() == Token.EQEQ) { - SQLExpr rightExp; - lexer.nextToken(); - try { - rightExp = bitOr(); - } catch (EOFParserException e) { - throw new ParserException("EOF, " + expr + "=", e); - } - rightExp = equalityRest(rightExp); - - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Equality, rightExp, getDbType()); - - return expr; - } - - return super.equalityRest(expr); - } public SQLExpr relationalRest(SQLExpr expr) { if (lexer.identifierEquals("REGEXP")) { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsLexer.java b/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsLexer.java index 901aea349d..6f4f884d64 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsLexer.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/odps/parser/OdpsLexer.java @@ -362,6 +362,10 @@ public class OdpsLexer extends Lexer { super.scanVariable(); } + protected void scanVariable_at() { + scanVariable(); + } + protected final void scanString() { scanString2(); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java index e501abcee4..393999dd5d 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleExprParser.java @@ -998,43 +998,6 @@ public class OracleExprParser extends SQLExprParser { return name; } - public SQLExpr equalityRest(SQLExpr expr) { - SQLExpr rightExp; - if (lexer.token() == Token.EQ) { - lexer.nextToken(); - - if (lexer.token() == Token.GT) { - lexer.nextToken(); - rightExp = expr(); - String argumentName = ((SQLIdentifierExpr) expr).getName(); - return new OracleArgumentExpr(argumentName, rightExp); - } - - rightExp = shift(); - - rightExp = equalityRest(rightExp); - - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Equality, rightExp, getDbType()); - } else if (lexer.token() == Token.BANGEQ || lexer.token() == Token.CARETEQ) { - lexer.nextToken(); - rightExp = shift(); - - rightExp = equalityRest(rightExp); - - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.NotEqual, rightExp, getDbType()); - } else if (lexer.token() == Token.BANG) { - lexer.nextToken(); - accept(Token.EQ); - rightExp = shift(); - - rightExp = equalityRest(rightExp); - - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.NotEqual, rightExp, getDbType()); - } - - return expr; - } - public OraclePrimaryKey parsePrimaryKey() { lexer.nextToken(); accept(Token.KEY); @@ -1043,7 +1006,6 @@ public class OracleExprParser extends SQLExprParser { accept(Token.LPAREN); orderBy(primaryKey.getColumns(), primaryKey); accept(Token.RPAREN); - if (lexer.token() == Token.USING) { OracleUsingIndexClause using = parseUsingIndex(); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleLexer.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleLexer.java index 29f7044036..78ee204ccf 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleLexer.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleLexer.java @@ -144,12 +144,6 @@ public class OracleLexer extends Lexer { } public void scanVariable() { - if (ch == '@') { - scanChar(); - token = Token.MONKEYS_AT; - return; - } - if (ch != ':' && ch != '#' && ch != '$') { throw new ParserException("illegal variable. " + info()); } @@ -206,6 +200,12 @@ public class OracleLexer extends Lexer { } } + protected void scanVariable_at() { + scanChar(); + token = Token.MONKEYS_AT; + return; + } + public void scanComment() { if (ch != '/' && ch != '-') { throw new IllegalStateException(); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleStatementParser.java index 68982cd93a..70c71273e5 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleStatementParser.java @@ -129,7 +129,7 @@ public class OracleStatementParser extends SQLStatementParser { if (lexer.token() == (Token.SLASH)) { lexer.nextToken(); - SQLStatement stmt = new OraclePLSQLCommitStatement(); + SQLStatement stmt = new SQLScriptCommitStatement(); stmt.setParent(parent); statementList.add(stmt); continue; diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitor.java index c870f74092..a78756018e 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitor.java @@ -36,7 +36,7 @@ import com.alibaba.druid.sql.visitor.SQLASTVisitor; public interface OracleASTVisitor extends SQLASTVisitor { - void endVisit(OraclePLSQLCommitStatement astNode); + void endVisit(OracleAnalytic x); @@ -68,8 +68,6 @@ public interface OracleASTVisitor extends SQLASTVisitor { void endVisit(OracleUpdateStatement x); - boolean visit(OraclePLSQLCommitStatement astNode); - boolean visit(OracleAnalytic x); boolean visit(OracleAnalyticWindowing x); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitorAdapter.java index fa968b026f..4d7134c336 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleASTVisitorAdapter.java @@ -17,6 +17,7 @@ package com.alibaba.druid.sql.dialect.oracle.visitor; import com.alibaba.druid.sql.ast.statement.SQLMergeStatement.MergeInsertClause; import com.alibaba.druid.sql.ast.statement.SQLMergeStatement.MergeUpdateClause; +import com.alibaba.druid.sql.ast.statement.SQLScriptCommitStatement; import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalDay; import com.alibaba.druid.sql.dialect.oracle.ast.OracleDataTypeIntervalYear; import com.alibaba.druid.sql.dialect.oracle.ast.clause.CycleClause; @@ -49,7 +50,7 @@ import com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter; public class OracleASTVisitorAdapter extends SQLASTVisitorAdapter implements OracleASTVisitor { @Override - public void endVisit(OraclePLSQLCommitStatement astNode) { + public void endVisit(SQLScriptCommitStatement astNode) { } @@ -124,7 +125,7 @@ public class OracleASTVisitorAdapter extends SQLASTVisitorAdapter implements Ora } @Override - public boolean visit(OraclePLSQLCommitStatement astNode) { + public boolean visit(SQLScriptCommitStatement astNode) { return true; } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java index 0a4c8f99eb..9196bd0cd4 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleOutputVisitor.java @@ -212,7 +212,7 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS return false; } - public boolean visit(OraclePLSQLCommitStatement astNode) { + public boolean visit(SQLScriptCommitStatement astNode) { print('/'); println(); return false; @@ -624,11 +624,6 @@ public class OracleOutputVisitor extends SQLASTOutputVisitor implements OracleAS return false; } - @Override - public void endVisit(OraclePLSQLCommitStatement astNode) { - - } - @Override public void endVisit(OracleAnalytic x) { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java index de362af6b1..e0547c9e7e 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/visitor/OracleSchemaStatVisitor.java @@ -17,7 +17,6 @@ package com.alibaba.druid.sql.dialect.oracle.visitor; import java.util.ArrayList; import java.util.List; -import java.util.Map; import com.alibaba.druid.sql.SQLUtils; import com.alibaba.druid.sql.ast.SQLExpr; @@ -222,11 +221,6 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle return super.visit(x); } - @Override - public void endVisit(OraclePLSQLCommitStatement astNode) { - - } - @Override public void endVisit(OracleAnalytic x) { @@ -288,7 +282,7 @@ public class OracleSchemaStatVisitor extends SchemaStatVisitor implements Oracle } @Override - public boolean visit(OraclePLSQLCommitStatement astNode) { + public boolean visit(SQLScriptCommitStatement astNode) { return true; } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGLexer.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGLexer.java index 55ecc0d098..e734d1238d 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGLexer.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGLexer.java @@ -15,15 +15,13 @@ */ package com.alibaba.druid.sql.dialect.postgresql.parser; +import static com.alibaba.druid.sql.parser.CharTypes.isIdentifierChar; import static com.alibaba.druid.sql.parser.Token.LITERAL_CHARS; import java.util.HashMap; import java.util.Map; -import com.alibaba.druid.sql.parser.Keywords; -import com.alibaba.druid.sql.parser.Lexer; -import com.alibaba.druid.sql.parser.SQLParserFeature; -import com.alibaba.druid.sql.parser.Token; +import com.alibaba.druid.sql.parser.*; import com.alibaba.druid.util.JdbcConstants; public class PGLexer extends Lexer { @@ -187,4 +185,43 @@ public class PGLexer extends Lexer { token = Token.POUND; } } + + protected void scanVariable_at() { + if (ch != '@') { + throw new ParserException("illegal variable. " + info()); + } + + mark = pos; + bufPos = 1; + char ch; + + final char c1 = charAt(pos + 1); + if (c1 == '@') { + pos += 2; + token = Token.MONKEYS_AT_AT; + this.ch = charAt(++pos); + return; + } else if (c1 == '>') { + pos += 2; + token = Token.MONKEYS_AT_GT; + this.ch = charAt(++pos); + return; + } + + for (;;) { + ch = charAt(++pos); + + if (!isIdentifierChar(ch)) { + break; + } + + bufPos++; + continue; + } + + this.ch = charAt(pos); + + stringVal = addSymbol(); + token = Token.VARIANT; + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerStatementParser.java index bbca866e71..5ab11024f9 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerStatementParser.java @@ -38,6 +38,7 @@ 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.parser.*; +import com.alibaba.druid.util.FnvHash; public class SQLServerStatementParser extends SQLStatementParser { @@ -64,7 +65,7 @@ public class SQLServerStatementParser extends SQLStatementParser { return true; } - if (lexer.identifierEquals("EXEC") || lexer.identifierEquals("EXECUTE")) { + if (lexer.identifierEquals(FnvHash.Constants.EXEC) || lexer.identifierEquals(FnvHash.Constants.EXECUTE)) { lexer.nextToken(); SQLServerExecStatement execStmt = new SQLServerExecStatement(); @@ -109,10 +110,18 @@ public class SQLServerStatementParser extends SQLStatementParser { return true; } - if (lexer.identifierEquals("WAITFOR")) { + if (lexer.identifierEquals(FnvHash.Constants.WAITFOR)) { statementList.add(this.parseWaitFor()); return true; } + + if (lexer.identifierEquals(FnvHash.Constants.GO)) { + lexer.nextToken(); + + SQLStatement stmt = new SQLScriptCommitStatement(); + statementList.add(stmt); + return true; + } return false; } @@ -442,7 +451,7 @@ public class SQLServerStatementParser extends SQLStatementParser { stmt.setCondition(this.exprParser.expr()); - this.parseStatementList(stmt.getStatements(), 1); + this.parseStatementList(stmt.getStatements(), 1, stmt); if(lexer.token() == Token.SEMI) { lexer.nextToken(); @@ -452,7 +461,7 @@ public class SQLServerStatementParser extends SQLStatementParser { lexer.nextToken(); SQLIfStatement.Else elseItem = new SQLIfStatement.Else(); - this.parseStatementList(elseItem.getStatements(), 1); + this.parseStatementList(elseItem.getStatements(), 1, elseItem); stmt.setElseItem(elseItem); } 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 2c4cc10aa4..111855e29a 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 @@ -573,4 +573,10 @@ public class SQLServerOutputVisitor extends SQLASTOutputVisitor implements SQLSe return false; } + + @Override + public boolean visit(SQLScriptCommitStatement x) { + print0(ucase ? "GO" : "go"); + return false; + } } 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 a9dc8a1240..371b062e42 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Lexer.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Lexer.java @@ -325,6 +325,40 @@ public class Lexer { nextToken(); } + public final void nextTokenEq() { + if (ch == ' ') { + scanChar(); + } + + if (ch == '=') { + scanChar(); + token = EQ; + return; + } + + if (ch == '.') { + scanChar(); + token = DOT; + return; + } + + if (ch == 'a' || ch == 'A') { + char ch_next = charAt(pos + 1); + if (ch_next == 's' || ch_next == 'S') { + char ch_next_2 = charAt(pos + 2); + if (ch_next_2 == ' ') { + pos += 2; + ch = ' '; + token = Token.AS; + stringVal = "AS"; + return; + } + } + } + + nextToken(); + } + public final void nextTokenLParen() { if (ch == ' ') { scanChar(); @@ -362,7 +396,30 @@ public class Lexer { return; } - if (isFirstIdentifierChar(ch) && ch != 'N') { + if (ch == 'n' || ch == 'N') { + char c1 = 0, c2, c3, c4; + if (pos + 4 < text.length() + && ((c1 = text.charAt(pos + 1)) == 'u' || c1 == 'U') + && ((c2 = text.charAt(pos + 2)) == 'l' || c2 == 'L') + && ((c3 = text.charAt(pos + 3)) == 'l' || c3 == 'L') + && (isWhitespace(c4 = text.charAt(pos + 4)) || c4 == ',' || c4 == ')')) { + pos += 4; + ch = c4; + token = Token.NULL; + stringVal = "NULL"; + return; + } + + if (c1 == '\'') { + ++pos; + ch = '\''; + scanString(); + token = Token.LITERAL_NCHARS; + return; + } + } + + if (isFirstIdentifierChar(ch)) { scanIdentifier(); return; } @@ -608,7 +665,7 @@ public class Lexer { case '`': throw new ParserException("TODO. " + info()); // TODO case '@': - scanVariable(); + scanVariable_at(); return; case '-': if (charAt(pos +1) == '-') { @@ -736,6 +793,9 @@ public class Lexer { if (ch == '=') { scanChar(); token = Token.EQEQ; + } else if (ch == '>') { + scanChar(); + token = Token.EQGT; } else { token = Token.EQ; } @@ -781,6 +841,9 @@ public class Lexer { break; case '!': scanChar(); + while (isWhitespace(ch)) { + scanChar(); + } if (ch == '=') { scanChar(); token = Token.BANGEQ; @@ -1145,7 +1208,7 @@ public class Lexer { } public void scanVariable() { - if (ch != '@' && ch != ':' && ch != '#' && ch != '$') { + if (ch != ':' && ch != '#' && ch != '$') { throw new ParserException("illegal variable. " + info()); } @@ -1154,17 +1217,7 @@ public class Lexer { char ch; final char c1 = charAt(pos + 1); - if (c1 == '@') { - if (JdbcConstants.POSTGRESQL.equalsIgnoreCase(dbType)) { - pos += 2; - token = Token.MONKEYS_AT_AT; - this.ch = charAt(++pos); - return; - } - ch = charAt(++pos); - - bufPos++; - } else if (c1 == '>' && JdbcConstants.POSTGRESQL.equalsIgnoreCase(dbType)) { + if (c1 == '>' && JdbcConstants.POSTGRESQL.equalsIgnoreCase(dbType)) { pos += 2; token = Token.MONKEYS_AT_GT; this.ch = charAt(++pos); @@ -1214,6 +1267,38 @@ public class Lexer { token = Token.VARIANT; } + protected void scanVariable_at() { + if (ch != '@') { + throw new ParserException("illegal variable. " + info()); + } + + mark = pos; + bufPos = 1; + char ch; + + final char c1 = charAt(pos + 1); + if (c1 == '@') { + ++pos; + bufPos++; + } + + for (;;) { + ch = charAt(++pos); + + if (!isIdentifierChar(ch)) { + break; + } + + bufPos++; + continue; + } + + this.ch = charAt(pos); + + stringVal = addSymbol(); + token = Token.VARIANT; + } + public void scanComment() { if (!allowComment) { throw new NotAllowCommentException(); @@ -1641,12 +1726,12 @@ public class Lexer { } multmin = negative ? MULTMIN_RADIX_TEN : N_MULTMAX_RADIX_TEN; if (i < max) { - digit = digits[charAt(i++)]; + digit = charAt(i++) - '0'; result = -digit; } while (i < max) { // Accumulating negatively avoids surprises near MAX_VALUE - digit = digits[charAt(i++)]; + digit = charAt(i++) - '0'; if (result < multmin) { return new BigInteger(numberString()); } 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 fc9130774a..5f96eb7263 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java @@ -44,6 +44,7 @@ import com.alibaba.druid.sql.ast.statement.SQLSelectItem; import com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem; import com.alibaba.druid.sql.ast.statement.SQLUnique; import com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem; +import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleArgumentExpr; import com.alibaba.druid.util.FnvHash; import com.alibaba.druid.util.JdbcConstants; @@ -1462,12 +1463,38 @@ public class SQLExprParser extends SQLParser { accept(Token.RPAREN); item.setColumn(list); } else { - item.setColumn(this.primary()); + String identName; + long hash; + + Token token = lexer.token(); + if (token == Token.IDENTIFIER) { + identName = lexer.stringVal(); + hash = lexer.hash_lower(); + } else if (token == Token.LITERAL_CHARS) { + identName = '\'' + lexer.stringVal() + '\''; + hash = 0; + } else { + identName = lexer.stringVal(); + hash = 0; + } + lexer.nextTokenEq(); + SQLExpr expr = new SQLIdentifierExpr(identName, hash); + while (lexer.token() == Token.DOT) { + lexer.nextToken(); + String propertyName = lexer.stringVal(); + lexer.nextTokenEq(); + expr = new SQLPropertyExpr(expr, propertyName); + } + + item.setColumn(expr); } if (lexer.token == Token.COLONEQ) { - lexer.nextToken(); + lexer.nextTokenValue(); + } else if (lexer.token == Token.EQ) { + lexer.nextTokenValue(); } else { - accept(Token.EQ); + throw new ParserException("syntax error, expect EQ, actual " + lexer.token + " " + + lexer.info()); } item.setValue(this.expr()); @@ -1519,28 +1546,28 @@ public class SQLExprParser extends SQLParser { } catch (EOFParserException e) { throw new ParserException("EOF, " + expr + "=", e); } - rightExp = equalityRest(rightExp); + + if (lexer.token == Token.COLONEQ) { + lexer.nextToken(); + SQLExpr colonExpr = expr(); + rightExp = new SQLBinaryOpExpr(rightExp, SQLBinaryOperator.Assignment, colonExpr, dbType); + } expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Equality, rightExp, dbType); - } else if (token == Token.BANGEQ) { + } else if (lexer.token() == Token.EQGT) { + lexer.nextToken(); + rightExp = expr(); + String argumentName = ((SQLIdentifierExpr) expr).getName(); + return new OracleArgumentExpr(argumentName, rightExp); + } else if (token == Token.BANGEQ || token == Token.CARETEQ) { lexer.nextToken(); rightExp = bitOr(); - rightExp = equalityRest(rightExp); - - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.NotEqual, rightExp, getDbType()); - } else if (token == Token.BANG) { - lexer.nextToken(); - accept(Token.EQ); - rightExp = bitOr(); - - rightExp = equalityRest(rightExp); - - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.NotEqual, rightExp, getDbType()); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.NotEqual, rightExp, dbType); } else if (token == Token.COLONEQ) { lexer.nextToken(); rightExp = expr(); - expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Assignment, rightExp, getDbType()); + expr = new SQLBinaryOpExpr(expr, SQLBinaryOperator.Assignment, rightExp, dbType); } return expr; @@ -1562,9 +1589,19 @@ public class SQLExprParser extends SQLParser { return queryExpr; } - exprList(inListExpr.getTargetList(), inListExpr); + List targetList = inListExpr.getTargetList(); + for (;;) { + SQLExpr item = this.expr(); + item.setParent(inListExpr); + targetList.add(item); + if (lexer.token == Token.COMMA) { + lexer.nextTokenValue(); + continue; + } + break; + } + accept(Token.RPAREN); - expr = inListExpr; } else { SQLExpr itemExpr = primary(); itemExpr.setParent(inListExpr); @@ -2632,6 +2669,13 @@ public class SQLExprParser extends SQLParser { String as = lexer.stringVal(); lexer.nextTokenComma(); + + if (lexer.token == Token.DOT) { + lexer.nextToken(); + as += '.' + lexer.stringVal(); + lexer.nextToken(); + } + return new SQLSelectItem(expr, as, connectByRoot); } 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 40e770f801..a15dfa1cc1 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLSelectParser.java @@ -18,8 +18,11 @@ package com.alibaba.druid.sql.parser; import java.util.List; import com.alibaba.druid.sql.ast.*; +import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; +import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr; import com.alibaba.druid.sql.ast.statement.*; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlOrderingExpr; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock; import com.alibaba.druid.util.FnvHash; import com.alibaba.druid.util.JdbcConstants; @@ -317,7 +320,7 @@ public class SQLSelectParser extends SQLParser { } SQLExpr where = expr(); - if (where != null && beforeComments != null) { + if (beforeComments != null) { where.addBeforeComment(beforeComments); } diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java index 372c7645a3..f170f3b2c4 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java @@ -19,12 +19,10 @@ import java.util.ArrayList; import java.util.List; import com.alibaba.druid.sql.ast.*; -import com.alibaba.druid.sql.ast.expr.SQLCharExpr; -import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; -import com.alibaba.druid.sql.ast.expr.SQLQueryExpr; -import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr; +import com.alibaba.druid.sql.ast.expr.*; import com.alibaba.druid.sql.ast.statement.*; import com.alibaba.druid.sql.ast.statement.SQLCreateTriggerStatement.TriggerType; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock; import com.alibaba.druid.sql.dialect.oracle.parser.OracleExprParser; import com.alibaba.druid.util.FnvHash; import com.alibaba.druid.util.JdbcConstants; @@ -77,7 +75,7 @@ public class SQLStatementParser extends SQLParser { } public void parseStatementList(List statementList) { - parseStatementList(statementList, -1); + parseStatementList(statementList, -1, null); } public void parseStatementList(List statementList, int max) { @@ -2430,7 +2428,7 @@ public class SQLStatementParser extends SQLParser { */ public SQLStatement parseStatement( final boolean tryBest) { List list = new ArrayList(); - this.parseStatementList(list, 1); + this.parseStatementList(list, 1, null); if (tryBest) { if (lexer.token != Token.EOF) { throw new ParserException("sql syntax error, no terminated. " + lexer.token); diff --git a/src/main/java/com/alibaba/druid/sql/parser/Token.java b/src/main/java/com/alibaba/druid/sql/parser/Token.java index f040296c0d..7517a76470 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Token.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Token.java @@ -317,7 +317,8 @@ public enum Token { COLON(":"), COLONCOLON("::"), COLONEQ(":="), - EQEQ("=="), + EQEQ("=="), + EQGT("=>"), LTEQ("<="), LTEQGT("<=>"), LTGT("<>"), 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 00e07a0caf..0d55242fbd 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -1041,13 +1041,8 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet } public boolean visit(SQLIdentifierExpr x) { - final String name = x.getName(); - if (!this.parameterized) { - print0(x.getName()); - return false; - } - - return printName(x, name); + print0(x.getName()); + return false; } private boolean printName(SQLName x, String name) { @@ -1535,7 +1530,12 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet if (mapTableName != null) { print0(mapTableName); } else { - printExpr(owner); + if (owner instanceof SQLIdentifierExpr) { + SQLIdentifierExpr ownerIdent = (SQLIdentifierExpr) owner; + printName(ownerIdent, ownerIdent.getName()); + } else { + printExpr(owner); + } } print('.'); @@ -1961,9 +1961,54 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet } if (expr instanceof SQLIdentifierExpr) { - visit((SQLIdentifierExpr) expr); + SQLIdentifierExpr identifierExpr = (SQLIdentifierExpr) expr; + final String name = identifierExpr.getName(); + if (!this.parameterized) { + print0(name); + return; + } + + boolean shardingSupport = this.shardingSupport + && this.parameterized; + + if (shardingSupport) { + String nameUnwrappe = unwrapShardingTable(name); + + if (!name.equals(nameUnwrappe)) { + incrementReplaceCunt(); + } + + print0(nameUnwrappe); + } else { + print0(name); + } } else if (expr instanceof SQLPropertyExpr) { - visit((SQLPropertyExpr) expr); + SQLPropertyExpr propertyExpr = (SQLPropertyExpr) expr; + SQLExpr owner = propertyExpr.getOwner(); + + printTableSourceExpr(owner); + print('.'); + + final String name = propertyExpr.getName(); + if (!this.parameterized) { + print0(propertyExpr.getName()); + return; + } + + boolean shardingSupport = this.shardingSupport + && this.parameterized; + + if (shardingSupport) { + String nameUnwrappe = unwrapShardingTable(name); + + if (!name.equals(nameUnwrappe)) { + incrementReplaceCunt(); + } + + print0(nameUnwrappe); + } else { + print0(name); + } } else { expr.accept(this); } diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java index 8a63c1080d..f9a52ea38d 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitor.java @@ -738,5 +738,8 @@ public interface SQLASTVisitor { boolean visit(SQLBinaryOpExprGroup x); void endVisit(SQLBinaryOpExprGroup x); - // + + boolean visit(SQLScriptCommitStatement astNode); + + void endVisit(SQLScriptCommitStatement astNode); } diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java index 59cc5b7673..2de60ec512 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTVisitorAdapter.java @@ -1689,6 +1689,16 @@ public class SQLASTVisitorAdapter implements SQLASTVisitor { features = VisitorFeature.config(features, feature, state); } + @Override + public boolean visit(SQLScriptCommitStatement x) { + return true; + } + + @Override + public void endVisit(SQLScriptCommitStatement astNode) { + + } + public final boolean isEnabled(VisitorFeature feature) { return VisitorFeature.isEnabled(this.features, feature); } diff --git a/src/main/java/com/alibaba/druid/util/FnvHash.java b/src/main/java/com/alibaba/druid/util/FnvHash.java index 6201e12366..77f47906db 100644 --- a/src/main/java/com/alibaba/druid/util/FnvHash.java +++ b/src/main/java/com/alibaba/druid/util/FnvHash.java @@ -417,6 +417,11 @@ public final class FnvHash { long DEFERRABLE = fnv1a_64_lower("DEFERRABLE"); long AS = fnv1a_64_lower("AS"); + long DELAYED = fnv1a_64_lower("DELAYED"); + long GO = fnv1a_64_lower("GO"); + long WAITFOR = fnv1a_64_lower("WAITFOR"); + long EXEC = fnv1a_64_lower("EXEC"); + long EXECUTE = fnv1a_64_lower("EXECUTE"); long STAR = fnv1a_64_lower("*"); } diff --git a/src/test/java/com/alibaba/druid/benckmark/sql/MySqlParameterizedBenchmark.java b/src/test/java/com/alibaba/druid/benckmark/sql/MySqlParameterizedBenchmark.java index e63d303463..0c76de3950 100644 --- a/src/test/java/com/alibaba/druid/benckmark/sql/MySqlParameterizedBenchmark.java +++ b/src/test/java/com/alibaba/druid/benckmark/sql/MySqlParameterizedBenchmark.java @@ -49,14 +49,22 @@ public class MySqlParameterizedBenchmark extends TestCase { "\tOR batch.batch_name = '')\n" + "ORDER BY batch_gmt_create DESC\n" + "LIMIT 0, 50"; + String sql8 = "select @@session.tx_read_only"; + String sql9 = "insert into seller_item_sku_1967 ( item_id, gmt_modified, gmt_create, sku_id, seller_id, outer_id, status, sync_version, sku_feature) values ( 558323210106, '2017-09-08 10:55:39', '2017-09-08 10:55:39', 3634115182525, 3403773871, '', 1, 0, '{\"sku_order_num\":\"2\"}')"; + String sql10 = "update seller_spu_site_1976 set gmt_modified = NOW(), spu_id = 0, site_id = null, site_en = null, features = null, outer_id = null, auction_status = -2 where ((sellerid = 2027808696) AND (item_id = 552891941272))"; + String sql11 = "select seller_item_sku.item_id,seller_item_sku.gmt_modified,seller_item_sku.gmt_create,seller_item_sku.sku_id,seller_item_sku.seller_id,seller_item_sku.outer_id,seller_item_sku.status,seller_item_sku.sync_version,seller_item_sku.sku_feature from seller_item_sku_2047 seller_item_sku where ((seller_item_sku.item_id = 558182960563) AND (seller_item_sku.seller_id = 673619967) AND (seller_item_sku.sku_id = 3634115286014))"; + String sql12 = "/* 0ba9776a15048393743937000d1936/0//7d21f1f2/ */select `auction_relation`.`id`,`auction_relation`.`item_id`,`auction_relation`.`sku_id`,`auction_relation`.`user_id`,`auction_relation`.`target_id`,`auction_relation`.`extra_id`,`auction_relation`.`type`,`auction_relation`.`target_type`,`auction_relation`.`type_attr`,`auction_relation`.`status`,`auction_relation`.`target_user_id`,`auction_relation`.`options`,`auction_relation`.`features`,`auction_relation`.`version`,`auction_relation`.`sub_type`,`auction_relation`.`gmt_create`,`auction_relation`.`gmt_modified` from `auction_relation_1080` `auction_relation` where ((`auction_relation`.`item_id` = 556887226360) AND (`auction_relation`.`target_Type` IN (1,2,3,4)) AND (`auction_relation`.`status` = 0) AND (`auction_relation`.`type` IN (16,17,6,7,8,9,10,11,12,13,14,15)))"; for (int i = 0; i < 5; ++i) { -// perf(sql); // 6740 6201 4752 4514 4391 4218 4127 4124 + perf(sql); // 6740 6201 4752 4514 4391 4218 4127 4124 // perf(sql2); // 2948 2928 2869 2780 2502 // perf(sql3); // 15093 10392 10416 10154 10007 9126 8907 // perf(sql4); // 4429 4190 4023 3747 -// perf(sql5); // 1917 +// perf(sql5); // 1917 1882 // perf(sql6); // 4193 +// perf(sql8); // 601 585 314 +// perf(sql9); // 2403 2392 2188 2169 +// perf(sql10); // 3163 2866 // perf_parse(sql); // 4643 4377 4345 3801 3627 3228 2961 2959 // perf_parse(sql2); // 1918 1779 1666 1646 @@ -65,6 +73,10 @@ public class MySqlParameterizedBenchmark extends TestCase { // perf_parse(sql5); // 1339 // perf_parse(sql6); // perf_parse(sql7); // 9831 8581 8552 +// perf_parse(sql8); // +// perf_parse(sql10); // 2291 2025 2024 2010 +// perf_parse(sql11); // 3209 +// perf_parse(sql12); // 4873 4767 // perf_lexer(sql4); // 2051 1802 // perf_lexer(sql5); // 1125 1054 @@ -72,7 +84,7 @@ public class MySqlParameterizedBenchmark extends TestCase { // perfParameterized(sql6); // 4224 4083 - perfFormat(sql7); // 14865 14132 13812 13714 12917 +// perfFormat(sql7); // 14865 14132 13812 13714 12917 // perf_hashCode64(sql5); // 181 diff --git a/src/test/java/com/alibaba/druid/benckmark/sql/SqlHolder.java b/src/test/java/com/alibaba/druid/benckmark/sql/SqlHolder.java index 0c97ebebd7..6dc3957fe9 100644 --- a/src/test/java/com/alibaba/druid/benckmark/sql/SqlHolder.java +++ b/src/test/java/com/alibaba/druid/benckmark/sql/SqlHolder.java @@ -2,11 +2,17 @@ package com.alibaba.druid.benckmark.sql; import com.alibaba.druid.sql.SQLUtils; import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; +import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr; +import com.alibaba.druid.sql.ast.statement.SQLSelect; import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock; import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser; import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor; +import com.alibaba.druid.sql.parser.LayoutCharacters; import com.alibaba.druid.sql.parser.ParserException; import com.alibaba.druid.sql.parser.SQLParserFeature; +import com.alibaba.druid.sql.parser.Token; import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor; import com.alibaba.druid.sql.visitor.SchemaStatVisitor; import com.alibaba.druid.stat.TableStat; @@ -56,9 +62,22 @@ public class SqlHolder { if (parsed) { return; } + + if (text.equals("select @@session.tx_read_only")) { + SQLSelect select = new SQLSelect(); + MySqlSelectQueryBlock queryBlock = new MySqlSelectQueryBlock(); + queryBlock.addSelectItem(new SQLPropertyExpr(new SQLVariantRefExpr("@@session"), "tx_read_only")); + select.setQuery(queryBlock); + + ast = new SQLSelectStatement(select); + parsed = true; + return; + } + // ast = SQLUtils.parseStatements(text, dialect).get(0); + SQLParserFeature[] features = {SQLParserFeature.EnableSQLBinaryOpExprGroup, SQLParserFeature.OptimizedForParameterized}; try { - ast = new MySqlStatementParser(text, SQLParserFeature.EnableSQLBinaryOpExprGroup).parseStatement(); + ast = new MySqlStatementParser(text, features).parseStatement(); } catch (ParserException e) { throw new UnsupportedOperationException(e); } @@ -98,6 +117,11 @@ public class SqlHolder { public String parameterize(Set physicalNames, List params) { ensureParsed(); + + if (text.equals("select @@session.tx_read_only")) { + return text; + } + return Templates.parameterize(ast, physicalNames, params); } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_41.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_41.java index 84dff4c67b..ceea0f12d1 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_41.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_41.java @@ -41,7 +41,7 @@ public class MySqlParameterizedOutputVisitorTest_41 extends TestCase { String psql = out.toString(); assertEquals("SELECT *\n" + - "FROM db_00.t\n" + + "FROM db.t\n" + "WHERE id > ?", psql); String params_json = JSONArray.toJSONString(parameters, SerializerFeature.WriteClassName); System.out.println(params_json); @@ -51,7 +51,7 @@ public class MySqlParameterizedOutputVisitorTest_41 extends TestCase { String rsql = SQLUtils.toSQLString(SQLUtils.parseStatements(psql, dbType), dbType, jsonArray); assertEquals("SELECT *\n" + - "FROM db_00.t\n" + + "FROM db.t\n" + "WHERE id > 1", rsql); } } diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_46.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_46.java index 7412cb6aed..18108436f8 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_46.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_46.java @@ -44,77 +44,77 @@ public class MySqlParameterizedOutputVisitorTest_46 extends TestCase { assertEquals("SELECT COUNT(*) AS count, `ipv_uv_1d_001` AS col\n" + "FROM (\n" + "\t(SELECT ipv_uv_1d_001\n" + - "\tFROM `cbu_da_dihu_16`.ads_tb_sycm_eff_slr_itm_1d_s015_p\n" + + "\tFROM cbu_da_dihu.ads_tb_sycm_eff_slr_itm_1d_s015_p\n" + "\tWHERE `auto_seq_id` > ?\n" + "\tLIMIT ?)\n" + "\tUNION ALL\n" + "\t(SELECT ipv_uv_1d_001\n" + - "\tFROM `cbu_da_dihu_16`.ads_tb_sycm_eff_slr_itm_1d_s015_p\n" + + "\tFROM cbu_da_dihu.ads_tb_sycm_eff_slr_itm_1d_s015_p\n" + "\tWHERE `auto_seq_id` > ?\n" + "\tLIMIT ?)\n" + "\tUNION ALL\n" + "\t(SELECT ipv_uv_1d_001\n" + - "\tFROM `cbu_da_dihu_16`.ads_tb_sycm_eff_slr_itm_1d_s015_p\n" + + "\tFROM cbu_da_dihu.ads_tb_sycm_eff_slr_itm_1d_s015_p\n" + "\tWHERE `auto_seq_id` > ?\n" + "\tLIMIT ?)\n" + "\tUNION ALL\n" + "\t(SELECT ipv_uv_1d_001\n" + - "\tFROM `cbu_da_dihu_16`.ads_tb_sycm_eff_slr_itm_1d_s015_p\n" + + "\tFROM cbu_da_dihu.ads_tb_sycm_eff_slr_itm_1d_s015_p\n" + "\tWHERE `auto_seq_id` > ?\n" + "\tLIMIT ?)\n" + "\tUNION ALL\n" + "\t(SELECT ipv_uv_1d_001\n" + - "\tFROM `cbu_da_dihu_16`.ads_tb_sycm_eff_slr_itm_1d_s015_p\n" + + "\tFROM cbu_da_dihu.ads_tb_sycm_eff_slr_itm_1d_s015_p\n" + "\tWHERE `auto_seq_id` > ?\n" + "\tLIMIT ?)\n" + "\tUNION ALL\n" + "\t(SELECT ipv_uv_1d_001\n" + - "\tFROM `cbu_da_dihu_16`.ads_tb_sycm_eff_slr_itm_1d_s015_p\n" + + "\tFROM cbu_da_dihu.ads_tb_sycm_eff_slr_itm_1d_s015_p\n" + "\tWHERE `auto_seq_id` > ?\n" + "\tLIMIT ?)\n" + "\tUNION ALL\n" + "\t(SELECT ipv_uv_1d_001\n" + - "\tFROM `cbu_da_dihu_16`.ads_tb_sycm_eff_slr_itm_1d_s015_p\n" + + "\tFROM cbu_da_dihu.ads_tb_sycm_eff_slr_itm_1d_s015_p\n" + "\tWHERE `auto_seq_id` > ?\n" + "\tLIMIT ?)\n" + "\tUNION ALL\n" + "\t(SELECT ipv_uv_1d_001\n" + - "\tFROM `cbu_da_dihu_16`.ads_tb_sycm_eff_slr_itm_1d_s015_p\n" + + "\tFROM cbu_da_dihu.ads_tb_sycm_eff_slr_itm_1d_s015_p\n" + "\tWHERE `auto_seq_id` > ?\n" + "\tLIMIT ?)\n" + "\tUNION ALL\n" + "\t(SELECT ipv_uv_1d_001\n" + - "\tFROM `cbu_da_dihu_16`.ads_tb_sycm_eff_slr_itm_1d_s015_p\n" + + "\tFROM cbu_da_dihu.ads_tb_sycm_eff_slr_itm_1d_s015_p\n" + "\tWHERE `auto_seq_id` > ?\n" + "\tLIMIT ?)\n" + "\tUNION ALL\n" + "\t(SELECT ipv_uv_1d_001\n" + - "\tFROM `cbu_da_dihu_16`.ads_tb_sycm_eff_slr_itm_1d_s015_p\n" + + "\tFROM cbu_da_dihu.ads_tb_sycm_eff_slr_itm_1d_s015_p\n" + "\tWHERE `auto_seq_id` > ?\n" + "\tLIMIT ?)\n" + "\tUNION ALL\n" + "\t(SELECT ipv_uv_1d_001\n" + - "\tFROM `cbu_da_dihu_16`.ads_tb_sycm_eff_slr_itm_1d_s015_p\n" + + "\tFROM cbu_da_dihu.ads_tb_sycm_eff_slr_itm_1d_s015_p\n" + "\tWHERE `auto_seq_id` > ?\n" + "\tLIMIT ?)\n" + "\tUNION ALL\n" + "\t(SELECT ipv_uv_1d_001\n" + - "\tFROM `cbu_da_dihu_16`.ads_tb_sycm_eff_slr_itm_1d_s015_p\n" + + "\tFROM cbu_da_dihu.ads_tb_sycm_eff_slr_itm_1d_s015_p\n" + "\tWHERE `auto_seq_id` > ?\n" + "\tLIMIT ?)\n" + "\tUNION ALL\n" + "\t(SELECT ipv_uv_1d_001\n" + - "\tFROM `cbu_da_dihu_16`.ads_tb_sycm_eff_slr_itm_1d_s015_p\n" + + "\tFROM cbu_da_dihu.ads_tb_sycm_eff_slr_itm_1d_s015_p\n" + "\tWHERE `auto_seq_id` > ?\n" + "\tLIMIT ?)\n" + "\tUNION ALL\n" + "\t(SELECT ipv_uv_1d_001\n" + - "\tFROM `cbu_da_dihu_16`.ads_tb_sycm_eff_slr_itm_1d_s015_p\n" + + "\tFROM cbu_da_dihu.ads_tb_sycm_eff_slr_itm_1d_s015_p\n" + "\tWHERE `auto_seq_id` > ?\n" + "\tLIMIT ?)\n" + "\tUNION ALL\n" + "\t(SELECT ipv_uv_1d_001\n" + - "\tFROM `cbu_da_dihu_16`.ads_tb_sycm_eff_slr_itm_1d_s015_p\n" + + "\tFROM cbu_da_dihu.ads_tb_sycm_eff_slr_itm_1d_s015_p\n" + "\tWHERE `auto_seq_id` > ?\n" + "\tLIMIT ?)\n" + ") ads_tb_sycm_eff_slr_itm_1d_s015_p033\n" + diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_51_schema.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_51_schema.java new file mode 100644 index 0000000000..a4f85a39b5 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/param/MySqlParameterizedOutputVisitorTest_51_schema.java @@ -0,0 +1,48 @@ +package com.alibaba.druid.bvt.sql.mysql.param; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.parser.SQLParserUtils; +import com.alibaba.druid.sql.parser.SQLStatementParser; +import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor; +import com.alibaba.druid.util.JdbcConstants; +import junit.framework.TestCase; + +import java.util.ArrayList; +import java.util.List; + +/** + * Created by wenshao on 16/8/23. + */ +public class MySqlParameterizedOutputVisitorTest_51_schema extends TestCase { + public void test_for_parameterize() throws Exception { + final String dbType = JdbcConstants.MYSQL; + String sql = "UPDATE `galicdb_0102`.auction_auctions_0201 SET `starts` = ?, `pict_url` = ?, `category` = ?, `minimum_bid` = ?, `reserve_price` = ?, `city` = ?, `prov` = ?, `ends` = ?, `current_bid` = NULL, `quantity` = ?, `zoo` = ?, `secure_trade_ordinary_post_fee` = ?, `secure_trade_fast_post_fee` = ?, `old_quantity` = ?, `options` = ?, `secure_trade_ems_post_fee` = ?, `property` = ?, `last_modified` = ?, `desc_path` = ?, `postage_id` = ?, `shop_categories_id_lists` = ?, `spu_id` = ?, `sync_version` = ?, `auction_status` = ?, `features` = ?, `feature_cc` = ?, `main_color` = ?, `outer_id` = ?, `auction_sub_status` = ?, `commodity_id` = ? WHERE `auction_id` = ?"; + + SQLStatementParser parser = SQLParserUtils.createSQLStatementParser(sql, dbType); + List stmtList = parser.parseStatementList(); + SQLStatement statement = stmtList.get(0); + + StringBuilder out = new StringBuilder(); + SQLASTOutputVisitor visitor = SQLUtils.createOutputVisitor(out, JdbcConstants.MYSQL); + List parameters = new ArrayList(); + visitor.setParameterized(true); + visitor.setParameterizedMergeInList(true); + visitor.setParameters(parameters); + /*visitor.setPrettyFormat(false);*/ + statement.accept(visitor); + /* JSONArray array = new JSONArray(); + for(String table : visitor.getTables()){ + array.add(table.replaceAll("`","")); + }*/ + + String psql = out.toString(); + + System.out.println(psql); + + + assertEquals("UPDATE galicdb.auction_auctions\n" + + "SET `starts` = ?, `pict_url` = ?, `category` = ?, `minimum_bid` = ?, `reserve_price` = ?, `city` = ?, `prov` = ?, `ends` = ?, `current_bid` = NULL, `quantity` = ?, `zoo` = ?, `secure_trade_ordinary_post_fee` = ?, `secure_trade_fast_post_fee` = ?, `old_quantity` = ?, `options` = ?, `secure_trade_ems_post_fee` = ?, `property` = ?, `last_modified` = ?, `desc_path` = ?, `postage_id` = ?, `shop_categories_id_lists` = ?, `spu_id` = ?, `sync_version` = ?, `auction_status` = ?, `features` = ?, `feature_cc` = ?, `main_color` = ?, `outer_id` = ?, `auction_sub_status` = ?, `commodity_id` = ?\n" + + "WHERE `auction_id` = ?", psql); + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlSelectTest_58_alias_dot.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlSelectTest_58_alias_dot.java new file mode 100644 index 0000000000..eea9591f10 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlSelectTest_58_alias_dot.java @@ -0,0 +1,100 @@ +/* + * Copyright 1999-2017 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.select; + +import com.alibaba.druid.sql.MysqlTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.visitor.SchemaStatVisitor; +import com.alibaba.druid.util.JdbcConstants; + +import java.util.List; + +public class MySqlSelectTest_58_alias_dot extends MysqlTest { + + public void test_0() throws Exception { + String sql = "SELECT m.*, m.icon AS micon, md.uid as md.uid, md.lastmsg,md.postnum,md.rvrc,md.money,md.credit,md.currency,md.lastvisit,md.thisvisit,md.onlinetime,md.lastpost,md.todaypost, md.monthpost,md.onlineip,md.uploadtime,md.uploadnum,md.starttime,md.pwdctime,md.monoltime,md.digests,md.f_num,md.creditpop, md.jobnum,md.lastgrab,md.follows,md.fans,md.newfans,md.newreferto,md.newcomment,md.postcheck,md.punch, mi.customdata " + + "FROM pw_members m LEFT JOIN pw_memberdata md ON m.uid=md.uid LEFT JOIN pw_memberinfo mi ON mi.uid=m.uid WHERE m.uid IN (?)"; + + System.out.println(sql); + + + List statementList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL, true); + SQLStatement stmt = statementList.get(0); + + assertEquals(1, statementList.size()); + + SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.MYSQL); + stmt.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()); + +// assertEquals(1, visitor.getTables().size()); +// assertEquals(1, visitor.getColumns().size()); +// assertEquals(0, visitor.getConditions().size()); +// assertEquals(0, visitor.getOrderByColumns().size()); + + { + String output = SQLUtils.toMySqlString(stmt); + assertEquals("SELECT m.*, m.icon AS micon, md.uid AS md.uid, md.lastmsg, md.postnum\n" + + "\t, md.rvrc, md.money, md.credit, md.currency, md.lastvisit\n" + + "\t, md.thisvisit, md.onlinetime, md.lastpost, md.todaypost, md.monthpost\n" + + "\t, md.onlineip, md.uploadtime, md.uploadnum, md.starttime, md.pwdctime\n" + + "\t, md.monoltime, md.digests, md.f_num, md.creditpop, md.jobnum\n" + + "\t, md.lastgrab, md.follows, md.fans, md.newfans, md.newreferto\n" + + "\t, md.newcomment, md.postcheck, md.punch, mi.customdata\n" + + "FROM pw_members m\n" + + "\tLEFT JOIN pw_memberdata md ON m.uid = md.uid\n" + + "\tLEFT JOIN pw_memberinfo mi ON mi.uid = m.uid\n" + + "WHERE m.uid IN (?)", // + output); + } + { + String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION); + assertEquals("select m.*, m.icon as micon, md.uid as md.uid, md.lastmsg, md.postnum\n" + + "\t, md.rvrc, md.money, md.credit, md.currency, md.lastvisit\n" + + "\t, md.thisvisit, md.onlinetime, md.lastpost, md.todaypost, md.monthpost\n" + + "\t, md.onlineip, md.uploadtime, md.uploadnum, md.starttime, md.pwdctime\n" + + "\t, md.monoltime, md.digests, md.f_num, md.creditpop, md.jobnum\n" + + "\t, md.lastgrab, md.follows, md.fans, md.newfans, md.newreferto\n" + + "\t, md.newcomment, md.postcheck, md.punch, mi.customdata\n" + + "from pw_members m\n" + + "\tleft join pw_memberdata md on m.uid = md.uid\n" + + "\tleft join pw_memberinfo mi on mi.uid = m.uid\n" + + "where m.uid in (?)", // + output); + } + + { + String output = SQLUtils.toMySqlString(stmt, new SQLUtils.FormatOption(true, true, true)); + assertEquals("SELECT m.*, m.icon AS micon, md.uid AS md.uid, md.lastmsg, md.postnum\n" + + "\t, md.rvrc, md.money, md.credit, md.currency, md.lastvisit\n" + + "\t, md.thisvisit, md.onlinetime, md.lastpost, md.todaypost, md.monthpost\n" + + "\t, md.onlineip, md.uploadtime, md.uploadnum, md.starttime, md.pwdctime\n" + + "\t, md.monoltime, md.digests, md.f_num, md.creditpop, md.jobnum\n" + + "\t, md.lastgrab, md.follows, md.fans, md.newfans, md.newreferto\n" + + "\t, md.newcomment, md.postcheck, md.punch, mi.customdata\n" + + "FROM pw_members m\n" + + "\tLEFT JOIN pw_memberdata md ON m.uid = md.uid\n" + + "\tLEFT JOIN pw_memberinfo mi ON mi.uid = m.uid\n" + + "WHERE m.uid IN (?)", // + output); + } + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlSelectTest_59_neq.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlSelectTest_59_neq.java new file mode 100644 index 0000000000..2925a4a7cf --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/select/MySqlSelectTest_59_neq.java @@ -0,0 +1,75 @@ +/* + * Copyright 1999-2017 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.select; + +import com.alibaba.druid.sql.MysqlTest; +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.visitor.SchemaStatVisitor; +import com.alibaba.druid.util.JdbcConstants; + +import java.util.List; + +public class MySqlSelectTest_59_neq extends MysqlTest { + + public void test_0() throws Exception { + String sql = "SELECT * from t where t ! = 1"; + + System.out.println(sql); + + + List statementList = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL, true); + SQLStatement stmt = statementList.get(0); + + assertEquals(1, statementList.size()); + + SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.MYSQL); + stmt.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()); + +// assertEquals(1, visitor.getTables().size()); +// assertEquals(1, visitor.getColumns().size()); +// assertEquals(0, visitor.getConditions().size()); +// assertEquals(0, visitor.getOrderByColumns().size()); + + { + String output = SQLUtils.toMySqlString(stmt); + assertEquals("SELECT *\n" + + "FROM t\n" + + "WHERE t != 1", // + output); + } + { + String output = SQLUtils.toMySqlString(stmt, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION); + assertEquals("select *\n" + + "from t\n" + + "where t != 1", // + output); + } + + { + String output = SQLUtils.toMySqlString(stmt, new SQLUtils.FormatOption(true, true, true)); + assertEquals("SELECT *\n" + + "FROM t\n" + + "WHERE t != ?", // + output); + } + } +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/oracle/visitor/OracleASTVisitorAdapterTest.java b/src/test/java/com/alibaba/druid/bvt/sql/oracle/visitor/OracleASTVisitorAdapterTest.java index 2dd68897e0..cf35ff01bf 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/oracle/visitor/OracleASTVisitorAdapterTest.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/oracle/visitor/OracleASTVisitorAdapterTest.java @@ -70,7 +70,7 @@ import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement.ConditionalInsertClause; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement.ConditionalInsertClauseItem; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleMultiInsertStatement.InsertIntoClause; -import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OraclePLSQLCommitStatement; +import com.alibaba.druid.sql.ast.statement.SQLScriptCommitStatement; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OraclePrimaryKey; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectPivot; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleSelectQueryBlock; @@ -89,7 +89,7 @@ public class OracleASTVisitorAdapterTest extends TestCase { public void test_adapter() throws Exception { OracleASTVisitorAdapter adapter = new OracleASTVisitorAdapter(); - new OraclePLSQLCommitStatement().accept(adapter); + new SQLScriptCommitStatement().accept(adapter); new OracleAnalytic().accept(adapter); new OracleAnalyticWindowing().accept(adapter); new SQLDateExpr().accept(adapter); diff --git a/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerSelectTest26.java b/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerSelectTest26.java new file mode 100644 index 0000000000..ffe57509c5 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerSelectTest26.java @@ -0,0 +1,74 @@ +/* + * Copyright 1999-2017 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.sqlserver; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.sqlserver.parser.SQLServerStatementParser; +import com.alibaba.druid.sql.parser.SQLStatementParser; +import com.alibaba.druid.util.JdbcConstants; +import junit.framework.TestCase; +import org.junit.Assert; + +import java.util.List; + +public class SQLServerSelectTest26 extends TestCase { + + public void test_simple() throws Exception { + String sql = // + "-- ----------------------------\n" + + "-- Table structure for Adode\n" + + "-- ----------------------------\n" + + "DROP TABLE [dbo].[Adode]\n" + + "GO\n" + + "CREATE TABLE [dbo].[Adode] (\n" + + "[Ad_Work_Start_Time] varchar(255) NULL,\n" + + "[Ad_Work_Stop_Time] varchar(255) NULL,\n" + + "[Ad_Wait_Start_Time] varchar(255) NULL,\n" + + "[Ad_Wait_Stop_Time] varchar(255) NULL,\n" + + "[Order_ID] varchar(255) NOT NULL\n" + + ")"; // + + List stmtList = SQLUtils.parseStatements(sql, JdbcConstants.SQL_SERVER); + + { + String text = SQLUtils.toSQLString(stmtList, JdbcConstants.SQL_SERVER); + + Assert.assertEquals("DROP TABLE [dbo].[Adode]\n" + + "GO\n" + + "CREATE TABLE [dbo].[Adode] (\n" + + "\t[Ad_Work_Start_Time] varchar(255) NULL,\n" + + "\t[Ad_Work_Stop_Time] varchar(255) NULL,\n" + + "\t[Ad_Wait_Start_Time] varchar(255) NULL,\n" + + "\t[Ad_Wait_Stop_Time] varchar(255) NULL,\n" + + "\t[Order_ID] varchar(255) NOT NULL\n" + + ")", text); + } + { + String text = SQLUtils.toSQLString(stmtList, JdbcConstants.SQL_SERVER, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION); + + Assert.assertEquals("drop table [dbo].[Adode]\n" + + "go\n" + + "create table [dbo].[Adode] (\n" + + "\t[Ad_Work_Start_Time] varchar(255) null,\n" + + "\t[Ad_Work_Stop_Time] varchar(255) null,\n" + + "\t[Ad_Wait_Start_Time] varchar(255) null,\n" + + "\t[Ad_Wait_Stop_Time] varchar(255) null,\n" + + "\t[Order_ID] varchar(255) not null\n" + + ")", text); + } + } +}