improved sql parser for sqlserver, support for xml clause

This commit is contained in:
wenshao
2014-11-16 09:56:36 +08:00
parent 95b6133d5a
commit 6983fa6d1f
16 changed files with 529 additions and 25 deletions
@@ -1,5 +1,5 @@
package com.alibaba.druid.sql.ast.statement;
public enum SQLObjectType {
TABLE, FUNCTION, PROCEDURE, USER
TABLE, FUNCTION, PROCEDURE, USER, DATABASE
}
@@ -29,7 +29,7 @@ public class SQLSelect extends SQLObjectImpl {
protected SQLSelectQuery query;
protected SQLOrderBy orderBy;
private List<SQLHint> hints;
protected List<SQLHint> hints;
public SQLSelect(){
@@ -15,8 +15,82 @@
*/
package com.alibaba.druid.sql.dialect.sqlserver.ast;
import com.alibaba.druid.sql.ast.statement.SQLSelect;
import java.util.ArrayList;
import java.util.List;
public class SQLServerSelect extends SQLSelect {
import com.alibaba.druid.sql.ast.statement.SQLSelect;
import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
public class SQLServerSelect extends SQLSelect implements SQLServerObject {
private boolean forBrowse;
private List<String> forXmlOptions = new ArrayList<String>(4);
public boolean isForBrowse() {
return forBrowse;
}
public void setForBrowse(boolean forBrowse) {
this.forBrowse = forBrowse;
}
public List<String> getForXmlOptions() {
return forXmlOptions;
}
public void setForXmlOptions(List<String> forXmlOptions) {
this.forXmlOptions = forXmlOptions;
}
@Override
protected void accept0(SQLASTVisitor visitor) {
this.accept0((SQLServerASTVisitor) visitor);
}
@Override
public void accept0(SQLServerASTVisitor visitor) {
if (visitor.visit(this)) {
acceptChild(visitor, this.query);
acceptChild(visitor, this.orderBy);
acceptChild(visitor, this.hints);
}
visitor.endVisit(this);
}
@Override
public int hashCode() {
final int prime = 31;
int result = super.hashCode();
result = prime * result + (forBrowse ? 1231 : 1237);
result = prime * result + ((forXmlOptions == null) ? 0 : forXmlOptions.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (!super.equals(obj)) {
return false;
}
if (getClass() != obj.getClass()) {
return false;
}
SQLServerSelect other = (SQLServerSelect) obj;
if (forBrowse != other.forBrowse) {
return false;
}
if (forXmlOptions == null) {
if (other.forXmlOptions != null) {
return false;
}
} else if (!forXmlOptions.equals(other.forXmlOptions)) {
return false;
}
return true;
}
}
@@ -25,6 +25,7 @@ import com.alibaba.druid.sql.ast.statement.SQLTableSource;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelect;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerTop;
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;
@@ -39,9 +40,9 @@ public class SQLServerSelectParser extends SQLSelectParser {
super(exprParser);
}
public SQLSelect select() {
public SQLSelect select() {
SQLServerSelect select = new SQLServerSelect();
withSubquery(select);
select.setQuery(query());
@@ -51,10 +52,50 @@ public class SQLServerSelectParser extends SQLSelectParser {
select.setOrderBy(parseOrderBy());
}
if (lexer.token() == Token.FOR) {
lexer.nextToken();
if (identifierEquals("BROWSE")) {
lexer.nextToken();
select.setForBrowse(true);
} else if (identifierEquals("XML")) {
lexer.nextToken();
for (;;) {
if (identifierEquals("AUTO") //
|| identifierEquals("TYPE") //
|| identifierEquals("XMLSCHEMA") //
) {
select.getForXmlOptions().add(lexer.stringVal());
lexer.nextToken();
} else if (identifierEquals("ELEMENTS")) {
lexer.nextToken();
if (identifierEquals("XSINIL")) {
lexer.nextToken();
select.getForXmlOptions().add("ELEMENTS XSINIL");
} else {
select.getForXmlOptions().add("ELEMENTS");
}
} else {
break;
}
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
} else {
break;
}
}
} else {
throw new ParserException("syntax error, not support option : " + lexer.token());
}
}
return select;
}
public SQLSelectQuery query() {
public SQLSelectQuery query() {
if (lexer.token() == Token.LPAREN) {
lexer.nextToken();
@@ -68,7 +109,7 @@ public class SQLServerSelectParser extends SQLSelectParser {
if (lexer.token() == Token.SELECT) {
lexer.nextToken();
if (lexer.token() == Token.COMMENT) {
lexer.nextToken();
}
@@ -88,10 +129,10 @@ public class SQLServerSelectParser extends SQLSelectParser {
parseSelectList(queryBlock);
}
if (lexer.token() == Token.INTO) {
lexer.nextToken();
SQLTableSource into = this.parseTableSource();
queryBlock.setInto((SQLExprTableSource) into);
}
@@ -104,16 +145,16 @@ public class SQLServerSelectParser extends SQLSelectParser {
return queryRest(queryBlock);
}
protected SQLServerExprParser createExprParser() {
return new SQLServerExprParser(lexer);
}
protected SQLTableSource parseTableSourceRest(SQLTableSource tableSource) {
if (lexer.token() == Token.WITH) {
lexer.nextToken();
accept(Token.LPAREN);
for (;;) {
SQLExpr expr = this.expr();
SQLExprHint hint = new SQLExprHint(expr);
@@ -126,10 +167,10 @@ public class SQLServerSelectParser extends SQLSelectParser {
break;
}
}
accept(Token.RPAREN);
}
return super.parseTableSourceRest(tableSource);
}
}
@@ -18,6 +18,7 @@ package com.alibaba.druid.sql.dialect.sqlserver.visitor;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerColumnDefinition;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerDeclareItem;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerOutput;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelect;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerTop;
import com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr;
@@ -97,5 +98,9 @@ public interface SQLServerASTVisitor extends SQLASTVisitor {
boolean visit(SQLServerBlockStatement x);
void endVisit(SQLServerBlockStatement x);
boolean visit(SQLServerSelect x);
void endVisit(SQLServerSelect x);
}
@@ -18,6 +18,7 @@ package com.alibaba.druid.sql.dialect.sqlserver.visitor;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerColumnDefinition;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerDeclareItem;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerOutput;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelect;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerTop;
import com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr;
@@ -193,5 +194,15 @@ public class SQLServerASTVisitorAdapter extends SQLASTVisitorAdapter implements
public void endVisit(SQLServerBlockStatement x) {
}
@Override
public boolean visit(SQLServerSelect x) {
return true;
}
@Override
public void endVisit(SQLServerSelect x) {
}
}
@@ -22,10 +22,12 @@ import com.alibaba.druid.sql.ast.statement.SQLAssignItem;
import com.alibaba.druid.sql.ast.statement.SQLColumnConstraint;
import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
import com.alibaba.druid.sql.ast.statement.SQLGrantStatement;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerColumnDefinition;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerColumnDefinition.Identity;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerDeclareItem;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerOutput;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelect;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerTop;
import com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr;
@@ -553,4 +555,44 @@ public class SQLServerOutputVisitor extends SQLASTOutputVisitor implements SQLSe
public void endVisit(SQLServerBlockStatement x) {
}
@Override
protected void printGrantOn(SQLGrantStatement x) {
if (x.getOn() != null) {
print(" ON ");
if (x.getObjectType() != null) {
print(x.getObjectType().name());
print("::");
}
x.getOn().accept(this);
}
}
@Override
public void endVisit(SQLServerSelect x) {
}
@Override
public boolean visit(SQLServerSelect x) {
super.visit(x);
if (x.isForBrowse()) {
println();
print("FOR BROWSE");
}
if (x.getForXmlOptions().size() > 0) {
println();
print("FOR XML ");
for (int i = 0; i < x.getForXmlOptions().size(); ++i) {
if (i != 0) {
print(", ");
print(x.getForXmlOptions().get(i));
}
}
}
return false;
}
}
@@ -25,6 +25,7 @@ import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerColumnDefinition;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerColumnDefinition.Identity;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerDeclareItem;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerOutput;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelect;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerSelectQueryBlock;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerTop;
import com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr;
@@ -230,4 +231,14 @@ public class SQLServerSchemaStatVisitor extends SchemaStatVisitor implements SQL
}
@Override
public boolean visit(SQLServerSelect x) {
return super.visit(x);
}
@Override
public void endVisit(SQLServerSelect x) {
}
}
@@ -379,6 +379,13 @@ public class SQLStatementParser extends SQLParser {
} else if (lexer.token() == Token.USER) {
lexer.nextToken();
stmt.setObjectType(SQLObjectType.USER);
} else if (lexer.token() == Token.DATABASE) {
lexer.nextToken();
stmt.setObjectType(SQLObjectType.DATABASE);
}
if (stmt.getObjectType() != null && lexer.token() == Token.COLONCOLON) {
lexer.nextToken(); // sql server
}
SQLExpr expr = this.exprParser.expr();
@@ -631,6 +638,13 @@ public class SQLStatementParser extends SQLParser {
} else if (identifierEquals("SUPER")) {
lexer.nextToken();
privilege = "SUPER";
} else if (identifierEquals("CONTROL")) { // sqlserver
lexer.nextToken();
privilege = "CONTROL";
} else if (identifierEquals("IMPERSONATE")) { // sqlserver
lexer.nextToken();
privilege = "IMPERSONATE";
}
if (privilege != null) {
@@ -1808,16 +1808,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab
print("GRANT ");
printAndAccept(x.getPrivileges(), ", ");
if (x.getOn() != null) {
print(" ON ");
if (x.getObjectType() != null) {
print(x.getObjectType().name());
print(' ');
}
x.getOn().accept(this);
}
printGrantOn(x);
if (x.getTo() != null) {
print(" TO ");
@@ -1877,6 +1868,19 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Printab
return false;
}
protected void printGrantOn(SQLGrantStatement x) {
if (x.getOn() != null) {
print(" ON ");
if (x.getObjectType() != null) {
print(x.getObjectType().name());
print(' ');
}
x.getOn().accept(this);
}
}
@Override
public boolean visit(SQLRevokeStatement x) {
print("ROVOKE ");