improve sql parser, support sql server

This commit is contained in:
wenshao
2013-08-02 16:16:35 +08:00
parent e9a6e6b135
commit b9fedcb6d4
45 changed files with 1397 additions and 220 deletions
@@ -0,0 +1,103 @@
/*
* Copyright 1999-2011 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.alibaba.druid.sql.dialect.sqlserver.ast;
import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;
import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
public class SQLServerColumnDefinition extends SQLColumnDefinition implements SQLServerObject {
private static final long serialVersionUID = 1L;
private Identity identity;
public SQLServerColumnDefinition(){
}
public Identity getIdentity() {
return identity;
}
public void setIdentity(Identity identity) {
if (identity != null) {
identity.setParent(this);
}
this.identity = identity;
}
@Override
protected void accept0(SQLASTVisitor visitor) {
this.accept0((SQLServerASTVisitor) visitor);
}
@Override
public void accept0(SQLServerASTVisitor visitor) {
if (visitor.visit(this)) {
this.acceptChild(visitor, name);
this.acceptChild(visitor, dataType);
this.acceptChild(visitor, defaultExpr);
this.acceptChild(visitor, constaints);
this.acceptChild(visitor, identity);
}
visitor.endVisit(this);
}
@SuppressWarnings("serial")
public static class Identity extends SQLServerObjectImpl {
private Integer seed;
private Integer increment;
private boolean notForReplication;
public Identity() {
}
public Integer getSeed() {
return seed;
}
public void setSeed(Integer seed) {
this.seed = seed;
}
public Integer getIncrement() {
return increment;
}
public void setIncrement(Integer increment) {
this.increment = increment;
}
public boolean isNotForReplication() {
return notForReplication;
}
public void setNotForReplication(boolean notForReplication) {
this.notForReplication = notForReplication;
}
@Override
public void accept0(SQLServerASTVisitor visitor) {
visitor.visit(this);
visitor.endVisit(this);
}
}
}
@@ -0,0 +1,52 @@
package com.alibaba.druid.sql.dialect.sqlserver.ast.stmt;
import java.util.ArrayList;
import java.util.List;
/*
* Copyright 1999-2011 Alibaba Group Holding Ltd.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerObjectImpl;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerStatement;
import com.alibaba.druid.sql.dialect.sqlserver.visitor.SQLServerASTVisitor;
@SuppressWarnings("serial")
public class SQLServerExecStatement extends SQLServerObjectImpl implements SQLServerStatement {
private SQLName moduleName;
private List<SQLExpr> parameters = new ArrayList<SQLExpr>();
public SQLName getModuleName() {
return moduleName;
}
public void setModuleName(SQLName moduleName) {
this.moduleName = moduleName;
}
public List<SQLExpr> getParameters() {
return parameters;
}
public void accept0(SQLServerASTVisitor visitor) {
if (visitor.visit(this)) {
acceptChild(visitor, this.moduleName);
acceptChild(visitor, this.parameters);
}
visitor.endVisit(this);
}
}
@@ -17,7 +17,10 @@ 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.SQLIntegerExpr;
import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;
import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerColumnDefinition;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerTop;
import com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr;
import com.alibaba.druid.sql.parser.Lexer;
@@ -129,4 +132,37 @@ public class SQLServerExprParser extends SQLExprParser {
return null;
}
protected SQLColumnDefinition createColumnDefinition() {
SQLColumnDefinition column = new SQLServerColumnDefinition();
return column;
}
public SQLColumnDefinition parseColumnRest(SQLColumnDefinition column) {
if (lexer.token() == Token.IDENTITY) {
lexer.nextToken();
accept(Token.LPAREN);
SQLIntegerExpr seed = (SQLIntegerExpr) this.primary();
accept(Token.COMMA);
SQLIntegerExpr increment = (SQLIntegerExpr) this.primary();
accept(Token.RPAREN);
SQLServerColumnDefinition.Identity identity = new SQLServerColumnDefinition.Identity();
identity.setSeed((Integer) seed.getNumber());
identity.setIncrement((Integer) increment.getNumber());
if (lexer.token() == Token.NOT) {
lexer.nextToken();
accept(Token.FOR);
identifierEquals("REPLICATION ");
identity.setNotForReplication(true);
}
SQLServerColumnDefinition sqlSreverColumn = (SQLServerColumnDefinition) column;
sqlSreverColumn.setIdentity(identity);
}
return super.parseColumnRest(column);
}
}
@@ -40,6 +40,7 @@ public class SQLServerLexer extends Lexer {
map.put("USE", Token.USE);
map.put("WITH", Token.WITH);
map.put("PERCENT", Token.PERCENT);
map.put("IDENTITY", Token.IDENTITY);
DEFAULT_SQL_SERVER_KEYWORDS = new Keywords(map);
}
@@ -17,6 +17,7 @@ package com.alibaba.druid.sql.dialect.sqlserver.parser;
import java.util.List;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.expr.SQLQueryExpr;
@@ -25,6 +26,7 @@ import com.alibaba.druid.sql.ast.statement.SQLInsertStatement;
import com.alibaba.druid.sql.ast.statement.SQLTableSource;
import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerTop;
import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerExecStatement;
import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerInsertStatement;
import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerUpdateStatement;
import com.alibaba.druid.sql.parser.Lexer;
@@ -53,6 +55,24 @@ public class SQLServerStatementParser extends SQLStatementParser {
return true;
}
if (identifierEquals("EXEC") || identifierEquals("EXECUTE")) {
lexer.nextToken();
SQLServerExecStatement execStmt = new SQLServerExecStatement();
if (lexer.token() == Token.LPAREN) {
lexer.nextToken();
this.exprParser.exprList(execStmt.getParameters(), execStmt);
accept(Token.RPAREN);
} else {
SQLName moduleName = this.exprParser.name();
execStmt.setModuleName(moduleName);
this.exprParser.exprList(execStmt.getParameters(), execStmt);
}
statementList.add(execStmt);
return true;
}
return false;
}
@@ -125,7 +145,7 @@ public class SQLServerStatementParser extends SQLStatementParser {
SQLServerUpdateStatement udpateStatement = createUpdateStatement();
accept(Token.UPDATE);
SQLServerTop top = this.getExprParser().parseTop();
if (top != null) {
udpateStatement.setTop(top);
@@ -149,7 +169,7 @@ public class SQLServerStatementParser extends SQLStatementParser {
return udpateStatement;
}
public SQLServerExprParser getExprParser() {
return (SQLServerExprParser) exprParser;
}
@@ -15,9 +15,11 @@
*/
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.SQLServerSelectQueryBlock;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerTop;
import com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr;
import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerExecStatement;
import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerInsertStatement;
import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerUpdateStatement;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
@@ -43,4 +45,17 @@ public interface SQLServerASTVisitor extends SQLASTVisitor {
boolean visit(SQLServerUpdateStatement x);
void endVisit(SQLServerUpdateStatement x);
boolean visit(SQLServerColumnDefinition x);
void endVisit(SQLServerColumnDefinition x);
boolean visit(SQLServerColumnDefinition.Identity x);
void endVisit(SQLServerColumnDefinition.Identity x);
boolean visit(SQLServerExecStatement x);
void endVisit(SQLServerExecStatement x);
}
@@ -15,9 +15,11 @@
*/
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.SQLServerSelectQueryBlock;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerTop;
import com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr;
import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerExecStatement;
import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerInsertStatement;
import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerUpdateStatement;
import com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter;
@@ -43,15 +45,15 @@ public class SQLServerASTVisitorAdapter extends SQLASTVisitorAdapter implements
public void endVisit(SQLServerTop x) {
}
@Override
public boolean visit(SQLServerObjectReferenceExpr x) {
return true;
}
@Override
public void endVisit(SQLServerObjectReferenceExpr x) {
}
@Override
@@ -61,7 +63,7 @@ public class SQLServerASTVisitorAdapter extends SQLASTVisitorAdapter implements
@Override
public void endVisit(SQLServerInsertStatement x) {
}
@Override
@@ -71,6 +73,36 @@ public class SQLServerASTVisitorAdapter extends SQLASTVisitorAdapter implements
@Override
public void endVisit(SQLServerUpdateStatement x) {
}
@Override
public boolean visit(SQLServerColumnDefinition.Identity x) {
return true;
}
@Override
public void endVisit(SQLServerColumnDefinition.Identity x) {
}
@Override
public boolean visit(SQLServerColumnDefinition x) {
return true;
}
@Override
public void endVisit(SQLServerColumnDefinition x) {
}
@Override
public boolean visit(SQLServerExecStatement x) {
return true;
}
@Override
public void endVisit(SQLServerExecStatement x) {
}
@@ -15,11 +15,17 @@
*/
package com.alibaba.druid.sql.dialect.sqlserver.visitor;
import com.alibaba.druid.sql.ast.SQLName;
import com.alibaba.druid.sql.ast.SQLSetQuantifier;
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.dialect.sqlserver.ast.SQLServerColumnDefinition;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerColumnDefinition.Identity;
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;
import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerExecStatement;
import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerInsertStatement;
import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerUpdateStatement;
import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;
@@ -47,7 +53,7 @@ public class SQLServerOutputVisitor extends SQLASTOutputVisitor implements SQLSe
}
printSelectList(x.getSelectList());
if (x.getInto() != null) {
println();
print("INTO ");
@@ -83,24 +89,24 @@ public class SQLServerOutputVisitor extends SQLASTOutputVisitor implements SQLSe
@Override
public boolean visit(SQLServerTop x) {
print("TOP ");
boolean paren = false;
if (x.getParent() instanceof SQLServerUpdateStatement) {
paren = true;
print("(");
}
x.getExpr().accept(this);
if (paren) {
print(")");
}
if (x.isPercent()) {
print(" PERCENT");
}
return false;
}
@@ -172,7 +178,7 @@ public class SQLServerOutputVisitor extends SQLASTOutputVisitor implements SQLSe
@Override
public boolean visit(SQLServerUpdateStatement x) {
print("UPDATE ");
if (x.getTop() != null) {
x.getTop().setParent(x);
x.getTop().accept(this);
@@ -189,7 +195,7 @@ public class SQLServerOutputVisitor extends SQLASTOutputVisitor implements SQLSe
}
x.getItems().get(i).accept(this);
}
if (x.getFrom() != null) {
println();
print("FROM ");
@@ -209,12 +215,12 @@ public class SQLServerOutputVisitor extends SQLASTOutputVisitor implements SQLSe
@Override
public void endVisit(SQLServerUpdateStatement x) {
}
public boolean visit(SQLExprTableSource x) {
x.getExpr().accept(this);
if (x.getHints() != null && x.getHints().size() > 0) {
print(" WITH (");
printAndAccept(x.getHints(), ", ");
@@ -228,4 +234,86 @@ public class SQLServerOutputVisitor extends SQLASTOutputVisitor implements SQLSe
return false;
}
@Override
public boolean visit(Identity x) {
print("IDENTITY (");
print(x.getSeed());
print(", ");
print(x.getIncrement());
print(")");
return false;
}
@Override
public void endVisit(Identity x) {
}
@Override
public boolean visit(SQLServerColumnDefinition x) {
x.getName().accept(this);
if (x.getDataType() != null) {
print(' ');
x.getDataType().accept(this);
}
if (x.getDefaultExpr() != null) {
visitColumnDefault(x);
}
for (SQLColumnConstraint item : x.getConstaints()) {
print(' ');
item.accept(this);
}
if (x.getIdentity() != null) {
print(' ');
x.getIdentity().accept(this);
}
if (x.getEnable() != null) {
if (x.getEnable().booleanValue()) {
print(" ENABLE");
}
}
return false;
}
@Override
public void endVisit(SQLServerColumnDefinition x) {
}
public boolean visit(SQLColumnDefinition x) {
if (x instanceof SQLServerColumnDefinition) {
return visit((SQLServerColumnDefinition) x);
}
return super.visit(x);
}
@Override
public boolean visit(SQLServerExecStatement x) {
print("EXEC ");
SQLName moduleName = x.getModuleName();
if (moduleName != null) {
moduleName.accept(this);
print(' ');
} else {
print(" (");
}
printAndAccept(x.getParameters(), ", ");
if (moduleName == null) {
print(')');
}
return false;
}
@Override
public void endVisit(SQLServerExecStatement x) {
}
}
@@ -17,25 +17,28 @@ package com.alibaba.druid.sql.dialect.sqlserver.visitor;
import java.util.Map;
import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition;
import com.alibaba.druid.sql.ast.statement.SQLInsertStatement;
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
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.SQLServerSelectQueryBlock;
import com.alibaba.druid.sql.dialect.sqlserver.ast.SQLServerTop;
import com.alibaba.druid.sql.dialect.sqlserver.ast.expr.SQLServerObjectReferenceExpr;
import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerExecStatement;
import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerInsertStatement;
import com.alibaba.druid.sql.dialect.sqlserver.ast.stmt.SQLServerUpdateStatement;
import com.alibaba.druid.sql.visitor.SchemaStatVisitor;
import com.alibaba.druid.stat.TableStat;
import com.alibaba.druid.util.JdbcUtils;
public class SQLServerSchemaStatVisitor extends SchemaStatVisitor implements SQLServerASTVisitor {
@Override
public String getDbType() {
return JdbcUtils.SQL_SERVER;
}
@Override
public boolean visit(SQLServerSelectQueryBlock x) {
return visit((SQLSelectQueryBlock) x);
@@ -53,7 +56,7 @@ public class SQLServerSchemaStatVisitor extends SchemaStatVisitor implements SQL
@Override
public void endVisit(SQLServerTop x) {
}
@Override
@@ -63,7 +66,7 @@ public class SQLServerSchemaStatVisitor extends SchemaStatVisitor implements SQL
@Override
public void endVisit(SQLServerObjectReferenceExpr x) {
}
@Override
@@ -74,7 +77,7 @@ public class SQLServerSchemaStatVisitor extends SchemaStatVisitor implements SQL
@Override
public void endVisit(SQLServerInsertStatement x) {
this.endVisit((SQLInsertStatement) x);
this.endVisit((SQLInsertStatement) x);
}
@Override
@@ -99,8 +102,37 @@ public class SQLServerSchemaStatVisitor extends SchemaStatVisitor implements SQL
@Override
public void endVisit(SQLServerUpdateStatement x) {
}
@Override
public boolean visit(Identity x) {
return false;
}
@Override
public void endVisit(Identity x) {
}
@Override
public boolean visit(SQLServerColumnDefinition x) {
return visit((SQLColumnDefinition) x);
}
@Override
public void endVisit(SQLServerColumnDefinition x) {
}
@Override
public boolean visit(SQLServerExecStatement x) {
return false;
}
@Override
public void endVisit(SQLServerExecStatement x) {
}
}