8
8
*
9
9
*
10
10
* IDENTIFICATION
11
- * $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.131 2007/02/16 20:57:19 tgl Exp $
11
+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.132 2007/05/22 23:23:56 tgl Exp $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
@@ -48,7 +48,8 @@ static void distribute_qual_to_rels(PlannerInfo *root, Node *clause,
48
48
Relids qualscope ,
49
49
Relids ojscope ,
50
50
Relids outerjoin_nonnullable );
51
- static bool check_outerjoin_delay (PlannerInfo * root , Relids * relids_p );
51
+ static bool check_outerjoin_delay (PlannerInfo * root , Relids * relids_p ,
52
+ bool is_pushed_down );
52
53
static void check_mergejoinable (RestrictInfo * restrictinfo );
53
54
static void check_hashjoinable (RestrictInfo * restrictinfo );
54
55
@@ -492,6 +493,9 @@ make_outerjoininfo(PlannerInfo *root,
492
493
errmsg ("SELECT FOR UPDATE/SHARE cannot be applied to the nullable side of an outer join" )));
493
494
}
494
495
496
+ /* this always starts out false */
497
+ ojinfo -> delay_upper_joins = false;
498
+
495
499
/* If it's a full join, no need to be very smart */
496
500
ojinfo -> is_full_join = is_full_join ;
497
501
if (is_full_join )
@@ -561,10 +565,21 @@ make_outerjoininfo(PlannerInfo *root,
561
565
* lower join's RHS and the lower OJ's join condition is strict, we
562
566
* can interchange the ordering of the two OJs, so exclude the lower
563
567
* RHS from our min_righthand.
568
+ *
569
+ * Here, we have to consider that "our join condition" includes
570
+ * any clauses that syntactically appeared above the lower OJ and
571
+ * below ours; those are equivalent to degenerate clauses in our
572
+ * OJ and must be treated as such. Such clauses obviously can't
573
+ * reference our LHS, and they must be non-strict for the lower OJ's
574
+ * RHS (else reduce_outer_joins would have reduced the lower OJ to
575
+ * a plain join). Hence the other ways in which we handle clauses
576
+ * within our join condition are not affected by them. The net
577
+ * effect is therefore sufficiently represented by the
578
+ * delay_upper_joins flag saved for us by check_outerjoin_delay.
564
579
*/
565
580
if (bms_overlap (ojinfo -> min_righthand , otherinfo -> min_righthand ) &&
566
581
!bms_overlap (clause_relids , otherinfo -> min_righthand ) &&
567
- otherinfo -> lhs_strict )
582
+ otherinfo -> lhs_strict && ! otherinfo -> delay_upper_joins )
568
583
{
569
584
ojinfo -> min_righthand = bms_del_members (ojinfo -> min_righthand ,
570
585
otherinfo -> min_righthand );
@@ -749,7 +764,7 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
749
764
* clauses.
750
765
*/
751
766
maybe_equivalence = false;
752
- maybe_outer_join = !check_outerjoin_delay (root , & relids );
767
+ maybe_outer_join = !check_outerjoin_delay (root , & relids , false );
753
768
754
769
/*
755
770
* Now force the qual to be evaluated exactly at the level of joining
@@ -776,7 +791,7 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
776
791
is_pushed_down = true;
777
792
778
793
/* Check to see if must be delayed by outer join */
779
- outerjoin_delayed = check_outerjoin_delay (root , & relids );
794
+ outerjoin_delayed = check_outerjoin_delay (root , & relids , true );
780
795
781
796
if (outerjoin_delayed )
782
797
{
@@ -918,10 +933,13 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
918
933
/*
919
934
* check_outerjoin_delay
920
935
* Detect whether a qual referencing the given relids must be delayed
921
- * in application due to the presence of a lower outer join.
936
+ * in application due to the presence of a lower outer join, and/or
937
+ * may force extra delay of higher-level outer joins.
922
938
*
923
- * If so, add relids to *relids_p to reflect the lowest safe level for
924
- * evaluating the qual, and return TRUE.
939
+ * If the qual must be delayed, add relids to *relids_p to reflect the lowest
940
+ * safe level for evaluating the qual, and return TRUE. Any extra delay for
941
+ * higher-level joins is reflected by setting delay_upper_joins to TRUE in
942
+ * OuterJoinInfo structs.
925
943
*
926
944
* For an is_pushed_down qual, we can evaluate the qual as soon as (1) we have
927
945
* all the rels it mentions, and (2) we are at or above any outer joins that
@@ -946,9 +964,23 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
946
964
* For a non-pushed-down qual, this isn't going to determine where we place the
947
965
* qual, but we need to determine outerjoin_delayed anyway so we can decide
948
966
* whether the qual is potentially useful for equivalence deductions.
967
+ *
968
+ * Lastly, a pushed-down qual that references the nullable side of any current
969
+ * oj_info_list member and has to be evaluated above that OJ (because its
970
+ * required relids overlap the LHS too) causes that OJ's delay_upper_joins
971
+ * flag to be set TRUE. This will prevent any higher-level OJs from
972
+ * being interchanged with that OJ, which would result in not having any
973
+ * correct place to evaluate the qual. (The case we care about here is a
974
+ * sub-select WHERE clause within the RHS of some outer join. The WHERE
975
+ * clause must effectively be treated as a degenerate clause of that outer
976
+ * join's condition. Rather than trying to match such clauses with joins
977
+ * directly, we set delay_upper_joins here, and when the upper outer join
978
+ * is processed by make_outerjoininfo, it will refrain from allowing the
979
+ * two OJs to commute.)
949
980
*/
950
981
static bool
951
- check_outerjoin_delay (PlannerInfo * root , Relids * relids_p )
982
+ check_outerjoin_delay (PlannerInfo * root , Relids * relids_p ,
983
+ bool is_pushed_down )
952
984
{
953
985
Relids relids = * relids_p ;
954
986
bool outerjoin_delayed ;
@@ -979,6 +1011,10 @@ check_outerjoin_delay(PlannerInfo *root, Relids *relids_p)
979
1011
/* we'll need another iteration */
980
1012
found_some = true;
981
1013
}
1014
+ /* set delay_upper_joins if needed */
1015
+ if (is_pushed_down && !ojinfo -> is_full_join &&
1016
+ bms_overlap (relids , ojinfo -> min_lefthand ))
1017
+ ojinfo -> delay_upper_joins = true;
982
1018
}
983
1019
}
984
1020
} while (found_some );
0 commit comments