From ce1663cdcdbd9bf15c81570277f70571b3727dd3 Mon Sep 17 00:00:00 2001 From: Robert Haas Date: Wed, 28 Feb 2018 10:56:06 -0500 Subject: [PATCH] Fix assertion failure when Parallel Append is run serially. Parallel-aware plan nodes must be prepared to run without parallelism if it's not possible at execution time for whatever reason. Commit ab72716778128fb63d54ac256adf7fe6820a1185, which introduced Parallel Append, overlooked this. Rajkumar Raghuwanshi reported this problem, and I included his test case in this patch. The code changes are by me. Discussion: http://postgr.es/m/CAKcux6=WqkUudLg1GLZZ7fc5ScWC1+Y9qD=pAHeqy32WoeJQvw@mail.gmail.com --- src/backend/executor/nodeAppend.c | 21 ++++++++++++------- src/test/regress/expected/select_parallel.out | 11 ++++++++++ src/test/regress/sql/select_parallel.sql | 6 ++++++ 3 files changed, 31 insertions(+), 7 deletions(-) diff --git a/src/backend/executor/nodeAppend.c b/src/backend/executor/nodeAppend.c index 7a3dd2ee2d..dcbf4d68aa 100644 --- a/src/backend/executor/nodeAppend.c +++ b/src/backend/executor/nodeAppend.c @@ -162,7 +162,7 @@ ExecInitAppend(Append *node, EState *estate, int eflags) appendstate->as_whichplan = appendstate->ps.plan->parallel_aware ? INVALID_SUBPLAN_INDEX : 0; - /* If parallel-aware, this will be overridden later. */ + /* For parallel query, this will be overridden later. */ appendstate->choose_next_subplan = choose_next_subplan_locally; return appendstate; @@ -361,14 +361,21 @@ choose_next_subplan_locally(AppendState *node) { int whichplan = node->as_whichplan; - /* We should never see INVALID_SUBPLAN_INDEX in this case. */ - Assert(whichplan >= 0 && whichplan <= node->as_nplans); - if (ScanDirectionIsForward(node->ps.state->es_direction)) { - if (whichplan >= node->as_nplans - 1) - return false; - node->as_whichplan++; + /* + * We won't normally see INVALID_SUBPLAN_INDEX in this case, but we + * might if a plan intended to be run in parallel ends up being run + * serially. + */ + if (whichplan == INVALID_SUBPLAN_INDEX) + node->as_whichplan = 0; + else + { + if (whichplan >= node->as_nplans - 1) + return false; + node->as_whichplan++; + } } else { diff --git a/src/test/regress/expected/select_parallel.out b/src/test/regress/expected/select_parallel.out index 452494fbfa..0a78261638 100644 --- a/src/test/regress/expected/select_parallel.out +++ b/src/test/regress/expected/select_parallel.out @@ -121,6 +121,17 @@ select round(avg(aa)), sum(aa) from a_star a4; (1 row) reset enable_parallel_append; +-- Parallel Append that runs serially +create or replace function foobar() returns setof text as +$$ select 'foo'::varchar union all select 'bar'::varchar $$ +language sql stable; +select foobar() order by 1; + foobar +-------- + bar + foo +(2 rows) + -- test with leader participation disabled set parallel_leader_participation = off; explain (costs off) diff --git a/src/test/regress/sql/select_parallel.sql b/src/test/regress/sql/select_parallel.sql index b12ba0b74a..fa03aae0c0 100644 --- a/src/test/regress/sql/select_parallel.sql +++ b/src/test/regress/sql/select_parallel.sql @@ -49,6 +49,12 @@ explain (costs off) select round(avg(aa)), sum(aa) from a_star a4; reset enable_parallel_append; +-- Parallel Append that runs serially +create or replace function foobar() returns setof text as +$$ select 'foo'::varchar union all select 'bar'::varchar $$ +language sql stable; +select foobar() order by 1; + -- test with leader participation disabled set parallel_leader_participation = off; explain (costs off) -- 2.40.0