|
15 | 15 | #include"postgres.h" |
16 | 16 |
|
17 | 17 | #include"optimizer/clauses.h" |
18 | | -#include"optimizer/predtest.h" |
19 | 18 | #include"optimizer/restrictinfo.h" |
20 | 19 | #include"optimizer/var.h" |
21 | 20 |
|
@@ -87,192 +86,6 @@ make_restrictinfo(Expr *clause, |
87 | 86 | nullable_relids); |
88 | 87 | } |
89 | 88 |
|
90 | | -/* |
91 | | - * make_restrictinfo_from_bitmapqual |
92 | | - * |
93 | | - * Given the bitmapqual Path structure for a bitmap indexscan, generate |
94 | | - * RestrictInfo node(s) equivalent to the condition represented by the |
95 | | - * indexclauses of the Path structure. |
96 | | - * |
97 | | - * The result is a List (effectively, implicit-AND representation) of |
98 | | - * RestrictInfos. |
99 | | - * |
100 | | - * The caller must pass is_pushed_down, but we assume outerjoin_delayed |
101 | | - * and pseudoconstant are false while outer_relids and nullable_relids |
102 | | - * are NULL (no other kind of qual should ever get into a bitmapqual). |
103 | | - * |
104 | | - * If include_predicates is true, we add any partial index predicates to |
105 | | - * the explicit index quals. When this is not true, we return a condition |
106 | | - * that might be weaker than the actual scan represents. |
107 | | - * |
108 | | - * To do this through the normal make_restrictinfo() API, callers would have |
109 | | - * to strip off the RestrictInfo nodes present in the indexclauses lists, and |
110 | | - * then make_restrictinfo() would have to build new ones. It's better to have |
111 | | - * a specialized routine to allow sharing of RestrictInfos. |
112 | | - * |
113 | | - * The qual manipulations here are much the same as in create_bitmap_subplan; |
114 | | - * keep the two routines in sync! |
115 | | - */ |
116 | | -List* |
117 | | -make_restrictinfo_from_bitmapqual(Path*bitmapqual, |
118 | | -boolis_pushed_down, |
119 | | -boolinclude_predicates) |
120 | | -{ |
121 | | -List*result; |
122 | | -ListCell*l; |
123 | | - |
124 | | -if (IsA(bitmapqual,BitmapAndPath)) |
125 | | -{ |
126 | | -BitmapAndPath*apath= (BitmapAndPath*)bitmapqual; |
127 | | - |
128 | | -/* |
129 | | - * There may well be redundant quals among the subplans, since a |
130 | | - * top-level WHERE qual might have gotten used to form several |
131 | | - * different index quals. We don't try exceedingly hard to eliminate |
132 | | - * redundancies, but we do eliminate obvious duplicates by using |
133 | | - * list_concat_unique. |
134 | | - */ |
135 | | -result=NIL; |
136 | | -foreach(l,apath->bitmapquals) |
137 | | -{ |
138 | | -List*sublist; |
139 | | - |
140 | | -sublist=make_restrictinfo_from_bitmapqual((Path*)lfirst(l), |
141 | | -is_pushed_down, |
142 | | -include_predicates); |
143 | | -result=list_concat_unique(result,sublist); |
144 | | -} |
145 | | -} |
146 | | -elseif (IsA(bitmapqual,BitmapOrPath)) |
147 | | -{ |
148 | | -BitmapOrPath*opath= (BitmapOrPath*)bitmapqual; |
149 | | -List*withris=NIL; |
150 | | -List*withoutris=NIL; |
151 | | - |
152 | | -/* |
153 | | - * Here, we only detect qual-free subplans. A qual-free subplan would |
154 | | - * cause us to generate "... OR true ..." which we may as well reduce |
155 | | - * to just "true".We do not try to eliminate redundant subclauses |
156 | | - * because (a) it's not as likely as in the AND case, and (b) we might |
157 | | - * well be working with hundreds or even thousands of OR conditions, |
158 | | - * perhaps from a long IN list. The performance of list_append_unique |
159 | | - * would be unacceptable. |
160 | | - */ |
161 | | -foreach(l,opath->bitmapquals) |
162 | | -{ |
163 | | -List*sublist; |
164 | | - |
165 | | -sublist=make_restrictinfo_from_bitmapqual((Path*)lfirst(l), |
166 | | -is_pushed_down, |
167 | | -include_predicates); |
168 | | -if (sublist==NIL) |
169 | | -{ |
170 | | -/* |
171 | | - * If we find a qual-less subscan, it represents a constant |
172 | | - * TRUE, and hence the OR result is also constant TRUE, so we |
173 | | - * can stop here. |
174 | | - */ |
175 | | -returnNIL; |
176 | | -} |
177 | | - |
178 | | -/* |
179 | | - * If the sublist contains multiple RestrictInfos, we create an |
180 | | - * AND subclause. If there's just one, we have to check if it's |
181 | | - * an OR clause, and if so flatten it to preserve AND/OR flatness |
182 | | - * of our output. |
183 | | - * |
184 | | - * We construct lists with and without sub-RestrictInfos, so as |
185 | | - * not to have to regenerate duplicate RestrictInfos below. |
186 | | - */ |
187 | | -if (list_length(sublist)>1) |
188 | | -{ |
189 | | -withris=lappend(withris,make_andclause(sublist)); |
190 | | -sublist=get_actual_clauses(sublist); |
191 | | -withoutris=lappend(withoutris,make_andclause(sublist)); |
192 | | -} |
193 | | -else |
194 | | -{ |
195 | | -RestrictInfo*subri= (RestrictInfo*)linitial(sublist); |
196 | | - |
197 | | -Assert(IsA(subri,RestrictInfo)); |
198 | | -if (restriction_is_or_clause(subri)) |
199 | | -{ |
200 | | -BoolExpr*subor= (BoolExpr*)subri->orclause; |
201 | | - |
202 | | -Assert(or_clause((Node*)subor)); |
203 | | -withris=list_concat(withris, |
204 | | -list_copy(subor->args)); |
205 | | -subor= (BoolExpr*)subri->clause; |
206 | | -Assert(or_clause((Node*)subor)); |
207 | | -withoutris=list_concat(withoutris, |
208 | | -list_copy(subor->args)); |
209 | | -} |
210 | | -else |
211 | | -{ |
212 | | -withris=lappend(withris,subri); |
213 | | -withoutris=lappend(withoutris,subri->clause); |
214 | | -} |
215 | | -} |
216 | | -} |
217 | | - |
218 | | -/* |
219 | | - * Avoid generating one-element ORs, which could happen due to |
220 | | - * redundancy elimination or ScalarArrayOpExpr quals. |
221 | | - */ |
222 | | -if (list_length(withris) <=1) |
223 | | -result=withris; |
224 | | -else |
225 | | -{ |
226 | | -/* Here's the magic part not available to outside callers */ |
227 | | -result= |
228 | | -list_make1(make_restrictinfo_internal(make_orclause(withoutris), |
229 | | -make_orclause(withris), |
230 | | -is_pushed_down, |
231 | | - false, |
232 | | - false, |
233 | | -NULL, |
234 | | -NULL, |
235 | | -NULL)); |
236 | | -} |
237 | | -} |
238 | | -elseif (IsA(bitmapqual,IndexPath)) |
239 | | -{ |
240 | | -IndexPath*ipath= (IndexPath*)bitmapqual; |
241 | | - |
242 | | -result=list_copy(ipath->indexclauses); |
243 | | -if (include_predicates&&ipath->indexinfo->indpred!=NIL) |
244 | | -{ |
245 | | -foreach(l,ipath->indexinfo->indpred) |
246 | | -{ |
247 | | -Expr*pred= (Expr*)lfirst(l); |
248 | | - |
249 | | -/* |
250 | | - * We know that the index predicate must have been implied by |
251 | | - * the query condition as a whole, but it may or may not be |
252 | | - * implied by the conditions that got pushed into the |
253 | | - * bitmapqual.Avoid generating redundant conditions. |
254 | | - */ |
255 | | -if (!predicate_implied_by(list_make1(pred),result)) |
256 | | -result=lappend(result, |
257 | | -make_restrictinfo(pred, |
258 | | -is_pushed_down, |
259 | | - false, |
260 | | - false, |
261 | | -NULL, |
262 | | -NULL, |
263 | | -NULL)); |
264 | | -} |
265 | | -} |
266 | | -} |
267 | | -else |
268 | | -{ |
269 | | -elog(ERROR,"unrecognized node type: %d",nodeTag(bitmapqual)); |
270 | | -result=NIL;/* keep compiler quiet */ |
271 | | -} |
272 | | - |
273 | | -returnresult; |
274 | | -} |
275 | | - |
276 | 89 | /* |
277 | 90 | * make_restrictinfos_from_actual_clauses |
278 | 91 | * |
|