This is an automated email from the ASF dual-hosted git repository.

huor pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hawq.git


The following commit(s) were added to refs/heads/master by this push:
     new 7f4f99a  HAWQ-1697. fix bug of window func unsafe push down
7f4f99a is described below

commit 7f4f99a95b1173cd1779d9ad128aad6e9a033ea0
Author: ZongtianHou <[email protected]>
AuthorDate: Thu Apr 11 10:43:16 2019 +0800

    HAWQ-1697. fix bug of window func unsafe push down
---
 src/backend/optimizer/path/allpaths.c    | 78 ++++++++++++++++++++++++++++++++
 src/backend/optimizer/util/clauses.c     | 22 +++++++--
 src/test/feature/planner/ans/subplan.ans | 15 ++++++
 src/test/feature/planner/sql/subplan.sql |  7 +++
 4 files changed, 119 insertions(+), 3 deletions(-)

diff --git a/src/backend/optimizer/path/allpaths.c 
b/src/backend/optimizer/path/allpaths.c
index 689c30a..6bc069c 100644
--- a/src/backend/optimizer/path/allpaths.c
+++ b/src/backend/optimizer/path/allpaths.c
@@ -97,6 +97,8 @@ static void compare_tlist_datatypes(List *tlist, List 
*colTypes,
                                                bool *differentTypes);
 static bool qual_is_pushdown_safe(Query *subquery, Index rti, Node *qual,
                                          bool *differentTypes);
