88 *
99 *
1010 * IDENTIFICATION
11- * $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.130 2007/02/13 02:31:03 tgl Exp $
11+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.131 2007/02/16 20:57:19 tgl Exp $
1212 *
1313 *-------------------------------------------------------------------------
1414 */
@@ -43,7 +43,6 @@ static OuterJoinInfo *make_outerjoininfo(PlannerInfo *root,
4343 Relids left_rels , Relids right_rels ,
4444 bool is_full_join , Node * clause );
4545static void distribute_qual_to_rels (PlannerInfo * root , Node * clause ,
46- bool is_pushed_down ,
4746 bool is_deduced ,
4847 bool below_outer_join ,
4948 Relids qualscope ,
@@ -283,12 +282,11 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join,
283282 }
284283
285284 /*
286- * Now process the top-level quals. These are always marked as
287- * "pushed down", since they clearly didn't come from a JOIN expr.
285+ * Now process the top-level quals.
288286 */
289287 foreach (l , (List * ) f -> quals )
290288 distribute_qual_to_rels (root , (Node * ) lfirst (l ),
291- true, false, below_outer_join ,
289+ false, below_outer_join ,
292290 * qualscope , NULL , NULL );
293291 }
294292 else if (IsA (jtnode , JoinExpr ))
@@ -389,7 +387,7 @@ deconstruct_recurse(PlannerInfo *root, Node *jtnode, bool below_outer_join,
389387 /* Process the qual clauses */
390388 foreach (qual , (List * ) j -> quals )
391389 distribute_qual_to_rels (root , (Node * ) lfirst (qual ),
392- false, false, below_outer_join ,
390+ false, below_outer_join ,
393391 * qualscope , ojscope , nonnullable_rels );
394392
395393 /* Now we can add the OuterJoinInfo to oj_info_list */
@@ -600,8 +598,6 @@ make_outerjoininfo(PlannerInfo *root,
600598 * EquivalenceClasses.
601599 *
602600 * 'clause': the qual clause to be distributed
603- * 'is_pushed_down': if TRUE, force the clause to be marked 'is_pushed_down'
604- * (this indicates the clause came from a FromExpr, not a JoinExpr)
605601 * 'is_deduced': TRUE if the qual came from implied-equality deduction
606602 * 'below_outer_join': TRUE if the qual is from a JOIN/ON that is below the
607603 * nullable side of a higher-level outer join
@@ -619,14 +615,14 @@ make_outerjoininfo(PlannerInfo *root,
619615 */
620616static void
621617distribute_qual_to_rels (PlannerInfo * root , Node * clause ,
622- bool is_pushed_down ,
623618 bool is_deduced ,
624619 bool below_outer_join ,
625620 Relids qualscope ,
626621 Relids ojscope ,
627622 Relids outerjoin_nonnullable )
628623{
629624 Relids relids ;
625+ bool is_pushed_down ;
630626 bool outerjoin_delayed ;
631627 bool pseudoconstant = false;
632628 bool maybe_equivalence ;
@@ -692,17 +688,37 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
692688 root -> hasPseudoConstantQuals = true;
693689 /* if not below outer join, push it to top of tree */
694690 if (!below_outer_join )
695- {
696691 relids = get_relids_in_jointree ((Node * ) root -> parse -> jointree );
697- is_pushed_down = true;
698- }
699692 }
700693 }
701694 }
702695
703- /*
696+ /*----------
704697 * Check to see if clause application must be delayed by outer-join
705698 * considerations.
699+ *
700+ * A word about is_pushed_down: we mark the qual as "pushed down" if
701+ * it is (potentially) applicable at a level different from its original
702+ * syntactic level. This flag is used to distinguish OUTER JOIN ON quals
703+ * from other quals pushed down to the same joinrel. The rules are:
704+ * WHERE quals and INNER JOIN quals: is_pushed_down = true.
705+ * Non-degenerate OUTER JOIN quals: is_pushed_down = false.
706+ * Degenerate OUTER JOIN quals: is_pushed_down = true.
707+ * A "degenerate" OUTER JOIN qual is one that doesn't mention the
708+ * non-nullable side, and hence can be pushed down into the nullable side
709+ * without changing the join result. It is correct to treat it as a
710+ * regular filter condition at the level where it is evaluated.
711+ *
712+ * Note: it is not immediately obvious that a simple boolean is enough
713+ * for this: if for some reason we were to attach a degenerate qual to
714+ * its original join level, it would need to be treated as an outer join
715+ * qual there. However, this cannot happen, because all the rels the
716+ * clause mentions must be in the outer join's min_righthand, therefore
717+ * the join it needs must be formed before the outer join; and we always
718+ * attach quals to the lowest level where they can be evaluated. But
719+ * if we were ever to re-introduce a mechanism for delaying evaluation
720+ * of "expensive" quals, this area would need work.
721+ *----------
706722 */
707723 if (is_deduced )
708724 {
@@ -713,6 +729,7 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
713729 * where the qual belongs.
714730 */
715731 Assert (!ojscope );
732+ is_pushed_down = true;
716733 outerjoin_delayed = false;
717734 /* Don't feed it back for more deductions */
718735 maybe_equivalence = false;
@@ -722,12 +739,7 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
722739 {
723740 /*
724741 * The qual is attached to an outer join and mentions (some of the)
725- * rels on the nonnullable side.
726- *
727- * Note: an outer-join qual that mentions only nullable-side rels can
728- * be pushed down into the nullable side without changing the join
729- * result, so we treat it almost the same as an ordinary inner-join
730- * qual (see below).
742+ * rels on the nonnullable side, so it's not degenerate.
731743 *
732744 * We can't use such a clause to deduce equivalence (the left and right
733745 * sides might be unequal above the join because one of them has gone
@@ -751,12 +763,19 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
751763 */
752764 Assert (ojscope );
753765 relids = ojscope ;
766+ is_pushed_down = false;
754767 outerjoin_delayed = true;
755768 Assert (!pseudoconstant );
756769 }
757770 else
758771 {
759- /* Normal qual clause; check to see if must be delayed by outer join */
772+ /*
773+ * Normal qual clause or degenerate outer-join clause. Either way,
774+ * we can mark it as pushed-down.
775+ */
776+ is_pushed_down = true;
777+
778+ /* Check to see if must be delayed by outer join */
760779 outerjoin_delayed = check_outerjoin_delay (root , & relids );
761780
762781 if (outerjoin_delayed )
@@ -791,17 +810,6 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
791810 maybe_outer_join = false;
792811 }
793812
794- /*
795- * Mark the qual as "pushed down" if it can be applied at a level below
796- * its original syntactic level. This allows us to distinguish original
797- * JOIN/ON quals from higher-level quals pushed down to the same joinrel.
798- * A qual originating from WHERE is always considered "pushed down". Note
799- * that for an outer-join qual, we have to compare to ojscope not
800- * qualscope.
801- */
802- if (!is_pushed_down )
803- is_pushed_down = !bms_equal (relids , ojscope ? ojscope : qualscope );
804-
805813 /*
806814 * Build the RestrictInfo node itself.
807815 */
@@ -915,7 +923,7 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
915923 * If so, add relids to *relids_p to reflect the lowest safe level for
916924 * evaluating the qual, and return TRUE.
917925 *
918- * For a non-outer-join qual, we can evaluate the qual as soon as (1) we have
926+ * For an is_pushed_down qual, we can evaluate the qual as soon as (1) we have
919927 * all the rels it mentions, and (2) we are at or above any outer joins that
920928 * can null any of these rels and are below the syntactic location of the
921929 * given qual. We must enforce (2) because pushing down such a clause below
@@ -935,7 +943,7 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
935943 * B/C join is done first then the join to A can null C, so a qual actually
936944 * mentioning only C cannot be applied below the join to A.
937945 *
938- * For an outer-join qual, this isn't going to determine where we place the
946+ * For a non-pushed-down qual, this isn't going to determine where we place the
939947 * qual, but we need to determine outerjoin_delayed anyway so we can decide
940948 * whether the qual is potentially useful for equivalence deductions.
941949 */
@@ -1101,12 +1109,9 @@ process_implied_equality(PlannerInfo *root,
11011109
11021110 /*
11031111 * Push the new clause into all the appropriate restrictinfo lists.
1104- *
1105- * Note: we mark the qual "pushed down" to ensure that it can never be
1106- * taken for an original JOIN/ON clause.
11071112 */
11081113 distribute_qual_to_rels (root , (Node * ) clause ,
1109- true, true, below_outer_join ,
1114+ true, below_outer_join ,
11101115 qualscope , NULL , NULL );
11111116}
11121117
0 commit comments