Skip to content

Commit b73f1b5

Browse files
committed
Make simpler-simple-expressions code cope with a Gather plan.
Commit 00418c6 expected that the plan generated for a simple-expression query would always be a plain Result node. However, if force_parallel_mode is on, the planner might stick a Gather atop that. Cope by looking through the Gather. For safety, assert that the Gather's tlist is trivial. Per buildfarm. Discussion: https://postgr.es/m/23425.1502822098@sss.pgh.pa.us
1 parent 70b573b commit b73f1b5

File tree

1 file changed

+46
-15
lines changed

1 file changed

+46
-15
lines changed

src/pl/plpgsql/src/pl_exec.c

Lines changed: 46 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -6553,7 +6553,7 @@ exec_save_simple_expr(PLpgSQL_expr *expr, CachedPlan *cplan)
65536553
{
65546554
PlannedStmt *stmt;
65556555
Plan *plan;
6556-
TargetEntry *tle;
6556+
Expr *tle_expr;
65576557

65586558
/*
65596559
* Given the checks that exec_simple_check_plan did, none of the Asserts
@@ -6563,33 +6563,64 @@ exec_save_simple_expr(PLpgSQL_expr *expr, CachedPlan *cplan)
65636563
/* Extract the single PlannedStmt */
65646564
Assert(list_length(cplan->stmt_list) == 1);
65656565
stmt = linitial_node(PlannedStmt, cplan->stmt_list);
6566-
6567-
/* Should be a trivial Result plan */
65686566
Assert(stmt->commandType == CMD_SELECT);
6567+
6568+
/*
6569+
* Ordinarily, the plan node should be a simple Result. However, if
6570+
* force_parallel_mode is on, the planner might've stuck a Gather node
6571+
* atop that. The simplest way to deal with this is to look through the
6572+
* Gather node. The Gather node's tlist would normally contain a Var
6573+
* referencing the child node's output ... but setrefs.c might also have
6574+
* copied a Const as-is.
6575+
*/
65696576
plan = stmt->planTree;
6570-
Assert(IsA(plan, Result));
6571-
Assert(plan->lefttree == NULL &&
6572-
plan->righttree == NULL &&
6573-
plan->initPlan == NULL &&
6574-
plan->qual == NULL &&
6575-
((Result *) plan)->resconstantqual == NULL);
6577+
for (;;)
6578+
{
6579+
/* Extract the single tlist expression */
6580+
Assert(list_length(plan->targetlist) == 1);
6581+
tle_expr = castNode(TargetEntry, linitial(plan->targetlist))->expr;
65766582

6577-
/* Extract the single tlist expression */
6578-
Assert(list_length(plan->targetlist) == 1);
6579-
tle = (TargetEntry *) linitial(plan->targetlist);
6583+
if (IsA(plan, Result))
6584+
{
6585+
Assert(plan->lefttree == NULL &&
6586+
plan->righttree == NULL &&
6587+
plan->initPlan == NULL &&
6588+
plan->qual == NULL &&
6589+
((Result *) plan)->resconstantqual == NULL);
6590+
break;
6591+
}
6592+
else if (IsA(plan, Gather))
6593+
{
6594+
Assert(plan->lefttree != NULL &&
6595+
plan->righttree == NULL &&
6596+
plan->initPlan == NULL &&
6597+
plan->qual == NULL);
6598+
/* If setrefs.c copied up a Const, no need to look further */
6599+
if (IsA(tle_expr, Const))
6600+
break;
6601+
/* Otherwise, it better be an outer Var */
6602+
Assert(IsA(tle_expr, Var));
6603+
Assert(((Var *) tle_expr)->varno == OUTER_VAR);
6604+
/* Descend to the child node */
6605+
plan = plan->lefttree;
6606+
}
6607+
else
6608+
elog(ERROR, "unexpected plan node type: %d",
6609+
(int) nodeTag(plan));
6610+
}
65806611

65816612
/*
65826613
* Save the simple expression, and initialize state to "not valid in
65836614
* current transaction".
65846615
*/
6585-
expr->expr_simple_expr = tle->expr;
6616+
expr->expr_simple_expr = tle_expr;
65866617
expr->expr_simple_generation = cplan->generation;
65876618
expr->expr_simple_state = NULL;
65886619
expr->expr_simple_in_use = false;
65896620
expr->expr_simple_lxid = InvalidLocalTransactionId;
65906621
/* Also stash away the expression result type */
6591-
expr->expr_simple_type = exprType((Node *) tle->expr);
6592-
expr->expr_simple_typmod = exprTypmod((Node *) tle->expr);
6622+
expr->expr_simple_type = exprType((Node *) tle_expr);
6623+
expr->expr_simple_typmod = exprTypmod((Node *) tle_expr);
65936624
}
65946625

65956626
/*

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy