Repository: drill Updated Branches: refs/heads/master 68c933c75 -> 4baf9e70b
DRILL-3182, DRILL-3188, DRILL-3195: Window function with DISTINCT qualifier is disabled; Disable unsupported window frames; Window functions NTILE, LAG, LEAD, FIRST_VALUE, LAST_VALUE are disabled Project: http://git-wip-us.apache.org/repos/asf/drill/repo Commit: http://git-wip-us.apache.org/repos/asf/drill/commit/4baf9e70 Tree: http://git-wip-us.apache.org/repos/asf/drill/tree/4baf9e70 Diff: http://git-wip-us.apache.org/repos/asf/drill/diff/4baf9e70 Branch: refs/heads/master Commit: 4baf9e70b19f78a19d59fc6670de00c871f9d609 Parents: 68c933c Author: Hsuan-Yi Chu <[email protected]> Authored: Tue Jun 9 14:56:08 2015 -0700 Committer: Aman Sinha <[email protected]> Committed: Mon Jun 15 17:11:08 2015 -0700 ---------------------------------------------------------------------- .../sql/parser/UnsupportedOperatorsVisitor.java | 91 +++++++++++- .../apache/drill/exec/TestWindowFunctions.java | 138 +++++++++++++++++-- 2 files changed, 213 insertions(+), 16 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/drill/blob/4baf9e70/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/UnsupportedOperatorsVisitor.java ---------------------------------------------------------------------- diff --git a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/UnsupportedOperatorsVisitor.java b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/UnsupportedOperatorsVisitor.java index f3c54cc..544a838 100644 --- a/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/UnsupportedOperatorsVisitor.java +++ b/exec/java-exec/src/main/java/org/apache/drill/exec/planner/sql/parser/UnsupportedOperatorsVisitor.java @@ -22,6 +22,7 @@ import org.apache.drill.exec.exception.UnsupportedOperatorCollector; import org.apache.drill.exec.ops.QueryContext; import org.apache.drill.exec.work.foreman.SqlUnsupportedException; +import org.apache.calcite.sql.SqlSelectKeyword; import org.apache.calcite.sql.SqlIdentifier; import org.apache.calcite.sql.SqlSelect; import org.apache.calcite.sql.SqlWindow; @@ -99,6 +100,84 @@ public class UnsupportedOperatorsVisitor extends SqlShuttle { throw new UnsupportedOperationException(); } + // DRILL-3182, DRILL-3195 + SqlCall over = (SqlCall) nodeInSelectList; + if(over.getOperandList().get(0) instanceof SqlCall) { + SqlCall function = (SqlCall) over.getOperandList().get(0); + + // DRILL-3195: + // The following window functions are temporarily disabled + // NTILE(), LAG(), LEAD(), FIRST_VALUE(), LAST_VALUE() + String functionName = function.getOperator().getName().toUpperCase(); + switch(functionName) { + case "NTILE": + case "LAG": + case "LEAD": + case "FIRST_VALUE": + case "LAST_VALUE": + unsupportedOperatorCollector.setException(SqlUnsupportedException.ExceptionType.FUNCTION, + "The window function " + functionName + " is not supported\n" + + "See Apache Drill JIRA: DRILL-3195"); + throw new UnsupportedOperationException(); + + default: + break; + } + + + // DRILL-3182 + // Window function with DISTINCT qualifier is temporarily disabled + if(function.getFunctionQuantifier() != null + && function.getFunctionQuantifier().getValue() == SqlSelectKeyword.DISTINCT) { + unsupportedOperatorCollector.setException(SqlUnsupportedException.ExceptionType.FUNCTION, + "DISTINCT for window aggregate functions is not currently supported\n" + + "See Apache Drill JIRA: DRILL-3182"); + throw new UnsupportedOperationException(); + } + } + + // DRILL-3188 + // Disable frame which is other than the default + // (i.e., BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) + if(((SqlCall) nodeInSelectList).operand(1) instanceof SqlWindow) { + SqlWindow window = (SqlWindow) ((SqlCall) nodeInSelectList).operand(1); + + SqlNode lowerBound = window.getLowerBound(); + SqlNode upperBound = window.getUpperBound(); + + // If no frame is specified + // it is a default frame + boolean isSupported = (lowerBound == null && upperBound == null); + + // When OVER clause contain an ORDER BY clause the following frames are equivalent to the default frame: + // RANGE UNBOUNDED PRECEDING + // RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW + if(window.getOrderList().size() != 0 + && !window.isRows() + && SqlWindow.isUnboundedPreceding(lowerBound) + && (upperBound == null || SqlWindow.isCurrentRow(upperBound))) { + isSupported = true; + } + + // When OVER clause doesn't contain an ORDER BY clause, the following are equivalent to the default frame: + // RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + // ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING + if(window.getOrderList().size() == 0 + && SqlWindow.isUnboundedPreceding(lowerBound) + && SqlWindow.isUnboundedFollowing(upperBound)) { + isSupported = true; + } + + if(!isSupported) { + unsupportedOperatorCollector.setException(SqlUnsupportedException.ExceptionType.FUNCTION, + "This type of window frame is currently not supported \n" + + "See Apache Drill JIRA: DRILL-3188"); + throw new UnsupportedOperationException(); + } + } + + // DRILL-3196 + // Disable multiple partitions in a SELECT-CLAUSE SqlNode window = ((SqlCall) nodeInSelectList).operand(1); // Partition window is referenced as a SqlIdentifier, @@ -119,12 +198,12 @@ public class UnsupportedOperatorsVisitor extends SqlShuttle { if(definedWindow == null) { definedWindow = window; } else { - if(!definedWindow.equalsDeep(window, false)) { - unsupportedOperatorCollector.setException(SqlUnsupportedException.ExceptionType.FUNCTION, - "Multiple window definitions in a single SELECT list is not currently supported \n" + - "See Apache Drill JIRA: DRILL-3196"); - throw new UnsupportedOperationException(); - } + if(!definedWindow.equalsDeep(window, false)) { + unsupportedOperatorCollector.setException(SqlUnsupportedException.ExceptionType.FUNCTION, + "Multiple window definitions in a single SELECT list is not currently supported \n" + + "See Apache Drill JIRA: DRILL-3196"); + throw new UnsupportedOperationException(); + } } } } http://git-wip-us.apache.org/repos/asf/drill/blob/4baf9e70/exec/java-exec/src/test/java/org/apache/drill/exec/TestWindowFunctions.java ---------------------------------------------------------------------- diff --git a/exec/java-exec/src/test/java/org/apache/drill/exec/TestWindowFunctions.java b/exec/java-exec/src/test/java/org/apache/drill/exec/TestWindowFunctions.java index fc75d73..2ec2481 100644 --- a/exec/java-exec/src/test/java/org/apache/drill/exec/TestWindowFunctions.java +++ b/exec/java-exec/src/test/java/org/apache/drill/exec/TestWindowFunctions.java @@ -34,9 +34,7 @@ public class TestWindowFunctions extends BaseTestQuery { final String query = "explain plan for select sum(a2) over(partition by a2), count(*) over(partition by a2) \n" + "from cp.`tpch/nation.parquet`"; - test("alter session set `window.enable` = true"); test(query); - test("alter session set `window.enable` = false"); } @Test // DRILL-3196 @@ -45,9 +43,7 @@ public class TestWindowFunctions extends BaseTestQuery { "from cp.`tpch/nation.parquet` \n" + "window w as (partition by a2 order by a2)"; - test("alter session set `window.enable` = true"); test(query); - test("alter session set `window.enable` = false"); } @Test(expected = UnsupportedFunctionException.class) // DRILL-3196 @@ -56,9 +52,7 @@ public class TestWindowFunctions extends BaseTestQuery { final String query = "explain plan for select sum(a2) over(partition by a2), count(*) over(partition by a2,b2,c2) \n" + "from cp.`tpch/nation.parquet`"; - test("alter session set `window.enable` = true"); test(query); - test("alter session set `window.enable` = false"); } catch(UserException ex) { throwAsUnsupportedException(ex); throw ex; @@ -71,9 +65,7 @@ public class TestWindowFunctions extends BaseTestQuery { final String query = "explain plan for select sum(a2) over(partition by a2 order by a2), count(*) over(partition by a2 order by b2) \n" + "from cp.`tpch/nation.parquet`"; - test("alter session set `window.enable` = true"); test(query); - test("alter session set `window.enable` = false"); } catch(UserException ex) { throwAsUnsupportedException(ex); throw ex; @@ -87,12 +79,138 @@ public class TestWindowFunctions extends BaseTestQuery { "from cp.`tpch/nation.parquet` \n" + "window w as (partition by a2, b2, c2)"; - test("alter session set `window.enable` = true"); test(query); - test("alter session set `window.enable` = false"); } catch(UserException ex) { throwAsUnsupportedException(ex); throw ex; } } + + @Test(expected = UnsupportedFunctionException.class) // DRILL-3182 + public void testWindowFunctionWithDistinct() throws Exception { + try { + final String query = "explain plan for select a2, count(distinct b2) over(partition by a2) \n" + + "from cp.`tpch/nation.parquet`"; + + test(query); + } catch(UserException ex) { + throwAsUnsupportedException(ex); + throw ex; + } + } + + @Test(expected = UnsupportedFunctionException.class) // DRILL-3195 + public void testWindowFunctionNTILE() throws Exception { + try { + final String query = "explain plan for select NTILE(1) over(partition by n_name order by n_name) \n" + + "from cp.`tpch/nation.parquet`"; + + test(query); + } catch(UserException ex) { + throwAsUnsupportedException(ex); + throw ex; + } + } + + @Test(expected = UnsupportedFunctionException.class) // DRILL-3195 + public void testWindowFunctionLAG() throws Exception { + try { + final String query = "explain plan for select LAG(n_nationKey, 1) over(partition by n_name order by n_name) \n" + + "from cp.`tpch/nation.parquet`"; + + test(query); + } catch(UserException ex) { + throwAsUnsupportedException(ex); + throw ex; + } + } + + @Test(expected = UnsupportedFunctionException.class) // DRILL-3195 + public void testWindowFunctionLEAD() throws Exception { + try { + final String query = "explain plan for select LEAD(n_nationKey, 1) over(partition by n_name order by n_name) \n" + + "from cp.`tpch/nation.parquet`"; + + test(query); + } catch(UserException ex) { + throwAsUnsupportedException(ex); + throw ex; + } + } + + @Test(expected = UnsupportedFunctionException.class) // DRILL-3195 + public void testWindowFunctionFIRST_VALUE() throws Exception { + try { + final String query = "explain plan for select FIRST_VALUE(n_nationKey) over(partition by n_name order by n_name) \n" + + "from cp.`tpch/nation.parquet`"; + + test(query); + } catch(UserException ex) { + throwAsUnsupportedException(ex); + throw ex; + } + } + + @Test(expected = UnsupportedFunctionException.class) // DRILL-3195 + public void testWindowFunctionLAST_VALUE() throws Exception { + try { + final String query = "explain plan for select LAST_VALUE(n_nationKey) over(partition by n_name order by n_name) \n" + + "from cp.`tpch/nation.parquet`"; + + test(query); + } catch(UserException ex) { + throwAsUnsupportedException(ex); + throw ex; + } + } + + @Test(expected = UnsupportedFunctionException.class) // DRILL-3188 + public void testWindowFrame() throws Exception { + try { + final String query = "select a2, sum(a2) over(partition by a2 order by a2 rows between 1 preceding and 1 following ) \n" + + "from cp.`tpch/nation.parquet` t \n" + + "order by a2"; + + test(query); + } catch(UserException ex) { + throwAsUnsupportedException(ex); + throw ex; + } + } + + @Test(expected = UnsupportedFunctionException.class) // DRILL-3188 + public void testRowsUnboundedPreceding() throws Exception { + try { + final String query = "explain plan for select sum(n_nationKey) over(partition by n_nationKey order by n_nationKey \n" + + "rows UNBOUNDED PRECEDING)" + + "from cp.`tpch/nation.parquet` t \n" + + "order by n_nationKey"; + + test(query); + } catch(UserException ex) { + throwAsUnsupportedException(ex); + throw ex; + } + } + + @Test // DRILL-3188 + public void testWindowFrameEquivalentToDefault() throws Exception { + final String query1 = "explain plan for select sum(n_nationKey) over(partition by n_nationKey order by n_nationKey) \n" + + "from cp.`tpch/nation.parquet` t \n" + + "order by n_nationKey"; + + final String query2 = "explain plan for select sum(n_nationKey) over(partition by n_nationKey order by n_nationKey \n" + + "range between unbounded preceding and current row) \n" + + "from cp.`tpch/nation.parquet` t \n" + + "order by n_nationKey"; + + final String query3 = "explain plan for select sum(n_nationKey) over(partition by n_nationKey \n" + + "rows BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)" + + "from cp.`tpch/nation.parquet` t \n" + + "order by n_nationKey"; + + test(query1); + test(query2); + test(query3); + } }
