8
8
*
9
9
*
10
10
* IDENTIFICATION
11
- * $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.149 2009/02/27 22:41:38 tgl Exp $
11
+ * $PostgreSQL: pgsql/src/backend/optimizer/plan/initsplan.c,v 1.150 2009/04/16 20:42:16 tgl Exp $
12
12
*
13
13
*-------------------------------------------------------------------------
14
14
*/
@@ -53,7 +53,7 @@ static void distribute_qual_to_rels(PlannerInfo *root, Node *clause,
53
53
Relids ojscope ,
54
54
Relids outerjoin_nonnullable );
55
55
static bool check_outerjoin_delay (PlannerInfo * root , Relids * relids_p ,
56
- bool is_pushed_down );
56
+ Relids * nullable_relids_p , bool is_pushed_down );
57
57
static bool check_redundant_nullability_qual (PlannerInfo * root , Node * clause );
58
58
static void check_mergejoinable (RestrictInfo * restrictinfo );
59
59
static void check_hashjoinable (RestrictInfo * restrictinfo );
@@ -755,6 +755,7 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
755
755
bool pseudoconstant = false;
756
756
bool maybe_equivalence ;
757
757
bool maybe_outer_join ;
758
+ Relids nullable_relids ;
758
759
RestrictInfo * restrictinfo ;
759
760
760
761
/*
@@ -861,6 +862,7 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
861
862
Assert (!ojscope );
862
863
is_pushed_down = true;
863
864
outerjoin_delayed = false;
865
+ nullable_relids = NULL ;
864
866
/* Don't feed it back for more deductions */
865
867
maybe_equivalence = false;
866
868
maybe_outer_join = false;
@@ -882,7 +884,10 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
882
884
maybe_outer_join = true;
883
885
884
886
/* Check to see if must be delayed by lower outer join */
885
- outerjoin_delayed = check_outerjoin_delay (root , & relids , false);
887
+ outerjoin_delayed = check_outerjoin_delay (root ,
888
+ & relids ,
889
+ & nullable_relids ,
890
+ false);
886
891
887
892
/*
888
893
* Now force the qual to be evaluated exactly at the level of joining
@@ -907,7 +912,10 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
907
912
is_pushed_down = true;
908
913
909
914
/* Check to see if must be delayed by lower outer join */
910
- outerjoin_delayed = check_outerjoin_delay (root , & relids , true);
915
+ outerjoin_delayed = check_outerjoin_delay (root ,
916
+ & relids ,
917
+ & nullable_relids ,
918
+ true);
911
919
912
920
if (outerjoin_delayed )
913
921
{
@@ -957,7 +965,8 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
957
965
is_pushed_down ,
958
966
outerjoin_delayed ,
959
967
pseudoconstant ,
960
- relids );
968
+ relids ,
969
+ nullable_relids );
961
970
962
971
/*
963
972
* If it's a join clause (either naturally, or because delayed by
@@ -1064,7 +1073,9 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
1064
1073
* If the qual must be delayed, add relids to *relids_p to reflect the lowest
1065
1074
* safe level for evaluating the qual, and return TRUE. Any extra delay for
1066
1075
* higher-level joins is reflected by setting delay_upper_joins to TRUE in
1067
- * SpecialJoinInfo structs.
1076
+ * SpecialJoinInfo structs. We also compute nullable_relids, the set of
1077
+ * referenced relids that are nullable by lower outer joins (note that this
1078
+ * can be nonempty even for a non-delayed qual).
1068
1079
*
1069
1080
* For an is_pushed_down qual, we can evaluate the qual as soon as (1) we have
1070
1081
* all the rels it mentions, and (2) we are at or above any outer joins that
@@ -1087,8 +1098,8 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
1087
1098
* mentioning only C cannot be applied below the join to A.
1088
1099
*
1089
1100
* For a non-pushed-down qual, this isn't going to determine where we place the
1090
- * qual, but we need to determine outerjoin_delayed anyway for possible use
1091
- * in reconsider_outer_join_clauses() .
1101
+ * qual, but we need to determine outerjoin_delayed and nullable_relids anyway
1102
+ * for use later in the planning process .
1092
1103
*
1093
1104
* Lastly, a pushed-down qual that references the nullable side of any current
1094
1105
* join_info_list member and has to be evaluated above that OJ (because its
@@ -1104,13 +1115,26 @@ distribute_qual_to_rels(PlannerInfo *root, Node *clause,
1104
1115
* two OJs to commute.)
1105
1116
*/
1106
1117
static bool
1107
- check_outerjoin_delay (PlannerInfo * root , Relids * relids_p ,
1118
+ check_outerjoin_delay (PlannerInfo * root ,
1119
+ Relids * relids_p , /* in/out parameter */
1120
+ Relids * nullable_relids_p , /* output parameter */
1108
1121
bool is_pushed_down )
1109
1122
{
1110
- Relids relids = * relids_p ;
1123
+ Relids relids ;
1124
+ Relids nullable_relids ;
1111
1125
bool outerjoin_delayed ;
1112
1126
bool found_some ;
1113
1127
1128
+ /* fast path if no special joins */
1129
+ if (root -> join_info_list == NIL )
1130
+ {
1131
+ * nullable_relids_p = NULL ;
1132
+ return false;
1133
+ }
1134
+
1135
+ /* must copy relids because we need the original value at the end */
1136
+ relids = bms_copy (* relids_p );
1137
+ nullable_relids = NULL ;
1114
1138
outerjoin_delayed = false;
1115
1139
do
1116
1140
{
@@ -1126,18 +1150,23 @@ check_outerjoin_delay(PlannerInfo *root, Relids *relids_p,
1126
1150
(sjinfo -> jointype == JOIN_FULL &&
1127
1151
bms_overlap (relids , sjinfo -> min_lefthand )))
1128
1152
{
1129
- /* yes, so set the result flag */
1130
- outerjoin_delayed = true;
1131
- /* have we included all its rels in relids? */
1153
+ /* yes; have we included all its rels in relids? */
1132
1154
if (!bms_is_subset (sjinfo -> min_lefthand , relids ) ||
1133
1155
!bms_is_subset (sjinfo -> min_righthand , relids ))
1134
1156
{
1135
1157
/* no, so add them in */
1136
1158
relids = bms_add_members (relids , sjinfo -> min_lefthand );
1137
1159
relids = bms_add_members (relids , sjinfo -> min_righthand );
1160
+ outerjoin_delayed = true;
1138
1161
/* we'll need another iteration */
1139
1162
found_some = true;
1140
1163
}
1164
+ /* track all the nullable rels of relevant OJs */
1165
+ nullable_relids = bms_add_members (nullable_relids ,
1166
+ sjinfo -> min_righthand );
1167
+ if (sjinfo -> jointype == JOIN_FULL )
1168
+ nullable_relids = bms_add_members (nullable_relids ,
1169
+ sjinfo -> min_lefthand );
1141
1170
/* set delay_upper_joins if needed */
1142
1171
if (is_pushed_down && sjinfo -> jointype != JOIN_FULL &&
1143
1172
bms_overlap (relids , sjinfo -> min_lefthand ))
@@ -1146,7 +1175,13 @@ check_outerjoin_delay(PlannerInfo *root, Relids *relids_p,
1146
1175
}
1147
1176
} while (found_some );
1148
1177
1178
+ /* identify just the actually-referenced nullable rels */
1179
+ nullable_relids = bms_int_members (nullable_relids , * relids_p );
1180
+
1181
+ /* replace *relids_p, and return nullable_relids */
1182
+ bms_free (* relids_p );
1149
1183
* relids_p = relids ;
1184
+ * nullable_relids_p = nullable_relids ;
1150
1185
return outerjoin_delayed ;
1151
1186
}
1152
1187
@@ -1352,7 +1387,8 @@ build_implied_join_equality(Oid opno,
1352
1387
true, /* is_pushed_down */
1353
1388
false, /* outerjoin_delayed */
1354
1389
false, /* pseudoconstant */
1355
- qualscope );
1390
+ qualscope , /* required_relids */
1391
+ NULL ); /* nullable_relids */
1356
1392
1357
1393
/* Set mergejoinability info always, and hashjoinability if enabled */
1358
1394
check_mergejoinable (restrictinfo );
0 commit comments