mirror of https://github.com/postgres/postgres
Repair bug reported by ldm@apartia.com: Append nodes, which don't
actually use their targetlist, are given a targetlist that is just a pointer to the first appended plan's targetlist. This is OK, but what is not OK is that any sub-select expressions in said tlist were being entered in the subPlan lists of both the Append and the first appended plan. That led to two startup and two shutdown calls for the same plan node at exec time, which led to crashes. Fix is to not generate a list of subPlans for an Append node. Same problem and fix apply to other node types that don't have a real, functioning targetlist: Material, Sort, Unique, Hash.
This commit is contained in:
parent
54bce381a7
commit
2190cf2926
|
@ -9,7 +9,7 @@
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* IDENTIFICATION
|
* IDENTIFICATION
|
||||||
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.63 2000/05/30 00:49:47 momjian Exp $
|
* $Header: /cvsroot/pgsql/src/backend/optimizer/plan/setrefs.c,v 1.64 2000/06/04 20:50:50 tgl Exp $
|
||||||
*
|
*
|
||||||
*-------------------------------------------------------------------------
|
*-------------------------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
@ -35,6 +35,7 @@ typedef struct
|
||||||
List *subplanTargetList;
|
List *subplanTargetList;
|
||||||
} replace_vars_with_subplan_refs_context;
|
} replace_vars_with_subplan_refs_context;
|
||||||
|
|
||||||
|
static void fix_expr_references(Plan *plan, Node *node);
|
||||||
static void set_join_references(Join *join);
|
static void set_join_references(Join *join);
|
||||||
static void set_uppernode_references(Plan *plan, Index subvarno);
|
static void set_uppernode_references(Plan *plan, Index subvarno);
|
||||||
static Node *join_references_mutator(Node *node,
|
static Node *join_references_mutator(Node *node,
|
||||||
|
@ -86,34 +87,39 @@ set_plan_references(Plan *plan)
|
||||||
switch (nodeTag(plan))
|
switch (nodeTag(plan))
|
||||||
{
|
{
|
||||||
case T_SeqScan:
|
case T_SeqScan:
|
||||||
/* nothing special */
|
fix_expr_references(plan, (Node *) plan->targetlist);
|
||||||
|
fix_expr_references(plan, (Node *) plan->qual);
|
||||||
break;
|
break;
|
||||||
case T_IndexScan:
|
case T_IndexScan:
|
||||||
fix_opids((Node *) ((IndexScan *) plan)->indxqual);
|
fix_expr_references(plan, (Node *) plan->targetlist);
|
||||||
fix_opids((Node *) ((IndexScan *) plan)->indxqualorig);
|
fix_expr_references(plan, (Node *) plan->qual);
|
||||||
plan->subPlan =
|
fix_expr_references(plan,
|
||||||
nconc(plan->subPlan,
|
(Node *) ((IndexScan *) plan)->indxqual);
|
||||||
pull_subplans((Node *) ((IndexScan *) plan)->indxqual));
|
fix_expr_references(plan,
|
||||||
plan->subPlan =
|
(Node *) ((IndexScan *) plan)->indxqualorig);
|
||||||
nconc(plan->subPlan,
|
break;
|
||||||
pull_subplans((Node *) ((IndexScan *) plan)->indxqualorig));
|
case T_TidScan:
|
||||||
|
fix_expr_references(plan, (Node *) plan->targetlist);
|
||||||
|
fix_expr_references(plan, (Node *) plan->qual);
|
||||||
break;
|
break;
|
||||||
case T_NestLoop:
|
case T_NestLoop:
|
||||||
set_join_references((Join *) plan);
|
set_join_references((Join *) plan);
|
||||||
|
fix_expr_references(plan, (Node *) plan->targetlist);
|
||||||
|
fix_expr_references(plan, (Node *) plan->qual);
|
||||||
break;
|
break;
|
||||||
case T_MergeJoin:
|
case T_MergeJoin:
|
||||||
set_join_references((Join *) plan);
|
set_join_references((Join *) plan);
|
||||||
fix_opids((Node *) ((MergeJoin *) plan)->mergeclauses);
|
fix_expr_references(plan, (Node *) plan->targetlist);
|
||||||
plan->subPlan =
|
fix_expr_references(plan, (Node *) plan->qual);
|
||||||
nconc(plan->subPlan,
|
fix_expr_references(plan,
|
||||||
pull_subplans((Node *) ((MergeJoin *) plan)->mergeclauses));
|
(Node *) ((MergeJoin *) plan)->mergeclauses);
|
||||||
break;
|
break;
|
||||||
case T_HashJoin:
|
case T_HashJoin:
|
||||||
set_join_references((Join *) plan);
|
set_join_references((Join *) plan);
|
||||||
fix_opids((Node *) ((HashJoin *) plan)->hashclauses);
|
fix_expr_references(plan, (Node *) plan->targetlist);
|
||||||
plan->subPlan =
|
fix_expr_references(plan, (Node *) plan->qual);
|
||||||
nconc(plan->subPlan,
|
fix_expr_references(plan,
|
||||||
pull_subplans((Node *) ((HashJoin *) plan)->hashclauses));
|
(Node *) ((HashJoin *) plan)->hashclauses);
|
||||||
break;
|
break;
|
||||||
case T_Material:
|
case T_Material:
|
||||||
case T_Sort:
|
case T_Sort:
|
||||||
|
@ -125,12 +131,17 @@ set_plan_references(Plan *plan)
|
||||||
* targetlists or quals (because they just return their
|
* targetlists or quals (because they just return their
|
||||||
* unmodified input tuples). The optimizer is lazy about
|
* unmodified input tuples). The optimizer is lazy about
|
||||||
* creating really valid targetlists for them. Best to just
|
* creating really valid targetlists for them. Best to just
|
||||||
* leave the targetlist alone.
|
* leave the targetlist alone. In particular, we do not want
|
||||||
|
* to pull a subplan list for them, since we will likely end
|
||||||
|
* up with duplicate list entries for subplans that also appear
|
||||||
|
* in lower levels of the plan tree!
|
||||||
*/
|
*/
|
||||||
break;
|
break;
|
||||||
case T_Agg:
|
case T_Agg:
|
||||||
case T_Group:
|
case T_Group:
|
||||||
set_uppernode_references(plan, (Index) 0);
|
set_uppernode_references(plan, (Index) 0);
|
||||||
|
fix_expr_references(plan, (Node *) plan->targetlist);
|
||||||
|
fix_expr_references(plan, (Node *) plan->qual);
|
||||||
break;
|
break;
|
||||||
case T_Result:
|
case T_Result:
|
||||||
|
|
||||||
|
@ -142,37 +153,25 @@ set_plan_references(Plan *plan)
|
||||||
*/
|
*/
|
||||||
if (plan->lefttree != NULL)
|
if (plan->lefttree != NULL)
|
||||||
set_uppernode_references(plan, (Index) OUTER);
|
set_uppernode_references(plan, (Index) OUTER);
|
||||||
fix_opids(((Result *) plan)->resconstantqual);
|
fix_expr_references(plan, (Node *) plan->targetlist);
|
||||||
plan->subPlan =
|
fix_expr_references(plan, (Node *) plan->qual);
|
||||||
nconc(plan->subPlan,
|
fix_expr_references(plan, ((Result *) plan)->resconstantqual);
|
||||||
pull_subplans(((Result *) plan)->resconstantqual));
|
|
||||||
break;
|
break;
|
||||||
case T_Append:
|
case T_Append:
|
||||||
|
/*
|
||||||
|
* Append, like Sort et al, doesn't actually evaluate its
|
||||||
|
* targetlist or quals, and we haven't bothered to give it
|
||||||
|
* its own tlist copy. So, don't fix targetlist/qual.
|
||||||
|
*/
|
||||||
foreach(pl, ((Append *) plan)->appendplans)
|
foreach(pl, ((Append *) plan)->appendplans)
|
||||||
set_plan_references((Plan *) lfirst(pl));
|
set_plan_references((Plan *) lfirst(pl));
|
||||||
break;
|
break;
|
||||||
case T_TidScan:
|
|
||||||
/* nothing special */
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
elog(ERROR, "set_plan_references: unknown plan type %d",
|
elog(ERROR, "set_plan_references: unknown plan type %d",
|
||||||
nodeTag(plan));
|
nodeTag(plan));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* For all plan types, fix operators in targetlist and qual
|
|
||||||
* expressions, and find subplans therein.
|
|
||||||
*/
|
|
||||||
fix_opids((Node *) plan->targetlist);
|
|
||||||
fix_opids((Node *) plan->qual);
|
|
||||||
plan->subPlan =
|
|
||||||
nconc(plan->subPlan,
|
|
||||||
pull_subplans((Node *) plan->targetlist));
|
|
||||||
plan->subPlan =
|
|
||||||
nconc(plan->subPlan,
|
|
||||||
pull_subplans((Node *) plan->qual));
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Now recurse into subplans, if any
|
* Now recurse into subplans, if any
|
||||||
*
|
*
|
||||||
|
@ -200,6 +199,20 @@ set_plan_references(Plan *plan)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* fix_expr_references
|
||||||
|
* Do final cleanup on expressions (targetlists or quals).
|
||||||
|
*
|
||||||
|
* This consists of looking up operator opcode info for Oper nodes
|
||||||
|
* and adding subplans to the Plan node's list of contained subplans.
|
||||||
|
*/
|
||||||
|
static void
|
||||||
|
fix_expr_references(Plan *plan, Node *node)
|
||||||
|
{
|
||||||
|
fix_opids(node);
|
||||||
|
plan->subPlan = nconc(plan->subPlan, pull_subplans(node));
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* set_join_references
|
* set_join_references
|
||||||
* Modifies the target list of a join node to reference its subplans,
|
* Modifies the target list of a join node to reference its subplans,
|
||||||
|
|
Loading…
Reference in New Issue