Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 5a7d369

Browse files
committed
Fix two separate bugs in setrefs.c. set_subqueryscan_references needs
to copy the whole plan tree before invoking adjust_plan_varnos(); else if there is any multiply-linked substructure, the latter might increment some Var's varno twice. Previously there were some retail copyObject calls inside adjust_plan_varnos, but it seems a lot safer to just dup the whole tree first. Also, set_inner_join_references was trying to avoid work by not recursing if a BitmapHeapScan's bitmapqualorig contained no outer references; which was OK at the time the code was written, I think, but now that create_bitmap_scan_plan removes duplicate clauses from bitmapqualorig it is possible for that field to be NULL while outer references still remain in the qpqual and/or contained indexscan nodes. For safety, always recurse even if the BitmapHeapScan looks to be outer reference free. Per reports from Michael Fuhr and Oleg Bartunov.
1 parent 5824d02 commit 5a7d369

File tree

1 file changed

+32
-40
lines changed

1 file changed

+32
-40
lines changed

src/backend/optimizer/plan/setrefs.c

Lines changed: 32 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
*
1010
*
1111
* IDENTIFICATION
12-
* $PostgreSQL: pgsql/src/backend/optimizer/plan/setrefs.c,v 1.111 2005/06/10 00:28:54 tgl Exp $
12+
* $PostgreSQL: pgsql/src/backend/optimizer/plan/setrefs.c,v 1.112 2005/08/27 18:04:49 tgl Exp $
1313
*
1414
*-------------------------------------------------------------------------
1515
*/
@@ -367,7 +367,12 @@ set_subqueryscan_references(SubqueryScan *plan, List *rtable)
367367
QTW_IGNORE_RT_SUBQUERIES);
368368
rtable = list_concat(rtable, sub_rtable);
369369

370-
result = plan->subplan;
370+
/*
371+
* we have to copy the subplan to make sure there are no duplicately
372+
* linked nodes in it, else adjust_plan_varnos might increment some
373+
* varnos twice
374+
*/
375+
result = copyObject(plan->subplan);
371376

372377
adjust_plan_varnos(result, rtoffset);
373378

@@ -538,10 +543,7 @@ adjust_plan_varnos(Plan *plan, int rtoffset)
538543
* Even though the targetlist won't be used by the executor,
539544
* we fix it up for possible use by EXPLAIN (not to mention
540545
* ease of debugging --- wrong varnos are very confusing).
541-
* We have to make a copy because the tlist is very likely
542-
* shared with lower plan levels.
543546
*/
544-
plan->targetlist = copyObject(plan->targetlist);
545547
adjust_expr_varnos((Node *) plan->targetlist, rtoffset);
546548
Assert(plan->qual == NIL);
547549
break;
@@ -552,7 +554,6 @@ adjust_plan_varnos(Plan *plan, int rtoffset)
552554
* or quals. It does have live expressions for limit/offset,
553555
* however.
554556
*/
555-
plan->targetlist = copyObject(plan->targetlist);
556557
adjust_expr_varnos((Node *) plan->targetlist, rtoffset);
557558
Assert(plan->qual == NIL);
558559
adjust_expr_varnos(((Limit *) plan)->limitOffset, rtoffset);
@@ -569,14 +570,6 @@ adjust_plan_varnos(Plan *plan, int rtoffset)
569570
adjust_expr_varnos(((Result *) plan)->resconstantqual, rtoffset);
570571
break;
571572
case T_Append:
572-
573-
/*
574-
* Append, like Sort et al, doesn't actually evaluate its
575-
* targetlist or check quals, and we haven't bothered to give it
576-
* its own tlist copy. So, copy tlist before fixing. Then
577-
* recurse into child plans.
578-
*/
579-
plan->targetlist = copyObject(plan->targetlist);
580573
adjust_expr_varnos((Node *) plan->targetlist, rtoffset);
581574
Assert(plan->qual == NIL);
582575
foreach(l, ((Append *) plan)->appendplans)
@@ -849,39 +842,38 @@ set_inner_join_references(Plan *inner_plan,
849842
/*
850843
* The inner side is a bitmap scan plan. Fix the top node,
851844
* and recurse to get the lower nodes.
845+
*
846+
* Note: create_bitmap_scan_plan removes clauses from bitmapqualorig
847+
* if they are duplicated in qpqual, so must test these independently.
852848
*/
853849
BitmapHeapScan *innerscan = (BitmapHeapScan *) inner_plan;
850+
Index innerrel = innerscan->scan.scanrelid;
854851
List *bitmapqualorig = innerscan->bitmapqualorig;
855852

856-
/* No work needed if bitmapqual refers only to its own rel... */
853+
/* only refs to outer vars get changed in the inner qual */
857854
if (NumRelids((Node *) bitmapqualorig) > 1)
858-
{
859-
Index innerrel = innerscan->scan.scanrelid;
860-
861-
/* only refs to outer vars get changed in the inner qual */
862855
innerscan->bitmapqualorig = join_references(bitmapqualorig,
863-
rtable,
864-
outer_itlist,
865-
NULL,
866-
innerrel);
867-
868-
/*
869-
* We must fix the inner qpqual too, if it has join
870-
* clauses (this could happen if special operators are
871-
* involved: some indexquals may get rechecked as qpquals).
872-
*/
873-
if (NumRelids((Node *) inner_plan->qual) > 1)
874-
inner_plan->qual = join_references(inner_plan->qual,
875-
rtable,
876-
outer_itlist,
877-
NULL,
878-
innerrel);
856+
rtable,
857+
outer_itlist,
858+
NULL,
859+
innerrel);
879860

880-
/* Now recurse */
881-
set_inner_join_references(inner_plan->lefttree,
882-
rtable,
883-
outer_itlist);
884-
}
861+
/*
862+
* We must fix the inner qpqual too, if it has join
863+
* clauses (this could happen if special operators are
864+
* involved: some indexquals may get rechecked as qpquals).
865+
*/
866+
if (NumRelids((Node *) inner_plan->qual) > 1)
867+
inner_plan->qual = join_references(inner_plan->qual,
868+
rtable,
869+
outer_itlist,
870+
NULL,
871+
innerrel);
872+
873+
/* Now recurse */
874+
set_inner_join_references(inner_plan->lefttree,
875+
rtable,
876+
outer_itlist);
885877
}
886878
else if (IsA(inner_plan, BitmapAnd))
887879
{

0 commit comments

Comments
 (0)