add db2 sql parser support

This commit is contained in:
wenshao
2013-07-25 23:23:55 +08:00
parent 920d826331
commit 89f1106e34
26 changed files with 943 additions and 41 deletions
@@ -33,6 +33,7 @@ import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
import com.alibaba.druid.sql.ast.statement.SQLSubqueryTableSource;
import com.alibaba.druid.sql.ast.statement.SQLUnionQuery;
import com.alibaba.druid.sql.dialect.db2.ast.stmt.DB2SelectQueryBlock;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock;
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlSelectQueryBlock.Limit;
import com.alibaba.druid.sql.dialect.oracle.ast.expr.OracleAggregateExpr;
@@ -226,6 +227,10 @@ public class PagerUtils {
if (JdbcConstants.SQL_SERVER.equals(dbType)) {
return new SQLServerSelectQueryBlock();
}
if (JdbcConstants.DB2.equals(dbType)) {
return new DB2SelectQueryBlock();
}
return new SQLSelectQueryBlock();
}
@@ -21,6 +21,8 @@ import com.alibaba.druid.DruidRuntimeException;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLObject;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.dialect.db2.visitor.DB2OutputVisitor;
import com.alibaba.druid.sql.dialect.db2.visitor.DB2SchemaStatVisitor;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleOutputVisitor;
@@ -38,8 +40,8 @@ import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;
import com.alibaba.druid.sql.visitor.SchemaStatVisitor;
import com.alibaba.druid.support.logging.Log;
import com.alibaba.druid.support.logging.LogFactory;
import com.alibaba.druid.util.JdbcUtils;
import com.alibaba.druid.util.JdbcConstants;
import com.alibaba.druid.util.JdbcUtils;
import com.alibaba.druid.util.StringUtils;
@@ -201,6 +203,10 @@ public class SQLUtils {
if (JdbcUtils.JTDS.equals(dbType)) {
return new SQLServerOutputVisitor(out);
}
if (JdbcUtils.DB2.equals(dbType)) {
return new DB2OutputVisitor(out);
}
return new SQLASTOutputVisitor(out);
}
@@ -231,6 +237,10 @@ public class SQLUtils {
if (JdbcUtils.JTDS.equals(dbType)) {
return new SQLServerSchemaStatVisitor();
}
if (JdbcUtils.DB2.equals(dbType)) {
return new DB2SchemaStatVisitor();
}
return new SchemaStatVisitor();
}
@@ -0,0 +1,25 @@
/*
* 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.db2.ast.stmt;
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
public class DB2SelectQueryBlock extends SQLSelectQueryBlock {
private static final long serialVersionUID = 1L;
}
@@ -0,0 +1,20 @@
package com.alibaba.druid.sql.dialect.db2.parser;
import com.alibaba.druid.sql.parser.Lexer;
import com.alibaba.druid.sql.parser.SQLExprParser;
public class DB2ExprParser extends SQLExprParser {
public final static String[] AGGREGATE_FUNCTIONS = { "AVG", "COUNT", "MAX", "MIN", "STDDEV", "SUM", "ROW_NUMBER" };
public DB2ExprParser(String sql){
this(new DB2Lexer(sql));
this.lexer.nextToken();
}
public DB2ExprParser(Lexer lexer){
super(lexer);
this.aggregateFunctions = AGGREGATE_FUNCTIONS;
}
}
@@ -0,0 +1,27 @@
package com.alibaba.druid.sql.dialect.db2.parser;
import java.util.HashMap;
import java.util.Map;
import com.alibaba.druid.sql.parser.Keywords;
import com.alibaba.druid.sql.parser.Lexer;
import com.alibaba.druid.sql.parser.Token;
public class DB2Lexer extends Lexer {
public final static Keywords DEFAULT_DB2_KEYWORDS;
static {
Map<String, Token> map = new HashMap<String, Token>();
map.putAll(Keywords.DEFAULT_KEYWORDS.getKeywords());
DEFAULT_DB2_KEYWORDS = new Keywords(map);
}
public DB2Lexer(String input){
super(input);
super.keywods = DEFAULT_DB2_KEYWORDS;
}
}
@@ -0,0 +1,80 @@
/*
* 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.db2.parser;
import com.alibaba.druid.sql.ast.SQLSetQuantifier;
import com.alibaba.druid.sql.ast.statement.SQLSelectQuery;
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
import com.alibaba.druid.sql.dialect.db2.ast.stmt.DB2SelectQueryBlock;
import com.alibaba.druid.sql.parser.SQLExprParser;
import com.alibaba.druid.sql.parser.SQLSelectParser;
import com.alibaba.druid.sql.parser.Token;
public class DB2SelectParser extends SQLSelectParser {
public DB2SelectParser(SQLExprParser exprParser){
super(exprParser);
}
public DB2SelectParser(String sql){
this(new DB2ExprParser(sql));
}
protected SQLExprParser createExprParser() {
return new DB2ExprParser(lexer);
}
@Override
public SQLSelectQuery query() {
if (lexer.token() == Token.LPAREN) {
lexer.nextToken();
SQLSelectQuery select = query();
accept(Token.RPAREN);
return queryRest(select);
}
accept(Token.SELECT);
if (lexer.token() == Token.COMMENT) {
lexer.nextToken();
}
DB2SelectQueryBlock queryBlock = new DB2SelectQueryBlock();
if (lexer.token() == Token.DISTINCT) {
queryBlock.setDistionOption(SQLSetQuantifier.DISTINCT);
lexer.nextToken();
} else if (lexer.token() == Token.UNIQUE) {
queryBlock.setDistionOption(SQLSetQuantifier.UNIQUE);
lexer.nextToken();
} else if (lexer.token() == Token.ALL) {
queryBlock.setDistionOption(SQLSetQuantifier.ALL);
lexer.nextToken();
}
parseSelectList(queryBlock);
parseFrom(queryBlock);
parseWhere(queryBlock);
parseGroupBy(queryBlock);
return queryRest(queryBlock);
}
}
@@ -0,0 +1,19 @@
package com.alibaba.druid.sql.dialect.db2.parser;
import com.alibaba.druid.sql.parser.Lexer;
import com.alibaba.druid.sql.parser.SQLStatementParser;
public class DB2StatementParser extends SQLStatementParser {
public DB2StatementParser(String sql) {
super (new DB2ExprParser(sql));
}
public DB2StatementParser(Lexer lexer){
super(new DB2ExprParser(lexer));
}
public DB2SelectParser createSQLSelectParser() {
return new DB2SelectParser(this.exprParser);
}
}
@@ -0,0 +1,8 @@
package com.alibaba.druid.sql.dialect.db2.visitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
public interface DB2ASTVisitor extends SQLASTVisitor {
}
@@ -0,0 +1,7 @@
package com.alibaba.druid.sql.dialect.db2.visitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter;
public class DB2ASTVisitorAdapter extends SQLASTVisitorAdapter implements DB2ASTVisitor {
}
@@ -0,0 +1,142 @@
/*
* 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.db2.visitor;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;
import com.alibaba.druid.sql.ast.expr.SQLCaseExpr;
import com.alibaba.druid.sql.ast.expr.SQLCharExpr;
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.ast.expr.SQLInListExpr;
import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;
import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;
import com.alibaba.druid.sql.ast.expr.SQLNullExpr;
import com.alibaba.druid.sql.ast.expr.SQLNumberExpr;
import com.alibaba.druid.sql.ast.expr.SQLQueryExpr;
import com.alibaba.druid.sql.ast.expr.SQLUnaryExpr;
import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
import com.alibaba.druid.sql.visitor.SQLEvalVisitor;
import com.alibaba.druid.sql.visitor.SQLEvalVisitorUtils;
import com.alibaba.druid.sql.visitor.functions.Function;
public class DB2EvalVisitor extends DB2ASTVisitorAdapter implements SQLEvalVisitor {
private Map<String, Function> functions = new HashMap<String, Function>();
private List<Object> parameters = new ArrayList<Object>();
private int variantIndex = -1;
private boolean markVariantIndex = true;
public DB2EvalVisitor(){
this(new ArrayList<Object>(1));
}
public DB2EvalVisitor(List<Object> parameters){
this.parameters = parameters;
}
public List<Object> getParameters() {
return parameters;
}
public void setParameters(List<Object> parameters) {
this.parameters = parameters;
}
public boolean visit(SQLCharExpr x) {
return SQLEvalVisitorUtils.visit(this, x);
}
public int incrementAndGetVariantIndex() {
return ++variantIndex;
}
public int getVariantIndex() {
return variantIndex;
}
public boolean visit(SQLVariantRefExpr x) {
return SQLEvalVisitorUtils.visit(this, x);
}
public boolean visit(SQLBinaryOpExpr x) {
return SQLEvalVisitorUtils.visit(this, x);
}
public boolean visit(SQLUnaryExpr x) {
return SQLEvalVisitorUtils.visit(this, x);
}
public boolean visit(SQLIntegerExpr x) {
return SQLEvalVisitorUtils.visit(this, x);
}
public boolean visit(SQLNumberExpr x) {
return SQLEvalVisitorUtils.visit(this, x);
}
@Override
public boolean visit(SQLCaseExpr x) {
return SQLEvalVisitorUtils.visit(this, x);
}
@Override
public boolean visit(SQLInListExpr x) {
return SQLEvalVisitorUtils.visit(this, x);
}
@Override
public boolean visit(SQLNullExpr x) {
return SQLEvalVisitorUtils.visit(this, x);
}
@Override
public boolean visit(SQLMethodInvokeExpr x) {
return SQLEvalVisitorUtils.visit(this, x);
}
@Override
public boolean visit(SQLQueryExpr x) {
return SQLEvalVisitorUtils.visit(this, x);
}
public boolean isMarkVariantIndex() {
return markVariantIndex;
}
public void setMarkVariantIndex(boolean markVariantIndex) {
this.markVariantIndex = markVariantIndex;
}
@Override
public Function getFunction(String funcName) {
return functions.get(funcName);
}
@Override
public void registerFunction(String funcName, Function function) {
functions.put(funcName, function);
}
public boolean visit(SQLIdentifierExpr x) {
return SQLEvalVisitorUtils.visit(this, x);
}
}
@@ -0,0 +1,87 @@
/*
* 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.db2.visitor;
import java.util.ArrayList;
import java.util.List;
import com.alibaba.druid.sql.ast.SQLOrderBy;
import com.alibaba.druid.sql.ast.expr.SQLBetweenExpr;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;
import com.alibaba.druid.sql.ast.expr.SQLInListExpr;
import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;
import com.alibaba.druid.sql.ast.statement.SQLSelectGroupByClause;
import com.alibaba.druid.sql.ast.statement.SQLSelectItem;
import com.alibaba.druid.sql.visitor.ExportParameterVisitor;
import com.alibaba.druid.sql.visitor.ExportParameterVisitorUtils;
public class DB2ExportParameterVisitor extends DB2ASTVisitorAdapter implements ExportParameterVisitor {
private final List<Object> parameters;
public DB2ExportParameterVisitor(){
this(new ArrayList<Object>());
}
public DB2ExportParameterVisitor(List<Object> parameters){
this.parameters = parameters;
}
public List<Object> getParameters() {
return parameters;
}
@Override
public boolean visit(SQLSelectItem x) {
return false;
}
@Override
public boolean visit(SQLOrderBy x) {
return false;
}
@Override
public boolean visit(SQLSelectGroupByClause x) {
return false;
}
@Override
public boolean visit(SQLMethodInvokeExpr x) {
ExportParameterVisitorUtils.exportParamterAndAccept(this.parameters, x.getParameters());
return true;
}
@Override
public boolean visit(SQLInListExpr x) {
ExportParameterVisitorUtils.exportParamterAndAccept(this.parameters, x.getTargetList());
return true;
}
@Override
public boolean visit(SQLBetweenExpr x) {
ExportParameterVisitorUtils.exportParameter(this.parameters, x);
return true;
}
public boolean visit(SQLBinaryOpExpr x) {
ExportParameterVisitorUtils.exportParameter(this.parameters, x);
return true;
}
}
@@ -0,0 +1,10 @@
package com.alibaba.druid.sql.dialect.db2.visitor;
import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor;
public class DB2OutputVisitor extends SQLASTOutputVisitor implements DB2ASTVisitor {
public DB2OutputVisitor(Appendable appender){
super(appender);
}
}
@@ -0,0 +1,88 @@
/*
* 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.db2.visitor;
import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;
import com.alibaba.druid.sql.ast.expr.SQLCharExpr;
import com.alibaba.druid.sql.ast.expr.SQLInListExpr;
import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;
import com.alibaba.druid.sql.ast.expr.SQLNCharExpr;
import com.alibaba.druid.sql.ast.expr.SQLNullExpr;
import com.alibaba.druid.sql.ast.expr.SQLNumberExpr;
import com.alibaba.druid.sql.visitor.ParameterizedOutputVisitorUtils;
public class DB2ParameterizedOutputVisitor extends DB2OutputVisitor {
public DB2ParameterizedOutputVisitor(){
this(new StringBuilder());
}
public DB2ParameterizedOutputVisitor(Appendable appender){
super(appender);
}
public boolean visit(SQLInListExpr x) {
return ParameterizedOutputVisitorUtils.visit(this, x);
}
public boolean visit(SQLBinaryOpExpr x) {
x = ParameterizedOutputVisitorUtils.merge(x);
return super.visit(x);
}
public boolean visit(SQLNullExpr x) {
print('?');
return false;
}
public boolean visit(SQLIntegerExpr x) {
if (Boolean.TRUE.equals(x.getAttribute(ParameterizedOutputVisitorUtils.ATTR_PARAMS_SKIP))) {
return super.visit(x);
}
print('?');
return false;
}
public boolean visit(SQLNumberExpr x) {
if (Boolean.TRUE.equals(x.getAttribute(ParameterizedOutputVisitorUtils.ATTR_PARAMS_SKIP))) {
return super.visit(x);
}
print('?');
return false;
}
public boolean visit(SQLCharExpr x) {
if (Boolean.TRUE.equals(x.getAttribute(ParameterizedOutputVisitorUtils.ATTR_PARAMS_SKIP))) {
return super.visit(x);
}
print('?');
return false;
}
public boolean visit(SQLNCharExpr x) {
if (Boolean.TRUE.equals(x.getAttribute(ParameterizedOutputVisitorUtils.ATTR_PARAMS_SKIP))) {
return super.visit(x);
}
print('?');
return false;
}
}
@@ -0,0 +1,28 @@
/*
* 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.db2.visitor;
import com.alibaba.druid.sql.visitor.SchemaStatVisitor;
import com.alibaba.druid.util.JdbcUtils;
public class DB2SchemaStatVisitor extends SchemaStatVisitor implements DB2ASTVisitor {
@Override
public String getDbType() {
return JdbcUtils.DB2;
}
}
@@ -15,6 +15,8 @@
*/
package com.alibaba.druid.sql.parser;
import com.alibaba.druid.sql.dialect.db2.parser.DB2ExprParser;
import com.alibaba.druid.sql.dialect.db2.parser.DB2StatementParser;
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlExprParser;
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;
import com.alibaba.druid.sql.dialect.oracle.parser.OracleExprParser;
@@ -55,6 +57,10 @@ public class SQLParserUtils {
if (JdbcUtils.H2.equals(dbType)) {
return new MySqlStatementParser(sql);
}
if (JdbcUtils.DB2.equals(dbType)) {
return new DB2StatementParser(sql);
}
return new SQLStatementParser(sql);
}
@@ -81,6 +87,10 @@ public class SQLParserUtils {
if (JdbcUtils.JTDS.equals(dbType)) {
return new SQLServerExprParser(sql);
}
if (JdbcUtils.DB2.equals(dbType)) {
return new DB2ExprParser(sql);
}
return new SQLExprParser(sql);
}
@@ -25,6 +25,7 @@ import com.alibaba.druid.sql.ast.expr.SQLBinaryOperator;
import com.alibaba.druid.sql.ast.expr.SQLInListExpr;
import com.alibaba.druid.sql.ast.expr.SQLLiteralExpr;
import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
import com.alibaba.druid.sql.dialect.db2.visitor.DB2ParameterizedOutputVisitor;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlParameterizedOutputVisitor;
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleParameterizedOutputVisitor;
import com.alibaba.druid.sql.dialect.postgresql.visitor.PGParameterizedOutputVisitor;
@@ -77,6 +78,10 @@ public class ParameterizedOutputVisitorUtils {
if (JdbcUtils.SQL_SERVER.equals(dbType) || JdbcUtils.JTDS.equals(dbType)) {
return new SQLServerParameterizedOutputVisitor(out);
}
if (JdbcUtils.DB2.equals(dbType)) {
return new DB2ParameterizedOutputVisitor(out);
}
return new ParameterizedOutputVisitor(out);
}
@@ -52,6 +52,7 @@ import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
import com.alibaba.druid.sql.ast.statement.SQLSelectItem;
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
import com.alibaba.druid.sql.dialect.db2.visitor.DB2EvalVisitor;
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlEvalVisitorImpl;
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleEvalVisitor;
import com.alibaba.druid.sql.dialect.postgresql.visitor.PGEvalVisitor;
@@ -167,6 +168,10 @@ public class SQLEvalVisitorUtils {
if (JdbcUtils.SQL_SERVER.equals(dbType)) {
return new SQLServerEvalVisitor();
}
if (JdbcUtils.DB2.equals(dbType)) {
return new DB2EvalVisitor();
}
return new SQLEvalVisitorImpl();
}