]> git.ipfire.org Git - thirdparty/postgresql.git/commitdiff
Prohibit pushing subqueries containing window function calculation to
authorAmit Kapila <akapila@postgresql.org>
Tue, 4 Sep 2018 05:31:25 +0000 (11:01 +0530)
committerAmit Kapila <akapila@postgresql.org>
Tue, 4 Sep 2018 05:31:25 +0000 (11:01 +0530)
workers.

Allowing window function calculation in workers leads to inconsistent
results because if the input row ordering is not fully deterministic, the
output of window functions might vary across workers.  The fix is to treat
them as parallel-restricted.

In the passing, improve the coding pattern in max_parallel_hazard_walker
so that it has a chain of mutually-exclusive if ... else if ... else if
... else if ... IsA tests.

Reported-by: Marko Tiikkaja
Bug: 15324
Author: Amit Kapila
Reviewed-by: Tom Lane
Backpatch-through: 9.6
Discussion: https://postgr.es/m/CAL9smLAnfPJCDUUG4ckX2iznj53V7VSMsYefzZieN93YxTNOcw@mail.gmail.com

src/backend/optimizer/util/clauses.c
src/test/regress/expected/select_parallel.out
src/test/regress/sql/select_parallel.sql

index 8cdee705d15e8df31a185590b87c04d2083ca189..9f2ead73cb54ba43ac7b19fc70191a99d61ac35b 100644 (file)
@@ -1161,6 +1161,20 @@ has_parallel_hazard_walker(Node *node, has_parallel_hazard_arg *context)
                        return true;
        }
 
+       /*
+        * Treat window functions as parallel-restricted because we aren't sure
+        * whether the input row ordering is fully deterministic, and the output
+        * of window functions might vary across workers if not.  (In some cases,
+        * like where the window frame orders by a primary key, we could relax
+        * this restriction.  But it doesn't currently seem worth expending extra
+        * effort to do so.)
+        */
+       else if (IsA(node, WindowFunc))
+       {
+               if (!context->allow_restricted)
+                       return true;
+       }
+
        /*
         * As a notational convenience for callers, look through RestrictInfo.
         */
index 43801e0f8a215ce896038245a476984487d9d790..926202192b3a123634b7b0e5cb459b7ff57b330e 100644 (file)
@@ -182,6 +182,29 @@ select count(*) from tenk1;
 (1 row)
 
 reset role;
+-- Window function calculation can't be pushed to workers.
+explain (costs off, verbose)
+  select count(*) from tenk1 a where (unique1, two) in
+    (select unique1, row_number() over() from tenk1 b);
+                                     QUERY PLAN                                     
+------------------------------------------------------------------------------------
+ Aggregate
+   Output: count(*)
+   ->  Hash Semi Join
+         Hash Cond: ((a.unique1 = b.unique1) AND (a.two = (row_number() OVER (?))))
+         ->  Gather
+               Output: a.unique1, a.two
+               Workers Planned: 4
+               ->  Parallel Seq Scan on public.tenk1 a
+                     Output: a.unique1, a.two
+         ->  Hash
+               Output: b.unique1, (row_number() OVER (?))
+               ->  WindowAgg
+                     Output: b.unique1, row_number() OVER (?)
+                     ->  Index Only Scan using tenk1_unique1 on public.tenk1 b
+                           Output: b.unique1
+(15 rows)
+
 explain (costs off)
   select stringu1::int2 from tenk1 where unique1 = 1;
                   QUERY PLAN                   
index 7defc34cb78818e05c7b8686ab2ae11e7a77d163..266d0dd64646dd2f19f44ca85696f74ca4efd527 100644 (file)
@@ -83,6 +83,11 @@ drop role regress_parallel_worker;
 select count(*) from tenk1;
 reset role;
 
+-- Window function calculation can't be pushed to workers.
+explain (costs off, verbose)
+  select count(*) from tenk1 a where (unique1, two) in
+    (select unique1, row_number() over() from tenk1 b);
+
 explain (costs off)
   select stringu1::int2 from tenk1 where unique1 = 1;