1111 * Portions Copyright (c) 1994, Regents of the University of California
1212 *
1313 * IDENTIFICATION
14- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.44 2003/01/15 19:35:40 tgl Exp $
14+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/pathkeys.c,v 1.45 2003/01/24 03:58:35 tgl Exp $
1515 *
1616 *-------------------------------------------------------------------------
1717 */
2323#include "optimizer/paths.h"
2424#include "optimizer/planmain.h"
2525#include "optimizer/tlist.h"
26+ #include "optimizer/var.h"
2627#include "parser/parsetree.h"
2728#include "parser/parse_func.h"
2829#include "utils/lsyscache.h"
@@ -147,14 +148,30 @@ add_equijoined_keys(Query *root, RestrictInfo *restrictinfo)
147148 * generate_implied_equalities
148149 * Scan the completed equi_key_list for the query, and generate explicit
149150 * qualifications (WHERE clauses) for all the pairwise equalities not
150- * already mentioned in the quals. This is useful because the additional
151- * clauses help the selectivity-estimation code, and in fact it's
152- * *necessary* to ensure that sort keys we think are equivalent really
153- * are (see src/backend/optimizer/README for more info).
151+ * already mentioned in the quals; or remove qualifications found to be
152+ * redundant.
153+ *
154+ * Adding deduced equalities is useful because the additional clauses help
155+ * the selectivity-estimation code and may allow better joins to be chosen;
156+ * and in fact it's *necessary* to ensure that sort keys we think are
157+ * equivalent really are (see src/backend/optimizer/README for more info).
158+ *
159+ * If an equi_key_list set includes any constants then we adopt a different
160+ * strategy: we record all the "var = const" deductions we can make, and
161+ * actively remove all the "var = var" clauses that are implied by the set
162+ * (including the clauses that originally gave rise to the set!). The reason
163+ * is that given input like "a = b AND b = 42", once we have deduced "a = 42"
164+ * there is no longer any need to apply the clause "a = b"; not only is
165+ * it a waste of time to check it, but we will misestimate selectivity if the
166+ * clause is left in. So we must remove it. For this purpose, any pathkey
167+ * item that mentions no Vars of the current level can be taken as a constant.
168+ * (The only case where this would be risky is if the item contains volatile
169+ * functions; but we will never consider such an expression to be a pathkey
170+ * at all, because check_mergejoinable() will reject it.)
154171 *
155172 * This routine just walks the equi_key_list to find all pairwise equalities.
156- * We call process_implied_equality (in plan/initsplan.c) todetermine whether
157- *each is already known and add it to the proper restrictinfolist if not .
173+ * We call process_implied_equality (in plan/initsplan.c) toadjust the
174+ * restrictinfodatastructures for each pair .
158175 */
159176void
160177generate_implied_equalities (Query * root )
@@ -164,35 +181,119 @@ generate_implied_equalities(Query *root)
164181foreach (cursetlink ,root -> equi_key_list )
165182{
166183List * curset = lfirst (cursetlink );
184+ int nitems = length (curset );
185+ Relids * relids ;
186+ bool have_consts ;
167187List * ptr1 ;
188+ int i1 ;
168189
169190/*
170191 * A set containing only two items cannot imply any equalities
171192 * beyond the one that created the set, so we can skip it.
172193 */
173- if (length ( curset ) < 3 )
194+ if (nitems < 3 )
174195continue ;
175196
197+ /*
198+ * Collect info about relids mentioned in each item. For this
199+ * routine we only really care whether there are any at all in
200+ * each item, but process_implied_equality() needs the exact
201+ * lists, so we may as well pull them here.
202+ */
203+ relids = (Relids * )palloc (nitems * sizeof (Relids ));
204+ have_consts = false;
205+ i1 = 0 ;
206+ foreach (ptr1 ,curset )
207+ {
208+ PathKeyItem * item1 = (PathKeyItem * )lfirst (ptr1 );
209+
210+ relids [i1 ]= pull_varnos (item1 -> key );
211+ if (relids [i1 ]== NIL )
212+ have_consts = true;
213+ i1 ++ ;
214+ }
215+
176216/*
177217 * Match each item in the set with all that appear after it (it's
178218 * sufficient to generate A=B, need not process B=A too).
179219 */
220+ i1 = 0 ;
180221foreach (ptr1 ,curset )
181222{
182223PathKeyItem * item1 = (PathKeyItem * )lfirst (ptr1 );
183224List * ptr2 ;
225+ int i2 = i1 + 1 ;
184226
185227foreach (ptr2 ,lnext (ptr1 ))
186228{
187229PathKeyItem * item2 = (PathKeyItem * )lfirst (ptr2 );
188230
189- process_implied_equality (root ,item1 -> key ,item2 -> key ,
190- item1 -> sortop ,item2 -> sortop );
231+ /*
232+ * If it's "const = const" then just ignore it altogether.
233+ * There is no place in the restrictinfo structure to store
234+ * it. (If the two consts are in fact unequal, then
235+ * propagating the comparison to Vars will cause us to
236+ * produce zero rows out, as expected.)
237+ */
238+ if (relids [i1 ]!= NIL || relids [i2 ]!= NIL )
239+ {
240+ /*
241+ * Tell process_implied_equality to delete the clause,
242+ * not add it, if it's "var = var" and we have constants
243+ * present in the list.
244+ */
245+ bool delete_it = (have_consts &&
246+ relids [i1 ]!= NIL &&
247+ relids [i2 ]!= NIL );
248+ process_implied_equality (root ,
249+ item1 -> key ,item2 -> key ,
250+ item1 -> sortop ,item2 -> sortop ,
251+ relids [i1 ],relids [i2 ],
252+ delete_it );
253+ }
254+ i2 ++ ;
191255}
256+ i1 ++ ;
257+ }
258+ }
259+ }
260+
261+ /*
262+ * exprs_known_equal
263+ * Detect whether two expressions are known equal due to equijoin clauses.
264+ *
265+ * Note: does not bother to check for "equal(item1, item2)"; caller must
266+ * check that case if it's possible to pass identical items.
267+ */
268+ bool
269+ exprs_known_equal (Query * root ,Node * item1 ,Node * item2 )
270+ {
271+ List * cursetlink ;
272+
273+ foreach (cursetlink ,root -> equi_key_list )
274+ {
275+ List * curset = lfirst (cursetlink );
276+ bool item1member = false;
277+ bool item2member = false;
278+ List * ptr ;
279+
280+ foreach (ptr ,curset )
281+ {
282+ PathKeyItem * pitem = (PathKeyItem * )lfirst (ptr );
283+
284+ if (equal (item1 ,pitem -> key ))
285+ item1member = true;
286+ else if (equal (item2 ,pitem -> key ))
287+ item2member = true;
288+ /* Exit as soon as equality is proven */
289+ if (item1member && item2member )
290+ return true;
192291}
193292}
293+ return false;
194294}
195295
296+
196297/*
197298 * make_canonical_pathkey
198299 * Given a PathKeyItem, find the equi_key_list subset it is a member of,