+static bool qual_contains_winref(Query *topquery, Index rti, Node *qual);
+static bool qual_is_pushdown_safe_set_operation(Query *subquery, Node *qual);
 static void subquery_push_qual(Query *subquery,
                                   RangeTblEntry *rte, Index rti, Node *qual);
 static void recurse_push_qual(Node *setOp, Query *topquery,
@@ -1463,6 +1465,16 @@ qual_is_pushdown_safe(Query *subquery, Index rti, Node 
*qual,
                return false;
 
        /*
+        * (point 2)
+        * if we try to push quals below set operation, make
+        * sure that qual is pushable to below set operation children
+        */
+       if (NULL != subquery->setOperations
+                       && !qual_is_pushdown_safe_set_operation(subquery, qual))
+       {
+               return false;
+       }
+       /*
         * Examine all Vars used in clause; since it's a restriction clause, all
         * such Vars must refer to subselect output columns.
         */
@@ -1561,6 +1573,72 @@ qual_is_pushdown_safe(Query *subquery, Index rti, Node 
*qual,
 }
 
 /*
+ * qual_contains_winref
+ *
+ * does qual include a window ref node?
+ *
+ */
+static bool qual_contains_winref(Query *topquery,
+                                                               Index rti,
+                                                               /* index of RTE 
of subquery where qual needs to be checked */
+                                                               Node *qual)
+{
+       /*
+        * extract subquery where qual needs to be checked
+        */
+       RangeTblEntry *rte = rt_fetch(rti, topquery->rtable);
+       Query *subquery = rte->subquery;
+       bool result = false;
+
+       if (NULL != subquery && NIL != subquery->windowClause)
+       {
+               /*
+                * qual needs to be resolved first to map qual columns to the
+                * underlying set of produced columns, e.g., if we work on a 
setop
+                * child
+                */
+               Node *qualNew = ResolveNew(qual, rti, 0, rte, 
subquery->targetList,
+                               CMD_SELECT, 0);
+
+               result = contain_window_functions(qualNew);
+               pfree(qualNew);
+       }
+
+       return result;
+}
+
+/*
+ * qual_is_pushdown_safe_set_operation
+ *
+ * is a particular qual safe to push down set operation?
+ *
+ */
+static bool qual_is_pushdown_safe_set_operation(Query *subquery, Node *qual)
+{
+       SetOperationStmt *setop = (SetOperationStmt *) subquery->setOperations;
+
+       /*
+        * MPP-21075
+        * for queries of the form:
+        *   SELECT * from (SELECT max(i) over () as w from X Union Select 1 as 
w) as foo where w > 0
+        * the qual (w > 0) is not push_down_safe since it uses a window ref
+        *
+        * we check if this is the case for either left or right setop inputs
+        *
+        */
+       Index rtiLeft = ((RangeTblRef *) setop->larg)->rtindex;
+       Index rtiRight = ((RangeTblRef *) setop->rarg)->rtindex;
+
+       if (qual_contains_winref(subquery, rtiLeft, qual)
+                       || qual_contains_winref(subquery, rtiRight, qual))
+       {
+               return false;
+       }
+
+       return true;
+}
+
+/*
  * subquery_push_qual - push down a qual that we have determined is safe
  */
 static void
diff --git a/src/backend/optimizer/util/clauses.c 
b/src/backend/optimizer/util/clauses.c
index a3d67f2..2dbeceb 100644
--- a/src/backend/optimizer/util/clauses.c
+++ b/src/backend/optimizer/util/clauses.c
@@ -93,6 +93,7 @@ static bool expression_returns_set_walker(Node *node, void 
*context);
 static bool contain_subplans_walker(Node *node, void *context);
 static bool contain_mutable_functions_walker(Node *node, void *context);
 static bool contain_volatile_functions_walker(Node *node, void *context);
+static bool contain_windowfuncs(Node *node);
 static bool contain_window_functions_walker(Node *node, void *context);
 static bool contain_nonstrict_functions_walker(Node *node, void *context);
 static Relids find_nonnullable_rels_walker(Node *node, bool top_level);
@@ -862,10 +863,25 @@ contain_volatile_functions_walker(Node *node, void 
*context)
  * window functions because if there are any, they pertain to a different
  * planning level.
  */
-bool
-contain_window_functions(Node *clause)
+bool contain_window_functions(Node *clause)
+{
+       return contain_windowfuncs(clause);
+}
+
+/*
+ * contain_windowfuncs -
+ *  Check if an expression contains a window function call of the
+ *  current query level.
+ */
+static bool contain_windowfuncs(Node *node)
 {
-       return contain_window_functions_walker(clause, NULL);
+       /*
+        * Must be prepared to start with a Query or a bare expression tree; if
+        * it's a Query, we don't want to increment sublevels_up.
+        */
+       return query_or_expression_tree_walker(node,
+                       contain_window_functions_walker,
+                       NULL, 0);
 }
 
 static bool
diff --git a/src/test/feature/planner/ans/subplan.ans 
b/src/test/feature/planner/ans/subplan.ans
index bb3df84..f68b8b8 100644
--- a/src/test/feature/planner/ans/subplan.ans
+++ b/src/test/feature/planner/ans/subplan.ans
@@ -351,6 +351,21 @@ select array(select nop(i) from toy order by i);
  {1,2,3,4,5,6,7,8,9,10}
 (1 row)
 
+-- This one contains one subquery and window function.
+create table aa(a int);
+CREATE TABLE
+insert into aa values (1);
+INSERT 0 1
+SELECT t1.sum
+FROM ( SELECT sum(a) OVER() AS sum FROM aa
+UNION ALL
+SELECT sum(a) OVER() AS sum FROM aa) t1 WHERE t1.sum = 1;
+ sum
+-----
+   1
+   1
+(2 rows)
+
 -- start_ignore
 drop schema subplan_tests cascade;
 psql:/tmp/TestSubplan_TestSubplanAll.sql:142: NOTICE:  drop cascades to append 
only table toy
diff --git a/src/test/feature/planner/sql/subplan.sql 
b/src/test/feature/planner/sql/subplan.sql
index eb4619b..540affa 100644
--- a/src/test/feature/planner/sql/subplan.sql
+++ b/src/test/feature/planner/sql/subplan.sql
@@ -132,6 +132,13 @@ create table toy as select generate_series(1, 10) i 
distributed by (i);
 select * from toy; -- only for debugging
 select array(select nop(i) from toy order by i);
 
+-- This one contains one subquery and window function.
+create table aa(a int);
+insert into aa values (1);
+SELECT t1.sum
+FROM ( SELECT sum(a) OVER() AS sum FROM aa
+UNION ALL
+SELECT sum(a) OVER() AS sum FROM aa) t1 WHERE t1.sum = 1;
 -- start_ignore
 drop schema subplan_tests cascade;
 -- end_ignore

Reply via email to