mirror of
https://github.com/alibaba/druid.git
synced 2023-03-04 19:17:16 +00:00
Merge pull request #1050 from wenshao/master
odps sql parser support lateral view & bug fixed for issue 1049
This commit is contained in:
@@ -0,0 +1,59 @@
|
||||
package com.alibaba.druid.sql.dialect.odps.ast;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.alibaba.druid.sql.ast.SQLName;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLTableSourceImpl;
|
||||
import com.alibaba.druid.sql.dialect.odps.visitor.OdpsASTVisitor;
|
||||
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
|
||||
|
||||
public class OdpsLateralViewTableSource extends SQLTableSourceImpl {
|
||||
|
||||
private SQLTableSource tableSource;
|
||||
|
||||
private SQLMethodInvokeExpr method;
|
||||
|
||||
private List<SQLName> columns = new ArrayList<SQLName>(2);
|
||||
|
||||
@Override
|
||||
protected void accept0(SQLASTVisitor visitor) {
|
||||
accept0((OdpsASTVisitor) visitor);
|
||||
}
|
||||
|
||||
protected void accept0(OdpsASTVisitor visitor) {
|
||||
if (visitor.visit(this)) {
|
||||
acceptChild(visitor, tableSource);
|
||||
acceptChild(visitor, method);
|
||||
acceptChild(visitor, columns);
|
||||
}
|
||||
visitor.endVisit(this);
|
||||
}
|
||||
|
||||
public SQLTableSource getTableSource() {
|
||||
return tableSource;
|
||||
}
|
||||
|
||||
public void setTableSource(SQLTableSource tableSource) {
|
||||
this.tableSource = tableSource;
|
||||
}
|
||||
|
||||
public SQLMethodInvokeExpr getMethod() {
|
||||
return method;
|
||||
}
|
||||
|
||||
public void setMethod(SQLMethodInvokeExpr method) {
|
||||
this.method = method;
|
||||
}
|
||||
|
||||
public List<SQLName> getColumns() {
|
||||
return columns;
|
||||
}
|
||||
|
||||
public void setColumns(List<SQLName> columns) {
|
||||
this.columns = columns;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -18,8 +18,11 @@ package com.alibaba.druid.sql.dialect.odps.parser;
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.SQLOrderingSpecification;
|
||||
import com.alibaba.druid.sql.ast.SQLSetQuantifier;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectQuery;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLTableSource;
|
||||
import com.alibaba.druid.sql.dialect.odps.ast.OdpsLateralViewTableSource;
|
||||
import com.alibaba.druid.sql.dialect.odps.ast.OdpsSelectQueryBlock;
|
||||
import com.alibaba.druid.sql.parser.SQLExprParser;
|
||||
import com.alibaba.druid.sql.parser.SQLSelectParser;
|
||||
@@ -121,5 +124,39 @@ public class OdpsSelectParser extends SQLSelectParser {
|
||||
|
||||
return queryRest(queryBlock);
|
||||
}
|
||||
|
||||
protected SQLTableSource parseTableSourceRest(SQLTableSource tableSource) {
|
||||
tableSource = super.parseTableSourceRest(tableSource);
|
||||
|
||||
if ("LATERAL".equalsIgnoreCase(tableSource.getAlias()) && lexer.token() == Token.VIEW) {
|
||||
return parseLateralView(tableSource);
|
||||
}
|
||||
|
||||
if (identifierEquals("LATERAL")) {
|
||||
lexer.nextToken();
|
||||
return parseLateralView(tableSource);
|
||||
}
|
||||
|
||||
return tableSource;
|
||||
}
|
||||
|
||||
protected SQLTableSource parseLateralView(SQLTableSource tableSource) {
|
||||
accept(Token.VIEW);
|
||||
tableSource.setAlias(null);
|
||||
OdpsLateralViewTableSource lateralViewTabSrc = new OdpsLateralViewTableSource();
|
||||
lateralViewTabSrc.setTableSource(tableSource);
|
||||
|
||||
SQLMethodInvokeExpr udtf = (SQLMethodInvokeExpr) this.exprParser.expr();
|
||||
lateralViewTabSrc.setMethod(udtf);
|
||||
|
||||
String alias = as();
|
||||
lateralViewTabSrc.setAlias(alias);
|
||||
|
||||
accept(Token.AS);
|
||||
|
||||
this.exprParser.names(lateralViewTabSrc.getColumns());
|
||||
|
||||
return parseTableSourceRest(lateralViewTabSrc);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.alibaba.druid.sql.dialect.odps.ast.OdpsDescStmt;
|
||||
import com.alibaba.druid.sql.dialect.odps.ast.OdpsGrantStmt;
|
||||
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.OdpsLateralViewTableSource;
|
||||
import com.alibaba.druid.sql.dialect.odps.ast.OdpsListStmt;
|
||||
import com.alibaba.druid.sql.dialect.odps.ast.OdpsReadStatement;
|
||||
import com.alibaba.druid.sql.dialect.odps.ast.OdpsRemoveStatisticStatement;
|
||||
@@ -123,4 +124,8 @@ public interface OdpsASTVisitor extends SQLASTVisitor {
|
||||
void endVisit(OdpsDescStmt x);
|
||||
|
||||
boolean visit(OdpsDescStmt x);
|
||||
|
||||
void endVisit(OdpsLateralViewTableSource x);
|
||||
|
||||
boolean visit(OdpsLateralViewTableSource x);
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import com.alibaba.druid.sql.dialect.odps.ast.OdpsDescStmt;
|
||||
import com.alibaba.druid.sql.dialect.odps.ast.OdpsGrantStmt;
|
||||
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.OdpsLateralViewTableSource;
|
||||
import com.alibaba.druid.sql.dialect.odps.ast.OdpsListStmt;
|
||||
import com.alibaba.druid.sql.dialect.odps.ast.OdpsReadStatement;
|
||||
import com.alibaba.druid.sql.dialect.odps.ast.OdpsRemoveStatisticStatement;
|
||||
@@ -256,5 +257,15 @@ public class OdpsASTVisitorAdapter extends SQLASTVisitorAdapter implements OdpsA
|
||||
public boolean visit(OdpsDescStmt x) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endVisit(OdpsLateralViewTableSource x) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(OdpsLateralViewTableSource x) {
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -41,6 +41,7 @@ import com.alibaba.druid.sql.dialect.odps.ast.OdpsDescStmt;
|
||||
import com.alibaba.druid.sql.dialect.odps.ast.OdpsGrantStmt;
|
||||
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.OdpsLateralViewTableSource;
|
||||
import com.alibaba.druid.sql.dialect.odps.ast.OdpsListStmt;
|
||||
import com.alibaba.druid.sql.dialect.odps.ast.OdpsReadStatement;
|
||||
import com.alibaba.druid.sql.dialect.odps.ast.OdpsRemoveStatisticStatement;
|
||||
@@ -847,4 +848,24 @@ public class OdpsOutputVisitor extends SQLASTOutputVisitor implements OdpsASTVis
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endVisit(OdpsLateralViewTableSource x) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(OdpsLateralViewTableSource x) {
|
||||
x.getTableSource().accept(this);
|
||||
incrementIndent();
|
||||
println();
|
||||
print0(ucase ? "LATERAL VIEW " : "lateral view ");
|
||||
x.getMethod().accept(this);
|
||||
print(' ');
|
||||
print0(x.getAlias());
|
||||
print0(ucase ? " AS " : " as ");
|
||||
printAndAccept(x.getColumns(), ", ");
|
||||
decrementIndent();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.alibaba.druid.sql.dialect.odps.ast.OdpsDescStmt;
|
||||
import com.alibaba.druid.sql.dialect.odps.ast.OdpsGrantStmt;
|
||||
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.OdpsLateralViewTableSource;
|
||||
import com.alibaba.druid.sql.dialect.odps.ast.OdpsListStmt;
|
||||
import com.alibaba.druid.sql.dialect.odps.ast.OdpsReadStatement;
|
||||
import com.alibaba.druid.sql.dialect.odps.ast.OdpsRemoveStatisticStatement;
|
||||
@@ -261,4 +262,14 @@ public class OdpsSchemaStatVisitor extends SchemaStatVisitor implements OdpsASTV
|
||||
public boolean visit(OdpsDescStmt x) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void endVisit(OdpsLateralViewTableSource x) {
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(OdpsLateralViewTableSource x) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -389,10 +389,9 @@ public class SQLExprParser extends SQLParser {
|
||||
SQLExpr notTarget = expr();
|
||||
|
||||
accept(Token.RPAREN);
|
||||
notTarget = exprRest(notTarget);
|
||||
|
||||
notTarget = relationalRest(notTarget);
|
||||
sqlExpr = new SQLNotExpr(notTarget);
|
||||
|
||||
|
||||
return primaryRest(sqlExpr);
|
||||
} else {
|
||||
SQLExpr restExpr = relational();
|
||||
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* Copyright 1999-2101 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.bvt.sql.mysql;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.junit.Assert;
|
||||
|
||||
import com.alibaba.druid.sql.MysqlTest;
|
||||
import com.alibaba.druid.sql.SQLUtils;
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser;
|
||||
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlSchemaStatVisitor;
|
||||
|
||||
public class MySqlSelectTest_24 extends MysqlTest {
|
||||
|
||||
public void test_0() throws Exception {
|
||||
String sql = "select * from company where id=1 and not (name='e') and addr='a'";
|
||||
|
||||
|
||||
MySqlStatementParser parser = new MySqlStatementParser(sql);
|
||||
List<SQLStatement> statementList = parser.parseStatementList();
|
||||
SQLStatement stmt = statementList.get(0);
|
||||
print(statementList);
|
||||
|
||||
Assert.assertEquals(1, statementList.size());
|
||||
|
||||
MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();
|
||||
stmt.accept(visitor);
|
||||
|
||||
System.out.println("Tables : " + visitor.getTables());
|
||||
System.out.println("fields : " + visitor.getColumns());
|
||||
System.out.println("coditions : " + visitor.getConditions());
|
||||
System.out.println("orderBy : " + visitor.getOrderByColumns());
|
||||
|
||||
Assert.assertEquals(1, visitor.getTables().size());
|
||||
Assert.assertEquals(4, visitor.getColumns().size());
|
||||
Assert.assertEquals(3, visitor.getConditions().size());
|
||||
Assert.assertEquals(0, visitor.getOrderByColumns().size());
|
||||
|
||||
String output = SQLUtils.toMySqlString(stmt);
|
||||
Assert.assertEquals("SELECT *"
|
||||
+ "\nFROM company"
|
||||
+ "\nWHERE id = 1"
|
||||
+ "\n\tAND NOT name = 'e'"
|
||||
+ "\n\tAND addr = 'a'", //
|
||||
output);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
package com.alibaba.druid.bvt.sql.odps;
|
||||
|
||||
import org.junit.Assert;
|
||||
|
||||
import com.alibaba.druid.sql.SQLUtils;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
public class OdpsFormatCommentTest28 extends TestCase {
|
||||
public void test_drop_function() throws Exception {
|
||||
String sql = "SELECT pageid, adid FROM pageAds LATERAL VIEW explode(adid_list) adTable AS adid;";
|
||||
Assert.assertEquals("SELECT pageid"
|
||||
+ "\n\t, adid"
|
||||
+ "\nFROM pageAds"
|
||||
+ "\n\tLATERAL VIEW EXPLODE(adid_list) adTable AS adid;", SQLUtils.formatOdps(sql));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user