diff --git a/src/main/java/com/alibaba/druid/sql/ast/SQLName.java b/src/main/java/com/alibaba/druid/sql/ast/SQLName.java index 7a317a28ec..c31c094fb2 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/SQLName.java +++ b/src/main/java/com/alibaba/druid/sql/ast/SQLName.java @@ -16,5 +16,5 @@ package com.alibaba.druid.sql.ast; public interface SQLName extends SQLExpr { - + String getSimleName(); } diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLIdentifierExpr.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLIdentifierExpr.java index 7d48d1df17..887b9145f4 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLIdentifierExpr.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLIdentifierExpr.java @@ -33,6 +33,10 @@ public class SQLIdentifierExpr extends SQLExprImpl implements SQLName { this.name = name; } + + public String getSimleName() { + return name; + } public String getName() { return this.name; diff --git a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLPropertyExpr.java b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLPropertyExpr.java index cc70848a9f..baee099885 100644 --- a/src/main/java/com/alibaba/druid/sql/ast/expr/SQLPropertyExpr.java +++ b/src/main/java/com/alibaba/druid/sql/ast/expr/SQLPropertyExpr.java @@ -36,6 +36,10 @@ public class SQLPropertyExpr extends SQLExprImpl implements SQLName { public SQLPropertyExpr(){ } + + public String getSimleName() { + return name; + } public SQLExpr getOwner() { return this.owner; 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 7d6fc7b9e6..904de5f75e 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 @@ -57,7 +57,6 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowWarningsStatem import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlStartTransactionStatement; import com.alibaba.druid.sql.parser.Lexer; import com.alibaba.druid.sql.parser.ParserException; -import com.alibaba.druid.sql.parser.SQLExprParser; import com.alibaba.druid.sql.parser.SQLSelectParser; import com.alibaba.druid.sql.parser.SQLStatementParser; import com.alibaba.druid.sql.parser.Token; @@ -67,16 +66,12 @@ public class MySqlStatementParser extends SQLStatementParser { public MySqlStatementParser(String sql) throws ParserException{ this(new MySqlLexer(sql)); this.lexer.nextToken(); - this.exprParser = this.createExprParser(); + this.exprParser = new MySqlExprParser(lexer); } public MySqlStatementParser(Lexer lexer){ super(lexer); - this.exprParser = this.createExprParser(); - } - - protected SQLExprParser createExprParser() { - return new MySqlExprParser(lexer); + this.exprParser = new MySqlExprParser(lexer); } public SQLCreateTableStatement parseCreateTable() throws ParserException { @@ -179,11 +174,11 @@ public class MySqlStatementParser extends SQLStatementParser { for (;;) { MySqlCreateUserStatement.UserSpecification userSpec = new MySqlCreateUserStatement.UserSpecification(); - SQLCharExpr expr = (SQLCharExpr) this.createExprParser().expr(); + SQLCharExpr expr = (SQLCharExpr) exprParser.expr(); String user = expr.toString(); if (lexer.token() == Token.VARIANT) { lexer.nextToken(); - SQLCharExpr expr2 = (SQLCharExpr) this.createExprParser().expr(); + SQLCharExpr expr2 = (SQLCharExpr) exprParser.expr(); user += '@'; user += expr2.toString(); } @@ -198,12 +193,12 @@ public class MySqlStatementParser extends SQLStatementParser { lexer.nextToken(); } - SQLCharExpr password = (SQLCharExpr) this.createExprParser().expr(); + SQLCharExpr password = (SQLCharExpr) this.exprParser.expr(); userSpec.setPassword(password); } else if (lexer.token() == Token.WITH) { lexer.nextToken(); - SQLCharExpr text = (SQLCharExpr) this.createExprParser().expr(); + SQLCharExpr text = (SQLCharExpr) this.exprParser.expr(); userSpec.setAuthPlugin(text); } } @@ -346,7 +341,7 @@ public class MySqlStatementParser extends SQLStatementParser { statementList.add(stmt); return true; } - + if (identifierEquals("DESCRIBE")) { SQLStatement stmt = parseDescribe(); statementList.add(stmt); @@ -355,13 +350,13 @@ public class MySqlStatementParser extends SQLStatementParser { return false; } - + public SQLStatement parseDescribe() throws ParserException { acceptIdentifier("DESCRIBE"); - + MySqlDescribeStatement stmt = new MySqlDescribeStatement(); stmt.setObject(this.exprParser.name()); - + return stmt; } @@ -487,15 +482,15 @@ public class MySqlStatementParser extends SQLStatementParser { MySqlSelectQueryBlock.Limit limit = new MySqlSelectQueryBlock.Limit(); - SQLExpr temp = this.createExprParser().expr(); + SQLExpr temp = this.exprParser.expr(); if (lexer.token() == (Token.COMMA)) { limit.setOffset(temp); lexer.nextToken(); - limit.setRowCount(createExprParser().expr()); + limit.setRowCount(exprParser.expr()); } else if (identifierEquals("OFFSET")) { limit.setRowCount(temp); lexer.nextToken(); - limit.setOffset(createExprParser().expr()); + limit.setOffset(exprParser.expr()); } else { limit.setRowCount(temp); } @@ -991,11 +986,11 @@ public class MySqlStatementParser extends SQLStatementParser { MySqlDropUser stmt = new MySqlDropUser(); for (;;) { - SQLCharExpr expr = (SQLCharExpr) this.createExprParser().expr(); + SQLCharExpr expr = (SQLCharExpr) this.exprParser.expr(); String user = expr.toString(); if (lexer.token() == Token.VARIANT) { lexer.nextToken(); - SQLCharExpr expr2 = (SQLCharExpr) this.createExprParser().expr(); + SQLCharExpr expr2 = (SQLCharExpr) this.exprParser.expr(); user += '@'; user += expr2.toString(); } @@ -1035,7 +1030,7 @@ public class MySqlStatementParser extends SQLStatementParser { } return stmt; } - + public SQLSelectParser createSQLSelectParser() { return new MySqlSelectParser(this.lexer); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleDbLinkExpr.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleDbLinkExpr.java index 69d7768318..9ccc8911a6 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleDbLinkExpr.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/ast/expr/OracleDbLinkExpr.java @@ -30,6 +30,10 @@ public class OracleDbLinkExpr extends SQLExprImpl implements SQLName, OracleExpr public OracleDbLinkExpr(){ } + + public String getSimleName() { + return dbLink; + } public SQLExpr getExpr() { return this.expr; 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 57dbe2e6b0..38effee89c 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 @@ -102,16 +102,21 @@ public class OracleStatementParser extends SQLStatementParser { public OracleStatementParser(String sql){ super(new OracleLexer(sql)); this.lexer.nextToken(); - this.exprParser = createExprParser(); + this.exprParser = new OracleExprParser(lexer); } public OracleStatementParser(Lexer lexer){ super(lexer); - this.exprParser = createExprParser(); + this.exprParser = new OracleExprParser(lexer); } - protected OracleExprParser createExprParser() { - return new OracleExprParser(lexer); + @Override + public OracleExprParser getExprParser() { + return (OracleExprParser) exprParser; + } + + public void parseHints(List hints) { + this.getExprParser().parseHints(hints); } public OracleCreateTableParser getSQLCreateTableParser() { @@ -121,10 +126,10 @@ public class OracleStatementParser extends SQLStatementParser { protected void parseInsert0_hinits(SQLInsertInto insertStatement) { if (insertStatement instanceof OracleInsertStatement) { OracleInsertStatement stmt = (OracleInsertStatement) insertStatement; - this.createExprParser().parseHints(stmt.getHints()); + this.getExprParser().parseHints(stmt.getHints()); } else { List hints = new ArrayList(); - this.createExprParser().parseHints(hints); + this.getExprParser().parseHints(hints); } } @@ -1124,8 +1129,7 @@ public class OracleStatementParser extends SQLStatementParser { OracleMergeStatement stmt = new OracleMergeStatement(); - OracleExprParser exprParser = this.createExprParser(); - exprParser.parseHints(stmt.getHints()); + parseHints(stmt.getHints()); accept(Token.INTO); stmt.setInto(exprParser.name()); @@ -1241,7 +1245,7 @@ public class OracleStatementParser extends SQLStatementParser { List hints = new ArrayList(); - this.createExprParser().parseHints(hints); + parseHints(hints); if (lexer.token() == Token.INTO) { OracleInsertStatement stmt = new OracleInsertStatement(); @@ -1290,7 +1294,7 @@ public class OracleStatementParser extends SQLStatementParser { OracleMultiInsertStatement.ConditionalInsertClauseItem item = new OracleMultiInsertStatement.ConditionalInsertClauseItem(); - item.setWhen(this.createExprParser().expr()); + item.setWhen(this.exprParser.expr()); accept(Token.THEN); OracleMultiInsertStatement.InsertIntoClause insertInto = new OracleMultiInsertStatement.InsertIntoClause(); parseInsert0(insertInto); @@ -1430,7 +1434,7 @@ public class OracleStatementParser extends SQLStatementParser { if (lexer.token() == Token.DELETE) { lexer.nextToken(); - this.createExprParser().parseHints(deleteStatement.getHints()); + parseHints(deleteStatement.getHints()); if (lexer.token() == (Token.FROM)) { lexer.nextToken(); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleUpdateParser.java b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleUpdateParser.java index 9c7d998ab9..3710accd1f 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleUpdateParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/oracle/parser/OracleUpdateParser.java @@ -22,18 +22,20 @@ import com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem; import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleUpdateStatement; import com.alibaba.druid.sql.parser.Lexer; import com.alibaba.druid.sql.parser.ParserException; -import com.alibaba.druid.sql.parser.SQLExprParser; import com.alibaba.druid.sql.parser.SQLStatementParser; import com.alibaba.druid.sql.parser.Token; public class OracleUpdateParser extends SQLStatementParser { public OracleUpdateParser(String sql) throws ParserException{ - super(sql); + super(new OracleLexer(sql)); + this.lexer.nextToken(); + this.exprParser = new OracleExprParser(lexer); } public OracleUpdateParser(Lexer lexer){ super(lexer); + this.exprParser = new OracleExprParser(lexer); } public OracleUpdateStatement parseUpdateStatement() throws ParserException { @@ -142,8 +144,4 @@ public class OracleUpdateParser extends SQLStatementParser { lexer.nextToken(); } } - - protected SQLExprParser createExprParser() { - return new OracleExprParser(lexer); - } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSQLStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSQLStatementParser.java index df650ddb94..9c058446cb 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSQLStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/postgresql/parser/PGSQLStatementParser.java @@ -124,7 +124,7 @@ public class PGSQLStatementParser extends SQLStatementParser { break; } } else if (lexer.token() == (Token.SELECT)) { - SQLQueryExpr queryExpr = (SQLQueryExpr) this.createExprParser().expr(); + SQLQueryExpr queryExpr = (SQLQueryExpr) this.exprParser.expr(); stmt.setQuery(queryExpr.getSubQuery()); } @@ -155,7 +155,7 @@ public class PGSQLStatementParser extends SQLStatementParser { if (lexer.token() == Token.USING) { lexer.nextToken(); for (;;) { - SQLName name = this.createExprParser().name(); + SQLName name = this.exprParser.name(); deleteStatement.getUsing().add(name); if (lexer.token() == Token.COMMA) { lexer.nextToken(); @@ -271,13 +271,13 @@ public class PGSQLStatementParser extends SQLStatementParser { private PGWithQuery withQuery() { PGWithQuery withQuery = new PGWithQuery(); - withQuery.setName(this.createExprParser().expr()); + withQuery.setName(this.exprParser.expr()); if (lexer.token() == Token.LPAREN) { lexer.nextToken(); for (;;) { - SQLExpr expr = this.createExprParser().expr(); + SQLExpr expr = this.exprParser.expr(); withQuery.getColumns().add(expr); if (lexer.token() == Token.COMMA) { lexer.nextToken(); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/expr/SQLServerExpr.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/expr/SQLServerExpr.java new file mode 100644 index 0000000000..9811450707 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/expr/SQLServerExpr.java @@ -0,0 +1,8 @@ +package com.alibaba.druid.sql.dialect.sqlserver.ast.expr; + +import com.alibaba.druid.sql.ast.SQLExpr; + + +public interface SQLServerExpr extends SQLExpr { + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/expr/SQLServerObjectReferenceExpr.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/expr/SQLServerObjectReferenceExpr.java new file mode 100644 index 0000000000..62114e7e27 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/expr/SQLServerObjectReferenceExpr.java @@ -0,0 +1,103 @@ +package com.alibaba.druid.sql.dialect.sqlserver.ast.expr; + +import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.ast.SQLName; +import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr; +import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; +import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerObjectImpl; +import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitor; + +public class SQLServerObjectReferenceExpr extends SQLServerObjectImpl implements SQLServerExpr, SQLName { + + private static final long serialVersionUID = 1L; + + private String server; + private String database; + private String schema; + + public SQLServerObjectReferenceExpr(){ + + } + + public SQLServerObjectReferenceExpr(SQLExpr owner){ + if (owner instanceof SQLIdentifierExpr) { + this.database = ((SQLIdentifierExpr) owner).getName(); + } else if (owner instanceof SQLPropertyExpr) { + SQLPropertyExpr propExpr = (SQLPropertyExpr) owner; + + this.server = ((SQLIdentifierExpr) propExpr.getOwner()).getName(); + this.database = propExpr.getName(); + } else { + throw new IllegalArgumentException(owner.toString()); + } + } + + public String getSimleName() { + if (schema != null) { + return schema; + } + + if (database != null) { + return database; + } + return server; + } + + @Override + public void accept0(SQLServerASTVisitor visitor) { + if (visitor.visit(this)) { + + } + visitor.endVisit(this); + } + + public void output(StringBuffer buf) { + boolean flag = false; + if (server != null) { + buf.append(server); + flag = true; + } + + if (flag) { + buf.append('.'); + } + if (database != null) { + buf.append(database); + flag = true; + } + + if (flag) { + buf.append('.'); + } + + if (schema != null) { + buf.append(schema); + flag = true; + } + } + + public String getServer() { + return server; + } + + public void setServer(String server) { + this.server = server; + } + + public String getDatabase() { + return database; + } + + public void setDatabase(String database) { + this.database = database; + } + + public String getSchema() { + return schema; + } + + public void setSchema(String schema) { + this.schema = schema; + } + +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerExprParser.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerExprParser.java new file mode 100644 index 0000000000..cf5a73e272 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerExprParser.java @@ -0,0 +1,43 @@ +package com.alibaba.druid.sql.dialect.sqlserver.parser; + +import com.alibaba.druid.sql.ast.SQLExpr; +import com.alibaba.druid.sql.ast.SQLName; +import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr; +import com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr; +import com.alibaba.druid.sql.parser.Lexer; +import com.alibaba.druid.sql.parser.ParserException; +import com.alibaba.druid.sql.parser.SQLExprParser; +import com.alibaba.druid.sql.parser.Token; + +public class SQLServerExprParser extends SQLExprParser { + + public SQLServerExprParser(Lexer lexer){ + super(lexer); + } + + public SQLServerExprParser(String sql) throws ParserException{ + super(new SQLServerLexer(sql)); + this.lexer.nextToken(); + } + + public SQLExpr primaryRest(SQLExpr expr) throws ParserException { + if (lexer.token() == Token.DOTDOT) { + expr = nameRest((SQLName) expr); + } + + return super.primaryRest(expr); + } + + public SQLName nameRest(SQLName expr) throws ParserException { + if (lexer.token() == Token.DOTDOT) { + lexer.nextToken(); + String text = lexer.stringVal(); + lexer.nextToken(); + + SQLServerObjectReferenceExpr owner = new SQLServerObjectReferenceExpr(expr); + expr = new SQLPropertyExpr(owner, text); + } + + return super.nameRest(expr); + } +} diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerSelectParser.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerSelectParser.java index d88a79ec49..c3cd4d58bb 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerSelectParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerSelectParser.java @@ -8,6 +8,7 @@ import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock; import com.alibaba.druid.sql.dialect.sqlserver.ast.Top; import com.alibaba.druid.sql.parser.Lexer; import com.alibaba.druid.sql.parser.ParserException; +import com.alibaba.druid.sql.parser.SQLExprParser; import com.alibaba.druid.sql.parser.SQLSelectParser; import com.alibaba.druid.sql.parser.Token; @@ -76,4 +77,8 @@ public class SQLServerSelectParser extends SQLSelectParser { return queryRest(queryBlock); } + + protected SQLExprParser createExprParser() { + return new SQLServerExprParser(lexer); + } } 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 a3b5689092..d71b78dfc0 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 @@ -24,6 +24,7 @@ public class SQLServerStatementParser extends SQLStatementParser { public SQLServerStatementParser(String sql){ super(new SQLServerLexer(sql)); this.lexer.nextToken(); + this.exprParser = new SQLServerExprParser(lexer); } public SQLSelectParser createSQLSelectParser() { diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitor.java index 30133fe68c..62ffab2bcc 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitor.java @@ -2,6 +2,7 @@ package com.alibaba.druid.sql.dialect.sqlserver.visitor; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock; import com.alibaba.druid.sql.dialect.sqlserver.ast.Top; +import com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr; import com.alibaba.druid.sql.visitor.SQLASTVisitor; public interface SQLServerASTVisitor extends SQLASTVisitor { @@ -13,4 +14,8 @@ public interface SQLServerASTVisitor extends SQLASTVisitor { boolean visit(Top x); void endVisit(Top x); + + boolean visit(SQLServerObjectReferenceExpr x); + + void endVisit(SQLServerObjectReferenceExpr x); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitorAdapter.java index 9eff67f70d..3e917ed396 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerASTVisitorAdapter.java @@ -2,6 +2,7 @@ package com.alibaba.druid.sql.dialect.sqlserver.visitor; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock; import com.alibaba.druid.sql.dialect.sqlserver.ast.Top; +import com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr; import com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter; public class SQLServerASTVisitorAdapter extends SQLASTVisitorAdapter implements SQLServerASTVisitor { @@ -25,5 +26,15 @@ public class SQLServerASTVisitorAdapter extends SQLASTVisitorAdapter implements public void endVisit(Top x) { } + + @Override + public boolean visit(SQLServerObjectReferenceExpr x) { + return true; + } + + @Override + public void endVisit(SQLServerObjectReferenceExpr 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 5d38004f23..f10368e017 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 @@ -3,6 +3,7 @@ package com.alibaba.druid.sql.dialect.sqlserver.visitor; import com.alibaba.druid.sql.ast.SQLSetQuantifier; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock; import com.alibaba.druid.sql.dialect.sqlserver.ast.Top; +import com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr; import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor; public class SQLServerOutputVisitor extends SQLASTOutputVisitor implements SQLServerASTVisitor { @@ -42,7 +43,7 @@ public class SQLServerOutputVisitor extends SQLASTOutputVisitor implements SQLSe } if (x.getGroupBy() != null) { - print(" "); + println(); x.getGroupBy().accept(this); } @@ -67,4 +68,15 @@ public class SQLServerOutputVisitor extends SQLASTOutputVisitor implements SQLSe } + @Override + public boolean visit(SQLServerObjectReferenceExpr x) { + print(x.toString()); + return false; + } + + @Override + public void endVisit(SQLServerObjectReferenceExpr x) { + + } + } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerSchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerSchemaStatVisitor.java index aafc17d44a..aff689e0d8 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerSchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/visitor/SQLServerSchemaStatVisitor.java @@ -3,6 +3,7 @@ package com.alibaba.druid.sql.dialect.sqlserver.visitor; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock; import com.alibaba.druid.sql.dialect.sqlserver.ast.Top; +import com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr; import com.alibaba.druid.sql.visitor.SchemaStatVisitor; @@ -28,5 +29,15 @@ public class SQLServerSchemaStatVisitor extends SchemaStatVisitor implements SQL } + @Override + public boolean visit(SQLServerObjectReferenceExpr x) { + return false; + } + + @Override + public void endVisit(SQLServerObjectReferenceExpr x) { + + } + } 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 f4c84b98a7..7180b9bab0 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Lexer.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Lexer.java @@ -288,7 +288,12 @@ public class Lexer { return; } else if (ch == '.') { scanChar(); - token = Token.DOTDOT; + if (ch == '.') { + scanChar(); + token = Token.DOTDOTDOT; + } else { + token = Token.DOTDOT; + } } else { token = Token.DOT; } 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 c9dd9a68eb..92ae4c8f12 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java @@ -626,7 +626,13 @@ public class SQLExprParser extends SQLParser { SQLName name = new SQLIdentifierExpr(identName); - while (lexer.token() == Token.DOT) { + name = nameRest(name); + + return name; + } + + public SQLName nameRest(SQLName name) throws ParserException { + if (lexer.token() == Token.DOT) { lexer.nextToken(); if (lexer.token() == Token.KEY) { @@ -646,6 +652,7 @@ public class SQLExprParser extends SQLParser { name = new SQLPropertyExpr(name, lexer.stringVal()); } lexer.nextToken(); + name = nameRest(name); } return name; 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 ce9f5e210c..4cf7f019f2 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java @@ -47,16 +47,16 @@ public class SQLStatementParser extends SQLParser { public SQLStatementParser(String sql){ super(sql); - this.exprParser = createExprParser(); + this.exprParser = new SQLExprParser(lexer); } public SQLStatementParser(Lexer lexer){ super(lexer); - this.exprParser = createExprParser(); + this.exprParser = new SQLExprParser(lexer); } - protected SQLExprParser createExprParser() { - return new SQLExprParser(lexer); + public SQLExprParser getExprParser() { + return exprParser; } public List parseStatementList() throws ParserException { @@ -255,7 +255,7 @@ public class SQLStatementParser extends SQLParser { insertStatement.setValues(values); accept(Token.RPAREN); } else if (acceptSubQuery && (lexer.token() == Token.SELECT || lexer.token() == Token.LPAREN)) { - SQLQueryExpr queryExpr = (SQLQueryExpr) this.createExprParser().expr(); + SQLQueryExpr queryExpr = (SQLQueryExpr) this.exprParser.expr(); insertStatement.setQuery(queryExpr.getSubQuery()); } } 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 a2fd78af7f..43c405d870 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/Token.java +++ b/src/main/java/com/alibaba/druid/sql/parser/Token.java @@ -213,6 +213,7 @@ public enum Token { COMMA(","), DOT("."), DOTDOT(".."), + DOTDOTDOT("..,"), EQ("="), GT(">"), LT("<"), 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 d1179a16d2..3e21457307 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -494,7 +494,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter { x.getQuery().accept(this); if (x.getOrderBy() != null) { - print(" "); + println(); x.getOrderBy().accept(this); } diff --git a/src/main/java/com/alibaba/druid/wall/spi/SQLServerWallVisitor.java b/src/main/java/com/alibaba/druid/wall/spi/SQLServerWallVisitor.java index 21b6a44e84..7b6c13fd1f 100644 --- a/src/main/java/com/alibaba/druid/wall/spi/SQLServerWallVisitor.java +++ b/src/main/java/com/alibaba/druid/wall/spi/SQLServerWallVisitor.java @@ -20,6 +20,7 @@ import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; import com.alibaba.druid.sql.ast.statement.SQLTruncateStatement; import com.alibaba.druid.sql.ast.statement.SQLUnionQuery; import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement; +import com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr; import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitor; import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitorAdapter; import com.alibaba.druid.wall.IllegalSQLObjectViolation; @@ -178,4 +179,12 @@ public class SQLServerWallVisitor extends SQLServerASTVisitorAdapter implements return true; } + + @Override + public boolean visit(SQLServerObjectReferenceExpr x) { + if (config.isPermitSchema(x.getSchema()) || config.isPermitSchema(x.getDatabase())) { + this.getViolations().add(new IllegalSQLObjectViolation(this.toSQL(x))); + } + return true; + } } diff --git a/src/main/java/com/alibaba/druid/wall/spi/WallVisitorUtils.java b/src/main/java/com/alibaba/druid/wall/spi/WallVisitorUtils.java index 779fd69d68..5272ac30c4 100644 --- a/src/main/java/com/alibaba/druid/wall/spi/WallVisitorUtils.java +++ b/src/main/java/com/alibaba/druid/wall/spi/WallVisitorUtils.java @@ -464,8 +464,8 @@ public class WallVisitorUtils { if (expr instanceof SQLPropertyExpr) { SQLPropertyExpr propExpr = (SQLPropertyExpr) expr; - if (propExpr.getOwner() instanceof SQLIdentifierExpr) { - String ownerName = ((SQLIdentifierExpr) propExpr.getOwner()).getName(); + if (propExpr.getOwner() instanceof SQLName) { + String ownerName = ((SQLName) propExpr.getOwner()).getSimleName(); ownerName = form(ownerName); diff --git a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDescribteTest.java b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDescribteTest.java index 524168520b..d5f60ce338 100644 --- a/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDescribteTest.java +++ b/src/test/java/com/alibaba/druid/bvt/sql/mysql/MySqlDescribteTest.java @@ -9,7 +9,6 @@ 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.stat.TableStat; -import com.alibaba.druid.stat.TableStat.Column; public class MySqlDescribteTest extends MysqlTest { diff --git a/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerSelectTest2.java b/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerSelectTest2.java new file mode 100644 index 0000000000..21c1c5c0f0 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerSelectTest2.java @@ -0,0 +1,31 @@ +package com.alibaba.druid.bvt.sql.sqlserver; + +import junit.framework.Assert; +import junit.framework.TestCase; + +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.dialect.sqlserver.parser.SQLServerStatementParser; +import com.alibaba.druid.sql.test.TestUtils; + +public class SQLServerSelectTest2 extends TestCase { + + public void test_isEmpty() throws Exception { + String sql = "SELECT TOP 1 name FROM (SELECT TOP 9 name FROM master..syslogins ORDER BY name ASC) sq ORDER BY name DESC "; + + String expect = "SELECT TOP 1 name\n" + // + "FROM (SELECT TOP 9 name\n" + // + "\tFROM master..syslogins\n" + // + "\tORDER BY name ASC\n" + // + "\t) sq\n" + // + "ORDER BY name DESC"; + + SQLServerStatementParser parser = new SQLServerStatementParser(sql); + SQLStatement stmt = parser.parseStatementList().get(0); + + String text = TestUtils.outputSqlServer(stmt); + + Assert.assertEquals(expect, text); + + System.out.println(text); + } +}