11/*-------------------------------------------------------------------------
22 *
33 * clausesel.c
4- * Routines to computeand set clause selectivities
4+ * Routines to compute clause selectivities
55 *
66 * Copyright (c) 1994, Regents of the University of California
77 *
88 *
99 * IDENTIFICATION
10- * $Header: /cvsroot/pgsql/src/backend/optimizer/path/clausesel.c,v 1.27 2000/01/09 00:26:31 tgl Exp $
10+ * $Header: /cvsroot/pgsql/src/backend/optimizer/path/clausesel.c,v 1.28 2000/01/23 02:06:58 tgl Exp $
1111 *
1212 *-------------------------------------------------------------------------
1313 */
2828 ****************************************************************************/
2929
3030/*
31- *restrictlist_selec -
31+ *restrictlist_selectivity -
3232 * Compute the selectivity of an implicitly-ANDed list of RestrictInfo
3333 * clauses.
3434 *
35- * This is the same as clauselist_selec except for the form of the input.
35+ * This is the same as clauselist_selectivity except for the representation
36+ * of the clause list.
3637 */
3738Selectivity
38- restrictlist_selec (Query * root ,List * restrictinfo_list )
39+ restrictlist_selectivity (Query * root ,
40+ List * restrictinfo_list ,
41+ int varRelid )
3942{
4043List * clauselist = get_actual_clauses (restrictinfo_list );
4144Selectivity result ;
4245
43- result = clauselist_selec (root ,clauselist );
46+ result = clauselist_selectivity (root ,clauselist , varRelid );
4447freeList (clauselist );
4548return result ;
4649}
4750
4851/*
49- *clauselist_selec -
52+ *clauselist_selectivity -
5053 * Compute the selectivity of an implicitly-ANDed list of boolean
51- * expression clauses.
54+ * expression clauses. The list can be empty, in which case 1.0
55+ * must be returned.
56+ *
57+ * See clause_selectivity() for the meaning of the varRelid parameter.
5258 */
5359Selectivity
54- clauselist_selec (Query * root ,List * clauses )
60+ clauselist_selectivity (Query * root ,
61+ List * clauses ,
62+ int varRelid )
5563{
5664Selectivity s1 = 1.0 ;
5765List * clause ;
5866
5967/* Use the product of the selectivities of the subclauses.
60- * XXX this isprobably too optimistic, since the subclauses
68+ * XXX this is too optimistic, since the subclauses
6169 * are very likely not independent...
6270 */
6371foreach (clause ,clauses )
6472{
65- Selectivity s2 = compute_clause_selec (root , (Node * )lfirst (clause ));
73+ Selectivity s2 = clause_selectivity (root ,
74+ (Node * )lfirst (clause ),
75+ varRelid );
6676s1 = s1 * s2 ;
6777}
6878return s1 ;
6979}
7080
7181/*
72- *compute_clause_selec -
82+ *clause_selectivity -
7383 * Compute the selectivity of a general boolean expression clause.
84+ *
85+ * varRelid is either 0 or a rangetable index.
86+ *
87+ * When varRelid is not 0, only variables belonging to that relation are
88+ * considered in computing selectivity; other vars are treated as constants
89+ * of unknown values. This is appropriate for estimating the selectivity of
90+ * a join clause that is being used as a restriction clause in a scan of a
91+ * nestloop join's inner relation --- varRelid should then be the ID of the
92+ * inner relation.
93+ *
94+ * When varRelid is 0, all variables are treated as variables. This
95+ * is appropriate for ordinary join clauses and restriction clauses.
7496 */
7597Selectivity
76- compute_clause_selec (Query * root ,Node * clause )
98+ clause_selectivity (Query * root ,
99+ Node * clause ,
100+ int varRelid )
77101{
78102Selectivity s1 = 1.0 ;/* default for any unhandled clause type */
79103
@@ -88,13 +112,16 @@ compute_clause_selec(Query *root, Node *clause)
88112 * didn't want to have to do system cache look ups to find out all
89113 * of that info.
90114 */
91- s1 = restriction_selectivity (F_EQSEL ,
92- BooleanEqualOperator ,
93- getrelid (((Var * )clause )-> varno ,
94- root -> rtable ),
95- ((Var * )clause )-> varattno ,
96- Int8GetDatum (true),
97- SEL_CONSTANT |SEL_RIGHT );
115+ Index varno = ((Var * )clause )-> varno ;
116+
117+ if (varRelid == 0 || varRelid == varno )
118+ s1 = restriction_selectivity (F_EQSEL ,
119+ BooleanEqualOperator ,
120+ getrelid (varno ,root -> rtable ),
121+ ((Var * )clause )-> varattno ,
122+ Int8GetDatum (true),
123+ SEL_CONSTANT |SEL_RIGHT );
124+ /* an outer-relation bool var is taken as always true... */
98125}
99126else if (IsA (clause ,Param ))
100127{
@@ -109,12 +136,16 @@ compute_clause_selec(Query *root, Node *clause)
109136else if (not_clause (clause ))
110137{
111138/* inverse of the selectivity of the underlying clause */
112- s1 = 1.0 - compute_clause_selec (root ,
113- (Node * )get_notclausearg ((Expr * )clause ));
139+ s1 = 1.0 - clause_selectivity (root ,
140+ (Node * )get_notclausearg ((Expr * )clause ),
141+ varRelid );
114142}
115143else if (and_clause (clause ))
116144{
117- s1 = clauselist_selec (root , ((Expr * )clause )-> args );
145+ /* share code with clauselist_selectivity() */
146+ s1 = clauselist_selectivity (root ,
147+ ((Expr * )clause )-> args ,
148+ varRelid );
118149}
119150else if (or_clause (clause ))
120151{
@@ -127,50 +158,37 @@ compute_clause_selec(Query *root, Node *clause)
127158s1 = 0.0 ;
128159foreach (arg , ((Expr * )clause )-> args )
129160{
130- Selectivity s2 = compute_clause_selec (root , (Node * )lfirst (arg ));
161+ Selectivity s2 = clause_selectivity (root ,
162+ (Node * )lfirst (arg ),
163+ varRelid );
131164s1 = s1 + s2 - s1 * s2 ;
132165}
133166}
134167else if (is_opclause (clause ))
135168{
136- if (NumRelids (clause )== 1 )
137- {
138- /* The opclause is not a join clause, since there is only one
139- * relid in the clause. The clause selectivity will be based on
140- * the operator selectivity and operand values.
141- */
142- Oid opno = ((Oper * ) ((Expr * )clause )-> oper )-> opno ;
143- RegProcedure oprrest = get_oprrest (opno );
169+ Oid opno = ((Oper * ) ((Expr * )clause )-> oper )-> opno ;
170+ bool is_join_clause ;
144171
172+ if (varRelid != 0 )
173+ {
145174/*
146- * if the oprrest procedure is missing for whatever reason, use a
147- * selectivity of 0.5
175+ * If we are considering a nestloop join then all clauses
176+ * are restriction clauses, since we are only interested in
177+ * the one relation.
148178 */
149- if (!oprrest )
150- s1 = (Selectivity )0.5 ;
151- else
152- {
153- int relidx ;
154- AttrNumber attno ;
155- Datum constval ;
156- int flag ;
157- Oid reloid ;
158-
159- get_relattval (clause ,0 ,& relidx ,& attno ,& constval ,& flag );
160- reloid = relidx ?getrelid (relidx ,root -> rtable ) :InvalidOid ;
161- s1 = restriction_selectivity (oprrest ,opno ,
162- reloid ,attno ,
163- constval ,flag );
164- }
179+ is_join_clause = false;
165180}
166181else
167182{
168183/*
169- * The clause must be a join clause. The clause selectivity will
170- * be based on the relations to be scanned and the attributes they
171- * are to be joined on.
184+ * Otherwise, it's a join if there's more than one relation used.
172185 */
173- Oid opno = ((Oper * ) ((Expr * )clause )-> oper )-> opno ;
186+ is_join_clause = (NumRelids (clause )> 1 );
187+ }
188+
189+ if (is_join_clause )
190+ {
191+ /* Estimate selectivity for a join clause. */
174192RegProcedure oprjoin = get_oprjoin (opno );
175193
176194/*
@@ -196,6 +214,33 @@ compute_clause_selec(Query *root, Node *clause)
196214reloid2 ,attno2 );
197215}
198216}
217+ else
218+ {
219+ /* Estimate selectivity for a restriction clause. */
220+ RegProcedure oprrest = get_oprrest (opno );
221+
222+ /*
223+ * if the oprrest procedure is missing for whatever reason, use a
224+ * selectivity of 0.5
225+ */
226+ if (!oprrest )
227+ s1 = (Selectivity )0.5 ;
228+ else
229+ {
230+ int relidx ;
231+ AttrNumber attno ;
232+ Datum constval ;
233+ int flag ;
234+ Oid reloid ;
235+
236+ get_relattval (clause ,varRelid ,
237+ & relidx ,& attno ,& constval ,& flag );
238+ reloid = relidx ?getrelid (relidx ,root -> rtable ) :InvalidOid ;
239+ s1 = restriction_selectivity (oprrest ,opno ,
240+ reloid ,attno ,
241+ constval ,flag );
242+ }
243+ }
199244}
200245else if (is_funcclause (clause ))
201246{