mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
improved sql parser for sqlserver, support for xml clause
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+52
-11
@@ -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);
|
||||
|
||||
}
|
||||
|
||||
+11
@@ -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) {
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+42
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
+11
@@ -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 ");
|
||||
|
||||
Reference in New Issue
Block a user