From 27e6b8f9f49fba74b4d0ed3a928b49e78095ea8d Mon Sep 17 00:00:00 2001 From: wenshao Date: Sun, 9 Oct 2016 13:28:58 +0800 Subject: [PATCH] improved sql parser, support over winding_clause. --- .../druid/sql/parser/SQLExprParser.java | 30 ++++++++-- .../sql/visitor/SQLASTOutputVisitor.java | 16 ++++- .../sql/odps/OdpsSelectTest_over_rows_3.java | 58 +++++++++++++++++++ .../sql/odps/OdpsSelectTest_over_rows_4.java | 58 +++++++++++++++++++ .../sql/odps/OdpsSelectTest_over_rows_5.java | 58 +++++++++++++++++++ 5 files changed, 211 insertions(+), 9 deletions(-) create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsSelectTest_over_rows_3.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsSelectTest_over_rows_4.java create mode 100644 src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsSelectTest_over_rows_5.java diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java index 92c8b5c6cf..c8993da561 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLExprParser.java @@ -1116,15 +1116,33 @@ public class SQLExprParser extends SQLParser { } } else { - SQLIntegerExpr rowsExpr = (SQLIntegerExpr) this.primary(); - over.setWindowing(rowsExpr); - if (identifierEquals("PRECEDING")) { - over.setWindowingPreceding(true); + if (identifierEquals("CURRENT")) { lexer.nextToken(); - } else if (identifierEquals("FOLLOWING")) { - over.setWindowingFollowing(true); + acceptIdentifier("ROW"); + over.setWindowing(new SQLIdentifierExpr("CURRENT ROW")); + } else if (identifierEquals("UNBOUNDED")) { lexer.nextToken(); + over.setWindowing(new SQLIdentifierExpr("UNBOUNDED")); + + if (identifierEquals("PRECEDING")) { + over.setWindowingPreceding(true); + lexer.nextToken(); + } else if (identifierEquals("FOLLOWING")) { + over.setWindowingFollowing(true); + lexer.nextToken(); + } + } else { + SQLIntegerExpr rowsExpr = (SQLIntegerExpr) this.primary(); + over.setWindowing(rowsExpr); + + if (identifierEquals("PRECEDING")) { + over.setWindowingPreceding(true); + lexer.nextToken(); + } else if (identifierEquals("FOLLOWING")) { + over.setWindowingFollowing(true); + lexer.nextToken(); + } } } } diff --git a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java index 41984b4520..e7fc19485c 100644 --- a/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/visitor/SQLASTOutputVisitor.java @@ -1760,7 +1760,8 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet print0(ucase ? " RANGE " : " range "); } - x.getWindowing().accept(this); + printWindowingExpr(x.getWindowing()); + if (x.isWindowingPreceding()) { print0(ucase ? " PRECEDING" : " preceding"); } else if (x.isWindowingFollowing()) { @@ -1775,7 +1776,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet print0(ucase ? " RANGE BETWEEN " : " range between "); } - x.getWindowingBetweenBegin().accept(this); + printWindowingExpr(x.getWindowingBetweenBegin()); if (x.isWindowingBetweenBeginPreceding()) { print0(ucase ? " PRECEDING" : " preceding"); @@ -1785,7 +1786,7 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet print0(ucase ? " AND " : " and "); - x.getWindowingBetweenEnd().accept(this); + printWindowingExpr(x.getWindowingBetweenEnd()); if (x.isWindowingBetweenEndPreceding()) { print0(ucase ? " PRECEDING" : " preceding"); @@ -1797,6 +1798,15 @@ public class SQLASTOutputVisitor extends SQLASTVisitorAdapter implements Paramet print(')'); return false; } + + void printWindowingExpr(SQLExpr expr) { + if (expr instanceof SQLIdentifierExpr) { + String ident = ((SQLIdentifierExpr) expr).getName(); + print0(ucase ? ident : ident.toLowerCase()); + } else { + expr.accept(this); + } + } @Override public boolean visit(SQLKeep x) { diff --git a/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsSelectTest_over_rows_3.java b/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsSelectTest_over_rows_3.java new file mode 100644 index 0000000000..383f954955 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsSelectTest_over_rows_3.java @@ -0,0 +1,58 @@ +/* + * 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.odps; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.visitor.SchemaStatVisitor; +import com.alibaba.druid.util.JdbcConstants; +import junit.framework.TestCase; +import org.junit.Assert; + +import java.util.List; + +public class OdpsSelectTest_over_rows_3 extends TestCase { + + public void test_select() throws Exception { + String sql = "SELECT sum(c) over(order by ds rows current row) s, ds FROM t1";// + Assert.assertEquals("SELECT SUM(c) OVER (ORDER BY ds ROWS CURRENT ROW) AS s\n" + + "\t, ds\n" + + "FROM t1", SQLUtils.formatOdps(sql)); + Assert.assertEquals("select sum(c) over (order by ds rows current row) as s\n" + + "\t, ds\n" + + "from t1", SQLUtils.formatOdps(sql, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION)); + + List statementList = SQLUtils.parseStatements(sql, JdbcConstants.ODPS); + SQLStatement stmt = statementList.get(0); + + Assert.assertEquals(1, statementList.size()); + + SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.ODPS); + 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(2, visitor.getColumns().size()); + Assert.assertEquals(0, visitor.getConditions().size()); + +// Assert.assertTrue(visitor.getColumns().contains(new Column("abc", "name"))); + } + +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsSelectTest_over_rows_4.java b/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsSelectTest_over_rows_4.java new file mode 100644 index 0000000000..3d92dfc7cf --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsSelectTest_over_rows_4.java @@ -0,0 +1,58 @@ +/* + * 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.odps; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.visitor.SchemaStatVisitor; +import com.alibaba.druid.util.JdbcConstants; +import junit.framework.TestCase; +import org.junit.Assert; + +import java.util.List; + +public class OdpsSelectTest_over_rows_4 extends TestCase { + + public void test_select() throws Exception { + String sql = "SELECT sum(c) over(order by ds rows UNBOUNDED PRECEDING) s, ds FROM t1";// + Assert.assertEquals("SELECT SUM(c) OVER (ORDER BY ds ROWS UNBOUNDED PRECEDING) AS s\n" + + "\t, ds\n" + + "FROM t1", SQLUtils.formatOdps(sql)); + Assert.assertEquals("select sum(c) over (order by ds rows unbounded preceding) as s\n" + + "\t, ds\n" + + "from t1", SQLUtils.formatOdps(sql, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION)); + + List statementList = SQLUtils.parseStatements(sql, JdbcConstants.ODPS); + SQLStatement stmt = statementList.get(0); + + Assert.assertEquals(1, statementList.size()); + + SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.ODPS); + 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(2, visitor.getColumns().size()); + Assert.assertEquals(0, visitor.getConditions().size()); + +// Assert.assertTrue(visitor.getColumns().contains(new Column("abc", "name"))); + } + +} diff --git a/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsSelectTest_over_rows_5.java b/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsSelectTest_over_rows_5.java new file mode 100644 index 0000000000..a505fccbc8 --- /dev/null +++ b/src/test/java/com/alibaba/druid/bvt/sql/odps/OdpsSelectTest_over_rows_5.java @@ -0,0 +1,58 @@ +/* + * 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.odps; + +import com.alibaba.druid.sql.SQLUtils; +import com.alibaba.druid.sql.ast.SQLStatement; +import com.alibaba.druid.sql.visitor.SchemaStatVisitor; +import com.alibaba.druid.util.JdbcConstants; +import junit.framework.TestCase; +import org.junit.Assert; + +import java.util.List; + +public class OdpsSelectTest_over_rows_5 extends TestCase { + + public void test_select() throws Exception { + String sql = "SELECT sum(c) over(order by ds rows UNBOUNDED following) s, ds FROM t1";// + Assert.assertEquals("SELECT SUM(c) OVER (ORDER BY ds ROWS UNBOUNDED FOLLOWING) AS s\n" + + "\t, ds\n" + + "FROM t1", SQLUtils.formatOdps(sql)); + Assert.assertEquals("select sum(c) over (order by ds rows unbounded following) as s\n" + + "\t, ds\n" + + "from t1", SQLUtils.formatOdps(sql, SQLUtils.DEFAULT_LCASE_FORMAT_OPTION)); + + List statementList = SQLUtils.parseStatements(sql, JdbcConstants.ODPS); + SQLStatement stmt = statementList.get(0); + + Assert.assertEquals(1, statementList.size()); + + SchemaStatVisitor visitor = SQLUtils.createSchemaStatVisitor(JdbcConstants.ODPS); + 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(2, visitor.getColumns().size()); + Assert.assertEquals(0, visitor.getConditions().size()); + +// Assert.assertTrue(visitor.getColumns().contains(new Column("abc", "name"))); + } + +}