Merge pull request #763 from yakolee/master

support odps select ... limit...
This commit is contained in:
Yako
2014-12-31 00:00:34 +08:00
9 changed files with 291 additions and 40 deletions
@@ -241,6 +241,10 @@ public class SQLUtils {
if (JdbcUtils.DB2.equals(dbType)) {
return new DB2OutputVisitor(out);
}
if (JdbcUtils.ODPS.equals(dbType)) {
return new OdpsOutputVisitor(out);
}
return new SQLASTOutputVisitor(out);
}
@@ -0,0 +1,97 @@
/*
* 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.odps.ast;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLOrderBy;
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
import com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitor;
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
public class OdpsSelectQueryBlock extends SQLSelectQueryBlock {
private SQLOrderBy orderBy;
private SQLExpr limit;
public OdpsSelectQueryBlock(){
}
public SQLOrderBy getOrderBy() {
return orderBy;
}
public void setOrderBy(SQLOrderBy orderBy) {
this.orderBy = orderBy;
}
public SQLExpr getLimit() {
return limit;
}
public void setLimit(SQLExpr limit) {
if (limit != null) {
limit.setParent(this);
}
this.limit = limit;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((limit == null) ? 0 : limit.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null) return false;
if (getClass() != obj.getClass()) return false;
OdpsSelectQueryBlock other = (OdpsSelectQueryBlock) obj;
if (limit == null) {
if (other.limit != null) return false;
} else if (!limit.equals(other.limit)) return false;
return true;
}
@Override
protected void accept0(SQLASTVisitor visitor) {
if (visitor instanceof OdpsASTVisitor) {
accept0((OdpsASTVisitor) visitor);
return;
}
super.accept0(visitor);
}
public void accept0(OdpsASTVisitor visitor) {
if (visitor.visit(this)) {
acceptChild(visitor, this.selectList);
acceptChild(visitor, this.from);
acceptChild(visitor, this.where);
acceptChild(visitor, this.groupBy);
acceptChild(visitor, this.orderBy);
acceptChild(visitor, this.limit);
acceptChild(visitor, this.into);
}
visitor.endVisit(this);
}
}
@@ -42,6 +42,7 @@ public class OdpsLexer extends Lexer {
map.put("PARTITIONED", Token.PARTITIONED);
map.put("OVERWRITE", Token.OVERWRITE);
map.put("OVER", Token.OVER);
map.put("LIMIT", Token.LIMIT);
DEFAULT_ODPS_KEYWORDS = new Keywords(map);
}
@@ -16,20 +16,72 @@
package com.alibaba.druid.sql.dialect.odps.parser;
import com.alibaba.druid.sql.ast.SQLExpr;
import com.alibaba.druid.sql.ast.SQLSetQuantifier;
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
import com.alibaba.druid.sql.ast.statement.SQLSelectItem;
import com.alibaba.druid.sql.ast.statement.SQLSelectQuery;
import com.alibaba.druid.sql.dialect.odps.ast.OdpsSelectQueryBlock;
import com.alibaba.druid.sql.dialect.odps.ast.OdpsUDTFSQLSelectItem;
import com.alibaba.druid.sql.parser.SQLExprParser;
import com.alibaba.druid.sql.parser.SQLSelectParser;
import com.alibaba.druid.sql.parser.Token;
public class OdpsSelectParser extends SQLSelectParser {
public OdpsSelectParser(SQLExprParser exprParser){
super(exprParser.getLexer());
this.exprParser = exprParser;
}
@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();
}
OdpsSelectQueryBlock queryBlock = new OdpsSelectQueryBlock();
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);
queryBlock.setOrderBy(this.exprParser.parseOrderBy());
if (lexer.token() == Token.LIMIT) {
lexer.nextToken();
queryBlock.setLimit(this.expr());
}
return queryRest(queryBlock);
}
@Override
protected SQLSelectItem parseSelectItem() {
SQLExpr expr;
if (lexer.token() == Token.IDENTIFIER) {
@@ -43,36 +95,36 @@ public class OdpsSelectParser extends SQLSelectParser {
} else {
expr = expr();
}
if (lexer.token() == Token.AS) {
lexer.nextToken();
if (lexer.token() == Token.LPAREN) {
lexer.nextToken();
OdpsUDTFSQLSelectItem selectItem = new OdpsUDTFSQLSelectItem();
selectItem.setExpr(expr);
for (;;) {
String alias = lexer.stringVal();
lexer.nextToken();
selectItem.getAliasList().add(alias);
if (lexer.token() == Token.COMMA) {
lexer.nextToken();
continue;
}
break;
}
accept(Token.RPAREN);
return selectItem;
}
}
final String alias = as();
return new SQLSelectItem(expr, alias);
@@ -24,6 +24,7 @@ import com.alibaba.druid.sql.ast.statement.SQLAssignItem;
import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
import com.alibaba.druid.sql.ast.statement.SQLSelect;
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
import com.alibaba.druid.sql.ast.statement.SQLSetStatement;
import com.alibaba.druid.sql.ast.statement.SQLSubqueryTableSource;
import com.alibaba.druid.sql.dialect.odps.ast.OdpsInsert;
@@ -37,6 +38,7 @@ 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;
import com.alibaba.druid.util.JdbcConstants;
public class OdpsStatementParser extends SQLStatementParser {
@@ -48,6 +50,11 @@ public class OdpsStatementParser extends SQLStatementParser {
super(exprParser);
}
public SQLSelectStatement parseSelect() {
OdpsSelectParser selectParser = new OdpsSelectParser(this.exprParser);
return new SQLSelectStatement(selectParser.select(), JdbcConstants.ODPS);
}
public SQLCreateTableStatement parseCreateTable() {
SQLCreateTableParser parser = new OdpsCreateTableParser(this.exprParser);
return parser.parseCrateTable();
@@ -179,7 +186,7 @@ public class OdpsStatementParser extends SQLStatementParser {
accept(Token.TO);
if (lexer.token() == Token.USER) {
lexer.nextToken();
SQLName name = this.exprParser.name();
stmt.setUser(name);
return stmt;
@@ -187,13 +194,13 @@ public class OdpsStatementParser extends SQLStatementParser {
accept(Token.TABLE);
SQLExpr expr = this.exprParser.name();
stmt.setTable(new SQLExprTableSource(expr));
if (lexer.token() == Token.LPAREN) {
lexer.nextToken();
this.exprParser.names(stmt.getColumns(), stmt);
accept(Token.RPAREN);
}
return stmt;
} else {
SQLSetStatement stmt = new SQLSetStatement(getDbType());
@@ -18,6 +18,7 @@ package com.alibaba.druid.sql.dialect.odps.visitor;
import com.alibaba.druid.sql.dialect.odps.ast.OdpsCreateTableStatement;
import com.alibaba.druid.sql.dialect.odps.ast.OdpsInsert;
import com.alibaba.druid.sql.dialect.odps.ast.OdpsInsertStatement;
import com.alibaba.druid.sql.dialect.odps.ast.OdpsSelectQueryBlock;
import com.alibaba.druid.sql.dialect.odps.ast.OdpsSetLabelStatement;
import com.alibaba.druid.sql.dialect.odps.ast.OdpsShowPartitionsStmt;
import com.alibaba.druid.sql.dialect.odps.ast.OdpsShowStatisticStmt;
@@ -53,4 +54,8 @@ public interface OdpsASTVisitor extends SQLASTVisitor {
void endVisit(OdpsSetLabelStatement x);
boolean visit(OdpsSetLabelStatement x);
void endVisit(OdpsSelectQueryBlock x);
boolean visit(OdpsSelectQueryBlock x);
}
@@ -17,6 +17,8 @@ package com.alibaba.druid.sql.dialect.odps.visitor;
import java.util.List;
import com.alibaba.druid.sql.ast.SQLOrderBy;
import com.alibaba.druid.sql.ast.SQLSetQuantifier;
import com.alibaba.druid.sql.ast.SQLStatement;
import com.alibaba.druid.sql.ast.expr.SQLCaseExpr;
import com.alibaba.druid.sql.ast.statement.SQLAssignItem;
@@ -29,6 +31,7 @@ import com.alibaba.druid.sql.ast.statement.SQLSubqueryTableSource;
import com.alibaba.druid.sql.dialect.odps.ast.OdpsCreateTableStatement;
import com.alibaba.druid.sql.dialect.odps.ast.OdpsInsert;
import com.alibaba.druid.sql.dialect.odps.ast.OdpsInsertStatement;
import com.alibaba.druid.sql.dialect.odps.ast.OdpsSelectQueryBlock;
import com.alibaba.druid.sql.dialect.odps.ast.OdpsSetLabelStatement;
import com.alibaba.druid.sql.dialect.odps.ast.OdpsShowPartitionsStmt;
import com.alibaba.druid.sql.dialect.odps.ast.OdpsShowStatisticStmt;
@@ -92,7 +95,7 @@ public class OdpsOutputVisitor extends SQLASTOutputVisitor implements OdpsASTVis
}
print(")");
}
if (x.getLifecycle() != null) {
println();
print("LIFECYCLE ");
@@ -132,7 +135,6 @@ public class OdpsOutputVisitor extends SQLASTOutputVisitor implements OdpsASTVis
}
for (OdpsInsert insert : x.getItems()) {
println();
println();
insert.accept(this);
}
@@ -149,7 +151,7 @@ public class OdpsOutputVisitor extends SQLASTOutputVisitor implements OdpsASTVis
if (x.isOverwrite()) {
print("INSERT OVERWRITE TABLE ");
} else {
print("INSERT INTO OVERWRITE ");
print("INSERT INTO TABLE ");
}
x.getTableSource().accept(this);
@@ -251,7 +253,7 @@ public class OdpsOutputVisitor extends SQLASTOutputVisitor implements OdpsASTVis
return false;
}
@Override
public boolean visit(SQLJoinTableSource x) {
x.getLeft().accept(this);
@@ -288,7 +290,7 @@ public class OdpsOutputVisitor extends SQLASTOutputVisitor implements OdpsASTVis
@Override
public void endVisit(OdpsUDTFSQLSelectItem x) {
}
@Override
@@ -296,14 +298,14 @@ public class OdpsOutputVisitor extends SQLASTOutputVisitor implements OdpsASTVis
x.getExpr().accept(this);
print(" AS (");
for (int i = 0; i < x.getAliasList().size(); ++i) {
if (i != 0) {
print(", ");
}
print(x.getAliasList().get(i));
}
print(")");
return false;
@@ -311,7 +313,7 @@ public class OdpsOutputVisitor extends SQLASTOutputVisitor implements OdpsASTVis
@Override
public void endVisit(OdpsShowPartitionsStmt x) {
}
@Override
@@ -320,12 +322,12 @@ public class OdpsOutputVisitor extends SQLASTOutputVisitor implements OdpsASTVis
x.getTableSource().accept(this);
return false;
}
@Override
public void endVisit(OdpsShowStatisticStmt x) {
}
@Override
public boolean visit(OdpsShowStatisticStmt x) {
print("SHOW STATISTIC ");
@@ -335,7 +337,7 @@ public class OdpsOutputVisitor extends SQLASTOutputVisitor implements OdpsASTVis
@Override
public void endVisit(OdpsSetLabelStatement x) {
}
@Override
@@ -343,7 +345,7 @@ public class OdpsOutputVisitor extends SQLASTOutputVisitor implements OdpsASTVis
print("SET LABEL ");
print(x.getLabel());
print(" TO ");
if (x.getUser() != null) {
print("USER ");
x.getUser().accept(this);
@@ -356,7 +358,75 @@ public class OdpsOutputVisitor extends SQLASTOutputVisitor implements OdpsASTVis
print(")");
}
}
return false;
}
@Override
public void endVisit(OdpsSelectQueryBlock x) {
}
@Override
public boolean visit(OdpsSelectQueryBlock x) {
print("SELECT ");
if (SQLSetQuantifier.ALL == x.getDistionOption()) {
print("ALL ");
} else if (SQLSetQuantifier.DISTINCT == x.getDistionOption()) {
print("DISTINCT ");
} else if (SQLSetQuantifier.UNIQUE == x.getDistionOption()) {
print("UNIQUE ");
}
printSelectList(x.getSelectList());
if (x.getFrom() != null) {
println();
print("FROM ");
x.getFrom().accept(this);
}
if (x.getWhere() != null) {
println();
print("WHERE ");
x.getWhere().setParent(x);
x.getWhere().accept(this);
}
if (x.getGroupBy() != null) {
println();
x.getGroupBy().accept(this);
}
if (x.getOrderBy() != null) {
println();
x.getOrderBy().accept(this);
}
if (x.getLimit() != null) {
println();
print("LIMIT ");
x.getLimit().accept(this);
}
return false;
}
public boolean visit(SQLOrderBy x) {
int itemSize = x.getItems().size();
if (itemSize > 0) {
print("ORDER BY ");
incrementIndent();
for (int i = 0; i < itemSize; ++i) {
if (i != 0) {
println(", ");
}
x.getItems().get(i).accept(this);
}
decrementIndent();
}
return false;
}
}
@@ -16,16 +16,17 @@
package com.alibaba.druid.sql.dialect.odps.visitor;
import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement;
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
import com.alibaba.druid.sql.dialect.odps.ast.OdpsCreateTableStatement;
import com.alibaba.druid.sql.dialect.odps.ast.OdpsInsert;
import com.alibaba.druid.sql.dialect.odps.ast.OdpsInsertStatement;
import com.alibaba.druid.sql.dialect.odps.ast.OdpsSelectQueryBlock;
import com.alibaba.druid.sql.dialect.odps.ast.OdpsSetLabelStatement;
import com.alibaba.druid.sql.dialect.odps.ast.OdpsShowPartitionsStmt;
import com.alibaba.druid.sql.dialect.odps.ast.OdpsShowStatisticStmt;
import com.alibaba.druid.sql.dialect.odps.ast.OdpsUDTFSQLSelectItem;
import com.alibaba.druid.sql.visitor.SchemaStatVisitor;
public class OdpsSchemaStatVisitor extends SchemaStatVisitor implements OdpsASTVisitor {
@Override
@@ -40,7 +41,7 @@ public class OdpsSchemaStatVisitor extends SchemaStatVisitor implements OdpsASTV
@Override
public void endVisit(OdpsInsertStatement x) {
}
@Override
@@ -50,7 +51,7 @@ public class OdpsSchemaStatVisitor extends SchemaStatVisitor implements OdpsASTV
@Override
public void endVisit(OdpsInsert x) {
}
@Override
@@ -60,7 +61,7 @@ public class OdpsSchemaStatVisitor extends SchemaStatVisitor implements OdpsASTV
@Override
public void endVisit(OdpsUDTFSQLSelectItem x) {
}
@Override
@@ -70,29 +71,29 @@ public class OdpsSchemaStatVisitor extends SchemaStatVisitor implements OdpsASTV
@Override
public void endVisit(OdpsShowPartitionsStmt x) {
}
@Override
public boolean visit(OdpsShowPartitionsStmt x) {
return true;
}
@Override
public void endVisit(OdpsShowStatisticStmt x) {
}
@Override
public boolean visit(OdpsShowStatisticStmt x) {
return true;
}
@Override
public void endVisit(OdpsSetLabelStatement x) {
}
@Override
public boolean visit(OdpsSetLabelStatement x) {
if (x.getTable() != null) {
@@ -101,5 +102,14 @@ public class OdpsSchemaStatVisitor extends SchemaStatVisitor implements OdpsASTV
return false;
}
@Override
public void endVisit(OdpsSelectQueryBlock x) {
}
@Override
public boolean visit(OdpsSelectQueryBlock x) {
return this.visit((SQLSelectQueryBlock) x);
}
}
@@ -20,6 +20,7 @@ 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.odps.parser.OdpsExprParser;
import com.alibaba.druid.sql.dialect.odps.parser.OdpsStatementParser;
import com.alibaba.druid.sql.dialect.oracle.parser.OracleExprParser;
import com.alibaba.druid.sql.dialect.oracle.parser.OracleStatementParser;
import com.alibaba.druid.sql.dialect.postgresql.parser.PGExprParser;
@@ -58,6 +59,10 @@ public class SQLParserUtils {
if (JdbcUtils.DB2.equals(dbType)) {
return new DB2StatementParser(sql);
}
if (JdbcUtils.ODPS.equals(dbType)) {
return new OdpsStatementParser(sql);
}
return new SQLStatementParser(sql);
}