From 192f7322c4a057503d6db978280e8f6d4a4b9696 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B8=A9=E5=B0=91?= Date: Sun, 18 Mar 2012 21:02:41 +0800 Subject: [PATCH 1/4] refactor --- .../mysql/parser/MySqlStatementParser.java | 37 ++++----- .../oracle/parser/OracleStatementParser.java | 26 +++--- .../oracle/parser/OracleUpdateParser.java | 10 +-- .../parser/PGSQLStatementParser.java | 8 +- .../sqlserver/ast/expr/SQLServerExpr.java | 8 ++ .../expr/SQLServerObjectReferenceExpr.java | 83 +++++++++++++++++++ .../sqlserver/parser/SQLServerExprParser.java | 18 ++++ .../parser/SQLServerStatementParser.java | 1 + .../druid/sql/parser/SQLStatementParser.java | 10 +-- .../bvt/sql/mysql/MySqlDescribteTest.java | 1 - 10 files changed, 154 insertions(+), 48 deletions(-) create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/expr/SQLServerExpr.java create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/expr/SQLServerObjectReferenceExpr.java create mode 100644 src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerExprParser.java 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/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..c2d6de348b --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/expr/SQLServerObjectReferenceExpr.java @@ -0,0 +1,83 @@ +package com.alibaba.druid.sql.dialect.sqlserver.ast.expr; + +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 { + + private static final long serialVersionUID = 1L; + + private String server; + private String database; + private String schema; + private String object; + + @Override + public void accept0(SQLServerASTVisitor visitor) { + + } + + public void output(StringBuffer buf) { + boolean flag = false; + if (server != null) { + buf.append(server); + buf.append('.'); + flag = true; + } + + if (database != null) { + buf.append(database); + buf.append('.'); + flag = true; + } else { + if (flag) { + buf.append('.'); + } + } + + if (schema != null) { + buf.append(schema); + buf.append('.'); + flag = true; + } else { + if (flag) { + buf.append('.'); + } + } + + buf.append(object); + } + + 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; + } + + public String getObject() { + return object; + } + + public void setObject(String object) { + this.object = object; + } + +} 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..cc955706f2 --- /dev/null +++ b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/parser/SQLServerExprParser.java @@ -0,0 +1,18 @@ +package com.alibaba.druid.sql.dialect.sqlserver.parser; + +import com.alibaba.druid.sql.parser.Lexer; +import com.alibaba.druid.sql.parser.ParserException; +import com.alibaba.druid.sql.parser.SQLExprParser; + +public class SQLServerExprParser extends SQLExprParser { + + public SQLServerExprParser(Lexer lexer){ + super(lexer); + } + + public SQLServerExprParser(String sql) throws ParserException{ + super(new SQLServerLexer(sql)); + this.lexer.nextToken(); + } + +} 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/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/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 { From 01a8023dcba8255b1090a520bbff11aa0c75443e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B8=A9=E5=B0=91?= Date: Sun, 18 Mar 2012 21:43:03 +0800 Subject: [PATCH 2/4] enhance sql server parser --- .../expr/SQLServerObjectReferenceExpr.java | 32 +++++++++++++++++-- .../sqlserver/parser/SQLServerExprParser.java | 23 +++++++++++++ .../parser/SQLServerSelectParser.java | 5 +++ .../visitor/SQLServerASTVisitor.java | 5 +++ .../visitor/SQLServerASTVisitorAdapter.java | 11 +++++++ .../visitor/SQLServerOutputVisitor.java | 14 +++++++- .../visitor/SQLServerSchemaStatVisitor.java | 11 +++++++ .../druid/sql/parser/SQLExprParser.java | 9 +++++- .../sql/visitor/SQLASTOutputVisitor.java | 2 +- .../sql/sqlserver/SQLServerSelectTest2.java | 31 ++++++++++++++++++ 10 files changed, 137 insertions(+), 6 deletions(-) create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/sqlserver/SQLServerSelectTest2.java 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 index c2d6de348b..b8cd6e3477 100644 --- 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 @@ -1,9 +1,13 @@ 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 { +public class SQLServerObjectReferenceExpr extends SQLServerObjectImpl implements SQLServerExpr, SQLName { private static final long serialVersionUID = 1L; @@ -11,10 +15,32 @@ public class SQLServerObjectReferenceExpr extends SQLServerObjectImpl implements private String database; private String schema; private String object; - + + public SQLServerObjectReferenceExpr() { + + } + + public SQLServerObjectReferenceExpr(SQLExpr owner, String name) { + if (owner instanceof SQLIdentifierExpr) { + this.database = ((SQLIdentifierExpr) owner).getName(); + this.object = name; + } else if (owner instanceof SQLPropertyExpr) { + SQLPropertyExpr propExpr = (SQLPropertyExpr) owner; + + this.server = ((SQLIdentifierExpr) propExpr.getOwner()).getName(); + this.database = propExpr.getName(); + this.object = name; + } else { + throw new IllegalArgumentException(owner.toString()); + } + } + @Override public void accept0(SQLServerASTVisitor visitor) { - + if (visitor.visit(this)) { + + } + visitor.endVisit(this); } public void output(StringBuffer buf) { 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 index cc955706f2..278b5b61b1 100644 --- 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 @@ -1,8 +1,12 @@ 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.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 { @@ -15,4 +19,23 @@ public class SQLServerExprParser extends SQLExprParser { 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 name) throws ParserException { + if (lexer.token() == Token.DOTDOT) { + lexer.nextToken(); + String text = lexer.stringVal(); + lexer.nextToken(); + + name = new SQLServerObjectReferenceExpr(name, text); + } + + return super.nameRest(name); + } } 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/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/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/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/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); + } +} From afdcf3570cb0ca238325e1dff5a552cdd5e827c7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B8=A9=E5=B0=91?= Date: Sun, 18 Mar 2012 21:46:59 +0800 Subject: [PATCH 3/4] add token dotdotdot --- src/main/java/com/alibaba/druid/sql/parser/Lexer.java | 7 ++++++- src/main/java/com/alibaba/druid/sql/parser/Token.java | 1 + 2 files changed, 7 insertions(+), 1 deletion(-) 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/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("<"), From 9ffd91524efa5deee15f1c73fc848cc6e0e070cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=B8=A9=E5=B0=91?= Date: Sun, 18 Mar 2012 22:07:04 +0800 Subject: [PATCH 4/4] refactor --- .../com/alibaba/druid/sql/ast/SQLName.java | 2 +- .../druid/sql/ast/expr/SQLIdentifierExpr.java | 4 ++ .../druid/sql/ast/expr/SQLPropertyExpr.java | 4 ++ .../oracle/ast/expr/OracleDbLinkExpr.java | 4 ++ .../expr/SQLServerObjectReferenceExpr.java | 58 +++++++++---------- .../sqlserver/parser/SQLServerExprParser.java | 8 ++- .../druid/wall/spi/SQLServerWallVisitor.java | 9 +++ .../druid/wall/spi/WallVisitorUtils.java | 4 +- 8 files changed, 55 insertions(+), 38 deletions(-) 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/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/sqlserver/ast/expr/SQLServerObjectReferenceExpr.java b/src/main/java/com/alibaba/druid/sql/dialect/sqlserver/ast/expr/SQLServerObjectReferenceExpr.java index b8cd6e3477..62114e7e27 100644 --- 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 @@ -14,31 +14,39 @@ public class SQLServerObjectReferenceExpr extends SQLServerObjectImpl implements private String server; private String database; private String schema; - private String object; - - public SQLServerObjectReferenceExpr() { - + + public SQLServerObjectReferenceExpr(){ + } - - public SQLServerObjectReferenceExpr(SQLExpr owner, String name) { + + public SQLServerObjectReferenceExpr(SQLExpr owner){ if (owner instanceof SQLIdentifierExpr) { this.database = ((SQLIdentifierExpr) owner).getName(); - this.object = name; } else if (owner instanceof SQLPropertyExpr) { SQLPropertyExpr propExpr = (SQLPropertyExpr) owner; - + this.server = ((SQLIdentifierExpr) propExpr.getOwner()).getName(); this.database = propExpr.getName(); - this.object = name; } 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); } @@ -47,31 +55,25 @@ public class SQLServerObjectReferenceExpr extends SQLServerObjectImpl implements boolean flag = false; if (server != null) { buf.append(server); - buf.append('.'); flag = true; } + if (flag) { + buf.append('.'); + } if (database != null) { buf.append(database); - buf.append('.'); flag = true; - } else { - if (flag) { - buf.append('.'); - } - } + } + if (flag) { + buf.append('.'); + } + if (schema != null) { buf.append(schema); - buf.append('.'); flag = true; - } else { - if (flag) { - buf.append('.'); - } } - - buf.append(object); } public String getServer() { @@ -98,12 +100,4 @@ public class SQLServerObjectReferenceExpr extends SQLServerObjectImpl implements this.schema = schema; } - public String getObject() { - return object; - } - - public void setObject(String object) { - this.object = object; - } - } 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 index 278b5b61b1..cf5a73e272 100644 --- 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 @@ -2,6 +2,7 @@ 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; @@ -27,15 +28,16 @@ public class SQLServerExprParser extends SQLExprParser { return super.primaryRest(expr); } - public SQLName nameRest(SQLName name) throws ParserException { + public SQLName nameRest(SQLName expr) throws ParserException { if (lexer.token() == Token.DOTDOT) { lexer.nextToken(); String text = lexer.stringVal(); lexer.nextToken(); - name = new SQLServerObjectReferenceExpr(name, text); + SQLServerObjectReferenceExpr owner = new SQLServerObjectReferenceExpr(expr); + expr = new SQLPropertyExpr(owner, text); } - return super.nameRest(name); + return super.nameRest(expr); } } 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);