Skip to content

Commit 14e9b2a

Browse files
author
Amit Kapila
committed
Prohibit pushing subqueries containing window function calculation to
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
1 parent 7c9e19c commit 14e9b2a

File tree

3 files changed

+47
-1
lines changed

3 files changed

+47
-1
lines changed

src/backend/optimizer/util/clauses.c

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1190,12 +1190,26 @@ max_parallel_hazard_walker(Node *node, max_parallel_hazard_context *context)
11901190
return true;
11911191
}
11921192

1193-
if (IsA(node, NextValueExpr))
1193+
else if (IsA(node, NextValueExpr))
11941194
{
11951195
if (max_parallel_hazard_test(PROPARALLEL_UNSAFE, context))
11961196
return true;
11971197
}
11981198

1199+
/*
1200+
* Treat window functions as parallel-restricted because we aren't sure
1201+
* whether the input row ordering is fully deterministic, and the output
1202+
* of window functions might vary across workers if not. (In some cases,
1203+
* like where the window frame orders by a primary key, we could relax
1204+
* this restriction. But it doesn't currently seem worth expending extra
1205+
* effort to do so.)
1206+
*/
1207+
else if (IsA(node, WindowFunc))
1208+
{
1209+
if (max_parallel_hazard_test(PROPARALLEL_RESTRICTED, context))
1210+
return true;
1211+
}
1212+
11991213
/*
12001214
* As a notational convenience for callers, look through RestrictInfo.
12011215
*/

src/test/regress/expected/select_parallel.out

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -958,6 +958,32 @@ select count(*) from tenk1;
958958

959959
reset force_parallel_mode;
960960
reset role;
961+
-- Window function calculation can't be pushed to workers.
962+
explain (costs off, verbose)
963+
select count(*) from tenk1 a where (unique1, two) in
964+
(select unique1, row_number() over() from tenk1 b);
965+
QUERY PLAN
966+
----------------------------------------------------------------------------------------------
967+
Aggregate
968+
Output: count(*)
969+
-> Hash Semi Join
970+
Hash Cond: ((a.unique1 = b.unique1) AND (a.two = (row_number() OVER (?))))
971+
-> Gather
972+
Output: a.unique1, a.two
973+
Workers Planned: 4
974+
-> Parallel Seq Scan on public.tenk1 a
975+
Output: a.unique1, a.two
976+
-> Hash
977+
Output: b.unique1, (row_number() OVER (?))
978+
-> WindowAgg
979+
Output: b.unique1, row_number() OVER (?)
980+
-> Gather
981+
Output: b.unique1
982+
Workers Planned: 4
983+
-> Parallel Index Only Scan using tenk1_unique1 on public.tenk1 b
984+
Output: b.unique1
985+
(18 rows)
986+
961987
-- to increase the parallel query test coverage
962988
SAVEPOINT settings;
963989
SET LOCAL force_parallel_mode = 1;

src/test/regress/sql/select_parallel.sql

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -362,6 +362,12 @@ select count(*) from tenk1;
362362
reset force_parallel_mode;
363363
reset role;
364364

365+
-- Window function calculation can't be pushed to workers.
366+
explain (costs off, verbose)
367+
select count(*) from tenk1 a where (unique1, two) in
368+
(select unique1, row_number() over() from tenk1 b);
369+
370+
365371
-- to increase the parallel query test coverage
366372
SAVEPOINT settings;
367373
SET LOCAL force_parallel_mode = 1;

0 commit comments

Comments
 (0)