@@ -41,8 +41,8 @@ typedef struct RangeQueryClause
41
41
42
42
static void addRangeClause (RangeQueryClause * * rqlist , Node * clause ,
43
43
bool varonleft , bool isLTsel , Selectivity s2 );
44
- static RelOptInfo * find_relation_from_clauses (PlannerInfo * root ,
45
- List * clauses );
44
+ static RelOptInfo * find_single_rel_for_clauses (PlannerInfo * root ,
45
+ List * clauses );
46
46
47
47
/****************************************************************************
48
48
* ROUTINES TO COMPUTE SELECTIVITIES
@@ -63,10 +63,8 @@ static RelOptInfo *find_relation_from_clauses(PlannerInfo *root,
63
63
* probabilities, and in reality they are often NOT independent. So,
64
64
* we want to be smarter where we can.
65
65
*
66
- * When 'rel' is not null and rtekind = RTE_RELATION, we'll try to apply
67
- * selectivity estimates using any extended statistcs on 'rel'.
68
- *
69
- * If we identify such extended statistics exist, we try to apply them.
66
+ * If the clauses taken together refer to just one relation, we'll try to
67
+ * apply selectivity estimates using any extended statistics for that rel.
70
68
* Currently we only have (soft) functional dependencies, so apply these in as
71
69
* many cases as possible, and fall back on normal estimates for remaining
72
70
* clauses.
@@ -105,41 +103,36 @@ clauselist_selectivity(PlannerInfo *root,
105
103
SpecialJoinInfo * sjinfo )
106
104
{
107
105
Selectivity s1 = 1.0 ;
106
+ RelOptInfo * rel ;
107
+ Bitmapset * estimatedclauses = NULL ;
108
108
RangeQueryClause * rqlist = NULL ;
109
109
ListCell * l ;
110
- Bitmapset * estimatedclauses = NULL ;
111
110
int listidx ;
112
- RelOptInfo * rel ;
113
111
114
112
/*
115
- * If there's exactly one clause, then extended statistics is futile at
116
- * this level (we might be able to apply them later if it's AND/OR
117
- * clause). So just go directly to clause_selectivity().
113
+ * If there's exactly one clause, just go directly to
114
+ * clause_selectivity(). None of what we might do below is relevant.
118
115
*/
119
116
if (list_length (clauses ) == 1 )
120
117
return clause_selectivity (root , (Node * ) linitial (clauses ),
121
118
varRelid , jointype , sjinfo );
122
119
123
120
/*
124
- * Determine if these clauses reference a single relation. If so we might
125
- * like to try applying any extended statistics which exist on it.
126
- * Called many time during joins, so must return NULL quickly if not.
127
- */
128
- rel = find_relation_from_clauses (root , clauses );
129
-
130
- /*
131
- * When a relation of RTE_RELATION is given as 'rel', we'll try to
132
- * perform selectivity estimation using extended statistics.
121
+ * Determine if these clauses reference a single relation. If so, and if
122
+ * it has extended statistics, try to apply those.
133
123
*/
124
+ rel = find_single_rel_for_clauses (root , clauses );
134
125
if (rel && rel -> rtekind == RTE_RELATION && rel -> statlist != NIL )
135
126
{
136
127
/*
137
128
* Perform selectivity estimations on any clauses found applicable by
138
- * dependencies_clauselist_selectivity. The 0-based list position of
139
- * estimated clauses will be populated in 'estimatedclauses'.
129
+ * dependencies_clauselist_selectivity. 'estimatedclauses' will be
130
+ * filled with the 0-based list positions of clauses used that way, so
131
+ * that we can ignore them below.
140
132
*/
141
133
s1 *= dependencies_clauselist_selectivity (root , clauses , varRelid ,
142
- jointype , sjinfo , rel , & estimatedclauses );
134
+ jointype , sjinfo , rel ,
135
+ & estimatedclauses );
143
136
144
137
/*
145
138
* This would be the place to apply any other types of extended
@@ -426,36 +419,46 @@ addRangeClause(RangeQueryClause **rqlist, Node *clause,
426
419
}
427
420
428
421
/*
429
- * find_relation_from_clauses
430
- * Process each clause in 'clauses' and determine if all clauses
431
- * reference only a single relation. If so return that relation,
422
+ * find_single_rel_for_clauses
423
+ * Examine each clause in 'clauses' and determine if all clauses
424
+ * reference only a single relation. If so return that relation,
432
425
* otherwise return NULL.
433
426
*/
434
427
static RelOptInfo *
435
- find_relation_from_clauses (PlannerInfo * root , List * clauses )
428
+ find_single_rel_for_clauses (PlannerInfo * root , List * clauses )
436
429
{
437
- ListCell * l ;
438
- int relid ;
439
- int lastrelid = 0 ;
430
+ int lastrelid = 0 ;
431
+ ListCell * l ;
440
432
441
433
foreach (l , clauses )
442
434
{
443
435
RestrictInfo * rinfo = (RestrictInfo * ) lfirst (l );
436
+ int relid ;
444
437
445
- if (bms_get_singleton_member (rinfo -> clause_relids , & relid ))
446
- {
447
- if (lastrelid != 0 && relid != lastrelid )
448
- return NULL ; /* relation not the same as last one */
449
- lastrelid = relid ;
450
- }
451
- else
452
- return NULL ; /* multiple relations in clause */
438
+ /*
439
+ * If we have a list of bare clauses rather than RestrictInfos, we
440
+ * could pull out their relids the hard way with pull_varnos().
441
+ * However, currently the extended-stats machinery won't do anything
442
+ * with non-RestrictInfo clauses anyway, so there's no point in
443
+ * spending extra cycles; just fail if that's what we have.
444
+ */
445
+ if (!IsA (rinfo , RestrictInfo ))
446
+ return NULL ;
447
+
448
+ if (bms_is_empty (rinfo -> clause_relids ))
449
+ continue ; /* we can ignore variable-free clauses */
450
+ if (!bms_get_singleton_member (rinfo -> clause_relids , & relid ))
451
+ return NULL ; /* multiple relations in this clause */
452
+ if (lastrelid == 0 )
453
+ lastrelid = relid ; /* first clause referencing a relation */
454
+ else if (relid != lastrelid )
455
+ return NULL ; /* relation not same as last one */
453
456
}
454
457
455
458
if (lastrelid != 0 )
456
459
return find_base_rel (root , lastrelid );
457
460
458
- return NULL ; /* no clauses */
461
+ return NULL ; /* no clauses */
459
462
}
460
463
461
464
/*
0 commit comments