OSDN Git Service

Update copyright for 2009.
[pg-rex/syncrep.git] / src / backend / optimizer / path / clausesel.c
1 /*-------------------------------------------------------------------------
2  *
3  * clausesel.c
4  *        Routines to compute clause selectivities
5  *
6  * Portions Copyright (c) 1996-2009, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *        $PostgreSQL: pgsql/src/backend/optimizer/path/clausesel.c,v 1.96 2009/01/01 17:23:43 momjian Exp $
12  *
13  *-------------------------------------------------------------------------
14  */
15 #include "postgres.h"
16
17 #include "catalog/pg_operator.h"
18 #include "nodes/makefuncs.h"
19 #include "optimizer/clauses.h"
20 #include "optimizer/cost.h"
21 #include "optimizer/pathnode.h"
22 #include "optimizer/plancat.h"
23 #include "parser/parsetree.h"
24 #include "utils/fmgroids.h"
25 #include "utils/lsyscache.h"
26 #include "utils/selfuncs.h"
27
28
29 /*
30  * Data structure for accumulating info about possible range-query
31  * clause pairs in clauselist_selectivity.
32  */
33 typedef struct RangeQueryClause
34 {
35         struct RangeQueryClause *next;          /* next in linked list */
36         Node       *var;                        /* The common variable of the clauses */
37         bool            have_lobound;   /* found a low-bound clause yet? */
38         bool            have_hibound;   /* found a high-bound clause yet? */
39         Selectivity lobound;            /* Selectivity of a var > something clause */
40         Selectivity hibound;            /* Selectivity of a var < something clause */
41 } RangeQueryClause;
42
43 static void addRangeClause(RangeQueryClause **rqlist, Node *clause,
44                            bool varonleft, bool isLTsel, Selectivity s2);
45
46
47 /****************************************************************************
48  *              ROUTINES TO COMPUTE SELECTIVITIES
49  ****************************************************************************/
50
51 /*
52  * clauselist_selectivity -
53  *        Compute the selectivity of an implicitly-ANDed list of boolean
54  *        expression clauses.  The list can be empty, in which case 1.0
55  *        must be returned.  List elements may be either RestrictInfos
56  *        or bare expression clauses --- the former is preferred since
57  *        it allows caching of results.
58  *
59  * See clause_selectivity() for the meaning of the additional parameters.
60  *
61  * Our basic approach is to take the product of the selectivities of the
62  * subclauses.  However, that's only right if the subclauses have independent
63  * probabilities, and in reality they are often NOT independent.  So,
64  * we want to be smarter where we can.
65
66  * Currently, the only extra smarts we have is to recognize "range queries",
67  * such as "x > 34 AND x < 42".  Clauses are recognized as possible range
68  * query components if they are restriction opclauses whose operators have
69  * scalarltsel() or scalargtsel() as their restriction selectivity estimator.
70  * We pair up clauses of this form that refer to the same variable.  An
71  * unpairable clause of this kind is simply multiplied into the selectivity
72  * product in the normal way.  But when we find a pair, we know that the
73  * selectivities represent the relative positions of the low and high bounds
74  * within the column's range, so instead of figuring the selectivity as
75  * hisel * losel, we can figure it as hisel + losel - 1.  (To visualize this,
76  * see that hisel is the fraction of the range below the high bound, while
77  * losel is the fraction above the low bound; so hisel can be interpreted
78  * directly as a 0..1 value but we need to convert losel to 1-losel before
79  * interpreting it as a value.  Then the available range is 1-losel to hisel.
80  * However, this calculation double-excludes nulls, so really we need
81  * hisel + losel + null_frac - 1.)
82  *
83  * If either selectivity is exactly DEFAULT_INEQ_SEL, we forget this equation
84  * and instead use DEFAULT_RANGE_INEQ_SEL.      The same applies if the equation
85  * yields an impossible (negative) result.
86  *
87  * A free side-effect is that we can recognize redundant inequalities such
88  * as "x < 4 AND x < 5"; only the tighter constraint will be counted.
89  *
90  * Of course this is all very dependent on the behavior of
91  * scalarltsel/scalargtsel; perhaps some day we can generalize the approach.
92  */
93 Selectivity
94 clauselist_selectivity(PlannerInfo *root,
95                                            List *clauses,
96                                            int varRelid,
97                                            JoinType jointype,
98                                            SpecialJoinInfo *sjinfo)
99 {
100         Selectivity s1 = 1.0;
101         RangeQueryClause *rqlist = NULL;
102         ListCell   *l;
103
104         /*
105          * If there's exactly one clause, then no use in trying to match up
106          * pairs, so just go directly to clause_selectivity().
107          */
108         if (list_length(clauses) == 1)
109                 return clause_selectivity(root, (Node *) linitial(clauses),
110                                                                   varRelid, jointype, sjinfo);
111
112         /*
113          * Initial scan over clauses.  Anything that doesn't look like a potential
114          * rangequery clause gets multiplied into s1 and forgotten. Anything that
115          * does gets inserted into an rqlist entry.
116          */
117         foreach(l, clauses)
118         {
119                 Node       *clause = (Node *) lfirst(l);
120                 RestrictInfo *rinfo;
121                 Selectivity s2;
122
123                 /* Always compute the selectivity using clause_selectivity */
124                 s2 = clause_selectivity(root, clause, varRelid, jointype, sjinfo);
125
126                 /*
127                  * Check for being passed a RestrictInfo.
128                  *
129                  * If it's a pseudoconstant RestrictInfo, then s2 is either 1.0 or
130                  * 0.0; just use that rather than looking for range pairs.
131                  */
132                 if (IsA(clause, RestrictInfo))
133                 {
134                         rinfo = (RestrictInfo *) clause;
135                         if (rinfo->pseudoconstant)
136                         {
137                                 s1 = s1 * s2;
138                                 continue;
139                         }
140                         clause = (Node *) rinfo->clause;
141                 }
142                 else
143                         rinfo = NULL;
144
145                 /*
146                  * See if it looks like a restriction clause with a pseudoconstant on
147                  * one side.  (Anything more complicated than that might not behave in
148                  * the simple way we are expecting.)  Most of the tests here can be
149                  * done more efficiently with rinfo than without.
150                  */
151                 if (is_opclause(clause) && list_length(((OpExpr *) clause)->args) == 2)
152                 {
153                         OpExpr     *expr = (OpExpr *) clause;
154                         bool            varonleft = true;
155                         bool            ok;
156
157                         if (rinfo)
158                         {
159                                 ok = (bms_membership(rinfo->clause_relids) == BMS_SINGLETON) &&
160                                         (is_pseudo_constant_clause_relids(lsecond(expr->args),
161                                                                                                           rinfo->right_relids) ||
162                                          (varonleft = false,
163                                           is_pseudo_constant_clause_relids(linitial(expr->args),
164                                                                                                            rinfo->left_relids)));
165                         }
166                         else
167                         {
168                                 ok = (NumRelids(clause) == 1) &&
169                                         (is_pseudo_constant_clause(lsecond(expr->args)) ||
170                                          (varonleft = false,
171                                           is_pseudo_constant_clause(linitial(expr->args))));
172                         }
173
174                         if (ok)
175                         {
176                                 /*
177                                  * If it's not a "<" or ">" operator, just merge the
178                                  * selectivity in generically.  But if it's the right oprrest,
179                                  * add the clause to rqlist for later processing.
180                                  */
181                                 switch (get_oprrest(expr->opno))
182                                 {
183                                         case F_SCALARLTSEL:
184                                                 addRangeClause(&rqlist, clause,
185                                                                            varonleft, true, s2);
186                                                 break;
187                                         case F_SCALARGTSEL:
188                                                 addRangeClause(&rqlist, clause,
189                                                                            varonleft, false, s2);
190                                                 break;
191                                         default:
192                                                 /* Just merge the selectivity in generically */
193                                                 s1 = s1 * s2;
194                                                 break;
195                                 }
196                                 continue;               /* drop to loop bottom */
197                         }
198                 }
199
200                 /* Not the right form, so treat it generically. */
201                 s1 = s1 * s2;
202         }
203
204         /*
205          * Now scan the rangequery pair list.
206          */
207         while (rqlist != NULL)
208         {
209                 RangeQueryClause *rqnext;
210
211                 if (rqlist->have_lobound && rqlist->have_hibound)
212                 {
213                         /* Successfully matched a pair of range clauses */
214                         Selectivity s2;
215
216                         /*
217                          * Exact equality to the default value probably means the
218                          * selectivity function punted.  This is not airtight but should
219                          * be good enough.
220                          */
221                         if (rqlist->hibound == DEFAULT_INEQ_SEL ||
222                                 rqlist->lobound == DEFAULT_INEQ_SEL)
223                         {
224                                 s2 = DEFAULT_RANGE_INEQ_SEL;
225                         }
226                         else
227                         {
228                                 s2 = rqlist->hibound + rqlist->lobound - 1.0;
229
230                                 /* Adjust for double-exclusion of NULLs */
231                                 s2 += nulltestsel(root, IS_NULL, rqlist->var,
232                                                                   varRelid, jointype, sjinfo);
233
234                                 /*
235                                  * A zero or slightly negative s2 should be converted into a
236                                  * small positive value; we probably are dealing with a very
237                                  * tight range and got a bogus result due to roundoff errors.
238                                  * However, if s2 is very negative, then we probably have
239                                  * default selectivity estimates on one or both sides of the
240                                  * range that we failed to recognize above for some reason.
241                                  */
242                                 if (s2 <= 0.0)
243                                 {
244                                         if (s2 < -0.01)
245                                         {
246                                                 /*
247                                                  * No data available --- use a default estimate that
248                                                  * is small, but not real small.
249                                                  */
250                                                 s2 = DEFAULT_RANGE_INEQ_SEL;
251                                         }
252                                         else
253                                         {
254                                                 /*
255                                                  * It's just roundoff error; use a small positive
256                                                  * value
257                                                  */
258                                                 s2 = 1.0e-10;
259                                         }
260                                 }
261                         }
262                         /* Merge in the selectivity of the pair of clauses */
263                         s1 *= s2;
264                 }
265                 else
266                 {
267                         /* Only found one of a pair, merge it in generically */
268                         if (rqlist->have_lobound)
269                                 s1 *= rqlist->lobound;
270                         else
271                                 s1 *= rqlist->hibound;
272                 }
273                 /* release storage and advance */
274                 rqnext = rqlist->next;
275                 pfree(rqlist);
276                 rqlist = rqnext;
277         }
278
279         return s1;
280 }
281
282 /*
283  * addRangeClause --- add a new range clause for clauselist_selectivity
284  *
285  * Here is where we try to match up pairs of range-query clauses
286  */
287 static void
288 addRangeClause(RangeQueryClause **rqlist, Node *clause,
289                            bool varonleft, bool isLTsel, Selectivity s2)
290 {
291         RangeQueryClause *rqelem;
292         Node       *var;
293         bool            is_lobound;
294
295         if (varonleft)
296         {
297                 var = get_leftop((Expr *) clause);
298                 is_lobound = !isLTsel;  /* x < something is high bound */
299         }
300         else
301         {
302                 var = get_rightop((Expr *) clause);
303                 is_lobound = isLTsel;   /* something < x is low bound */
304         }
305
306         for (rqelem = *rqlist; rqelem; rqelem = rqelem->next)
307         {
308                 /*
309                  * We use full equal() here because the "var" might be a function of
310                  * one or more attributes of the same relation...
311                  */
312                 if (!equal(var, rqelem->var))
313                         continue;
314                 /* Found the right group to put this clause in */
315                 if (is_lobound)
316                 {
317                         if (!rqelem->have_lobound)
318                         {
319                                 rqelem->have_lobound = true;
320                                 rqelem->lobound = s2;
321                         }
322                         else
323                         {
324
325                                 /*------
326                                  * We have found two similar clauses, such as
327                                  * x < y AND x < z.
328                                  * Keep only the more restrictive one.
329                                  *------
330                                  */
331                                 if (rqelem->lobound > s2)
332                                         rqelem->lobound = s2;
333                         }
334                 }
335                 else
336                 {
337                         if (!rqelem->have_hibound)
338                         {
339                                 rqelem->have_hibound = true;
340                                 rqelem->hibound = s2;
341                         }
342                         else
343                         {
344
345                                 /*------
346                                  * We have found two similar clauses, such as
347                                  * x > y AND x > z.
348                                  * Keep only the more restrictive one.
349                                  *------
350                                  */
351                                 if (rqelem->hibound > s2)
352                                         rqelem->hibound = s2;
353                         }
354                 }
355                 return;
356         }
357
358         /* No matching var found, so make a new clause-pair data structure */
359         rqelem = (RangeQueryClause *) palloc(sizeof(RangeQueryClause));
360         rqelem->var = var;
361         if (is_lobound)
362         {
363                 rqelem->have_lobound = true;
364                 rqelem->have_hibound = false;
365                 rqelem->lobound = s2;
366         }
367         else
368         {
369                 rqelem->have_lobound = false;
370                 rqelem->have_hibound = true;
371                 rqelem->hibound = s2;
372         }
373         rqelem->next = *rqlist;
374         *rqlist = rqelem;
375 }
376
377 /*
378  * bms_is_subset_singleton
379  *
380  * Same result as bms_is_subset(s, bms_make_singleton(x)),
381  * but a little faster and doesn't leak memory.
382  *
383  * Is this of use anywhere else?  If so move to bitmapset.c ...
384  */
385 static bool
386 bms_is_subset_singleton(const Bitmapset *s, int x)
387 {
388         switch (bms_membership(s))
389         {
390                 case BMS_EMPTY_SET:
391                         return true;
392                 case BMS_SINGLETON:
393                         return bms_is_member(x, s);
394                 case BMS_MULTIPLE:
395                         return false;
396         }
397         /* can't get here... */
398         return false;
399 }
400
401 /*
402  * treat_as_join_clause -
403  *        Decide whether an operator clause is to be handled by the
404  *        restriction or join estimator.  Subroutine for clause_selectivity().
405  */
406 static inline bool
407 treat_as_join_clause(Node *clause, RestrictInfo *rinfo,
408                                          int varRelid, SpecialJoinInfo *sjinfo)
409 {
410         if (varRelid != 0)
411         {
412                 /*
413                  * Caller is forcing restriction mode (eg, because we are examining
414                  * an inner indexscan qual).
415                  */
416                 return false;
417         }
418         else if (sjinfo == NULL)
419         {
420                 /*
421                  * It must be a restriction clause, since it's being evaluated at
422                  * a scan node.
423                  */
424                 return false;
425         }
426         else
427         {
428                 /*
429                  * Otherwise, it's a join if there's more than one relation used.
430                  * We can optimize this calculation if an rinfo was passed.
431                  *
432                  * XXX  Since we know the clause is being evaluated at a join,
433                  * the only way it could be single-relation is if it was delayed
434                  * by outer joins.  Although we can make use of the restriction
435                  * qual estimators anyway, it seems likely that we ought to account
436                  * for the probability of injected nulls somehow.
437                  */
438                 if (rinfo)
439                         return (bms_membership(rinfo->clause_relids) == BMS_MULTIPLE);
440                 else
441                         return (NumRelids(clause) > 1);
442         }
443 }
444
445
446 /*
447  * clause_selectivity -
448  *        Compute the selectivity of a general boolean expression clause.
449  *
450  * The clause can be either a RestrictInfo or a plain expression.  If it's
451  * a RestrictInfo, we try to cache the selectivity for possible re-use,
452  * so passing RestrictInfos is preferred.
453  *
454  * varRelid is either 0 or a rangetable index.
455  *
456  * When varRelid is not 0, only variables belonging to that relation are
457  * considered in computing selectivity; other vars are treated as constants
458  * of unknown values.  This is appropriate for estimating the selectivity of
459  * a join clause that is being used as a restriction clause in a scan of a
460  * nestloop join's inner relation --- varRelid should then be the ID of the
461  * inner relation.
462  *
463  * When varRelid is 0, all variables are treated as variables.  This
464  * is appropriate for ordinary join clauses and restriction clauses.
465  *
466  * jointype is the join type, if the clause is a join clause.  Pass JOIN_INNER
467  * if the clause isn't a join clause.
468  *
469  * sjinfo is NULL for a non-join clause, otherwise it provides additional
470  * context information about the join being performed.  There are some
471  * special cases:
472  *      1. For a special (not INNER) join, sjinfo is always a member of
473  *         root->join_info_list.
474  *      2. For an INNER join, sjinfo is just a transient struct, and only the
475  *         relids and jointype fields in it can be trusted.
476  * It is possible for jointype to be different from sjinfo->jointype.
477  * This indicates we are considering a variant join: either with
478  * the LHS and RHS switched, or with one input unique-ified.
479  *
480  * Note: when passing nonzero varRelid, it's normally appropriate to set
481  * jointype == JOIN_INNER, sjinfo == NULL, even if the clause is really a
482  * join clause; because we aren't treating it as a join clause.
483  */
484 Selectivity
485 clause_selectivity(PlannerInfo *root,
486                                    Node *clause,
487                                    int varRelid,
488                                    JoinType jointype,
489                                    SpecialJoinInfo *sjinfo)
490 {
491         Selectivity s1 = 0.5;           /* default for any unhandled clause type */
492         RestrictInfo *rinfo = NULL;
493         bool            cacheable = false;
494
495         if (clause == NULL)                     /* can this still happen? */
496                 return s1;
497
498         if (IsA(clause, RestrictInfo))
499         {
500                 rinfo = (RestrictInfo *) clause;
501
502                 /*
503                  * If the clause is marked pseudoconstant, then it will be used as a
504                  * gating qual and should not affect selectivity estimates; hence
505                  * return 1.0.  The only exception is that a constant FALSE may be
506                  * taken as having selectivity 0.0, since it will surely mean no rows
507                  * out of the plan.  This case is simple enough that we need not
508                  * bother caching the result.
509                  */
510                 if (rinfo->pseudoconstant)
511                 {
512                         if (!IsA(rinfo->clause, Const))
513                                 return (Selectivity) 1.0;
514                 }
515
516                 /*
517                  * If the clause is marked redundant, always return 1.0.
518                  */
519                 if (rinfo->this_selec > 1)
520                         return (Selectivity) 1.0;
521
522                 /*
523                  * If possible, cache the result of the selectivity calculation for
524                  * the clause.  We can cache if varRelid is zero or the clause
525                  * contains only vars of that relid --- otherwise varRelid will affect
526                  * the result, so mustn't cache.
527                  */
528                 if (varRelid == 0 ||
529                         bms_is_subset_singleton(rinfo->clause_relids, varRelid))
530                 {
531                         /* Cacheable --- do we already have the result? */
532                         if (rinfo->this_selec >= 0)
533                                 return rinfo->this_selec;
534                         cacheable = true;
535                 }
536
537                 /*
538                  * Proceed with examination of contained clause.  If the clause is an
539                  * OR-clause, we want to look at the variant with sub-RestrictInfos,
540                  * so that per-subclause selectivities can be cached.
541                  */
542                 if (rinfo->orclause)
543                         clause = (Node *) rinfo->orclause;
544                 else
545                         clause = (Node *) rinfo->clause;
546         }
547
548         if (IsA(clause, Var))
549         {
550                 Var                *var = (Var *) clause;
551
552                 /*
553                  * We probably shouldn't ever see an uplevel Var here, but if we do,
554                  * return the default selectivity...
555                  */
556                 if (var->varlevelsup == 0 &&
557                         (varRelid == 0 || varRelid == (int) var->varno))
558                 {
559                         /*
560                          * A Var at the top of a clause must be a bool Var. This is
561                          * equivalent to the clause reln.attribute = 't', so we
562                          * compute the selectivity as if that is what we have.
563                          */
564                         s1 = restriction_selectivity(root,
565                                                                                  BooleanEqualOperator,
566                                                                                  list_make2(var,
567                                                                                                         makeBoolConst(true,
568                                                                                                                                   false)),
569                                                                                  varRelid);
570                 }
571         }
572         else if (IsA(clause, Const))
573         {
574                 /* bool constant is pretty easy... */
575                 Const      *con = (Const *) clause;
576
577                 s1 = con->constisnull ? 0.0 :
578                         DatumGetBool(con->constvalue) ? 1.0 : 0.0;
579         }
580         else if (IsA(clause, Param))
581         {
582                 /* see if we can replace the Param */
583                 Node       *subst = estimate_expression_value(root, clause);
584
585                 if (IsA(subst, Const))
586                 {
587                         /* bool constant is pretty easy... */
588                         Const      *con = (Const *) subst;
589
590                         s1 = con->constisnull ? 0.0 :
591                                 DatumGetBool(con->constvalue) ? 1.0 : 0.0;
592                 }
593                 else
594                 {
595                         /* XXX any way to do better than default? */
596                 }
597         }
598         else if (not_clause(clause))
599         {
600                 /* inverse of the selectivity of the underlying clause */
601                 s1 = 1.0 - clause_selectivity(root,
602                                                                   (Node *) get_notclausearg((Expr *) clause),
603                                                                           varRelid,
604                                                                           jointype,
605                                                                           sjinfo);
606         }
607         else if (and_clause(clause))
608         {
609                 /* share code with clauselist_selectivity() */
610                 s1 = clauselist_selectivity(root,
611                                                                         ((BoolExpr *) clause)->args,
612                                                                         varRelid,
613                                                                         jointype,
614                                                                         sjinfo);
615         }
616         else if (or_clause(clause))
617         {
618                 /*
619                  * Selectivities for an OR clause are computed as s1+s2 - s1*s2 to
620                  * account for the probable overlap of selected tuple sets.
621                  *
622                  * XXX is this too conservative?
623                  */
624                 ListCell   *arg;
625
626                 s1 = 0.0;
627                 foreach(arg, ((BoolExpr *) clause)->args)
628                 {
629                         Selectivity s2 = clause_selectivity(root,
630                                                                                                 (Node *) lfirst(arg),
631                                                                                                 varRelid,
632                                                                                                 jointype,
633                                                                                                 sjinfo);
634
635                         s1 = s1 + s2 - s1 * s2;
636                 }
637         }
638         else if (is_opclause(clause) || IsA(clause, DistinctExpr))
639         {
640                 Oid                     opno = ((OpExpr *) clause)->opno;
641
642                 if (treat_as_join_clause(clause, rinfo, varRelid, sjinfo))
643                 {
644                         /* Estimate selectivity for a join clause. */
645                         s1 = join_selectivity(root, opno,
646                                                                   ((OpExpr *) clause)->args,
647                                                                   jointype,
648                                                                   sjinfo);
649                 }
650                 else
651                 {
652                         /* Estimate selectivity for a restriction clause. */
653                         s1 = restriction_selectivity(root, opno,
654                                                                                  ((OpExpr *) clause)->args,
655                                                                                  varRelid);
656                 }
657
658                 /*
659                  * DistinctExpr has the same representation as OpExpr, but the
660                  * contained operator is "=" not "<>", so we must negate the result.
661                  * This estimation method doesn't give the right behavior for nulls,
662                  * but it's better than doing nothing.
663                  */
664                 if (IsA(clause, DistinctExpr))
665                         s1 = 1.0 - s1;
666         }
667         else if (is_funcclause(clause))
668         {
669                 /*
670                  * This is not an operator, so we guess at the selectivity. THIS IS A
671                  * HACK TO GET V4 OUT THE DOOR.  FUNCS SHOULD BE ABLE TO HAVE
672                  * SELECTIVITIES THEMSELVES.       -- JMH 7/9/92
673                  */
674                 s1 = (Selectivity) 0.3333333;
675         }
676 #ifdef NOT_USED
677         else if (IsA(clause, SubPlan) ||
678                          IsA(clause, AlternativeSubPlan))
679         {
680                 /*
681                  * Just for the moment! FIX ME! - vadim 02/04/98
682                  */
683                 s1 = (Selectivity) 0.5;
684         }
685 #endif
686         else if (IsA(clause, ScalarArrayOpExpr))
687         {
688                 /* Use node specific selectivity calculation function */
689                 s1 = scalararraysel(root,
690                                                         (ScalarArrayOpExpr *) clause,
691                                                         treat_as_join_clause(clause, rinfo,
692                                                                                                  varRelid, sjinfo),
693                                                         varRelid,
694                                                         jointype,
695                                                         sjinfo);
696         }
697         else if (IsA(clause, RowCompareExpr))
698         {
699                 /* Use node specific selectivity calculation function */
700                 s1 = rowcomparesel(root,
701                                                    (RowCompareExpr *) clause,
702                                                    varRelid,
703                                                    jointype,
704                                                    sjinfo);
705         }
706         else if (IsA(clause, NullTest))
707         {
708                 /* Use node specific selectivity calculation function */
709                 s1 = nulltestsel(root,
710                                                  ((NullTest *) clause)->nulltesttype,
711                                                  (Node *) ((NullTest *) clause)->arg,
712                                                  varRelid,
713                                                  jointype,
714                                                  sjinfo);
715         }
716         else if (IsA(clause, BooleanTest))
717         {
718                 /* Use node specific selectivity calculation function */
719                 s1 = booltestsel(root,
720                                                  ((BooleanTest *) clause)->booltesttype,
721                                                  (Node *) ((BooleanTest *) clause)->arg,
722                                                  varRelid,
723                                                  jointype,
724                                                  sjinfo);
725         }
726         else if (IsA(clause, CurrentOfExpr))
727         {
728                 /* CURRENT OF selects at most one row of its table */
729                 CurrentOfExpr *cexpr = (CurrentOfExpr *) clause;
730                 RelOptInfo *crel = find_base_rel(root, cexpr->cvarno);
731
732                 if (crel->tuples > 0)
733                         s1 = 1.0 / crel->tuples;
734         }
735         else if (IsA(clause, RelabelType))
736         {
737                 /* Not sure this case is needed, but it can't hurt */
738                 s1 = clause_selectivity(root,
739                                                                 (Node *) ((RelabelType *) clause)->arg,
740                                                                 varRelid,
741                                                                 jointype,
742                                                                 sjinfo);
743         }
744         else if (IsA(clause, CoerceToDomain))
745         {
746                 /* Not sure this case is needed, but it can't hurt */
747                 s1 = clause_selectivity(root,
748                                                                 (Node *) ((CoerceToDomain *) clause)->arg,
749                                                                 varRelid,
750                                                                 jointype,
751                                                                 sjinfo);
752         }
753
754         /* Cache the result if possible */
755         if (cacheable)
756                 rinfo->this_selec = s1;
757
758 #ifdef SELECTIVITY_DEBUG
759         elog(DEBUG4, "clause_selectivity: s1 %f", s1);
760 #endif   /* SELECTIVITY_DEBUG */
761
762         return s1;
763 }