15
15
*
16
16
*
17
17
* IDENTIFICATION
18
- * $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.258 2009/01/01 17:23:50 momjian Exp $
18
+ * $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.259 2009/02/15 20:16:21 tgl Exp $
19
19
*
20
20
*-------------------------------------------------------------------------
21
21
*/
@@ -234,6 +234,15 @@ var_eq_const(VariableStatData *vardata, Oid operator,
234
234
if (constisnull )
235
235
return 0.0 ;
236
236
237
+ /*
238
+ * If we matched the var to a unique index, assume there is exactly one
239
+ * match regardless of anything else. (This is slightly bogus, since
240
+ * the index's equality operator might be different from ours, but it's
241
+ * more likely to be right than ignoring the information.)
242
+ */
243
+ if (vardata -> isunique && vardata -> rel && vardata -> rel -> tuples >= 1.0 )
244
+ return 1.0 / vardata -> rel -> tuples ;
245
+
237
246
if (HeapTupleIsValid (vardata -> statsTuple ))
238
247
{
239
248
Form_pg_statistic stats ;
@@ -357,6 +366,15 @@ var_eq_non_const(VariableStatData *vardata, Oid operator,
357
366
{
358
367
double selec ;
359
368
369
+ /*
370
+ * If we matched the var to a unique index, assume there is exactly one
371
+ * match regardless of anything else. (This is slightly bogus, since
372
+ * the index's equality operator might be different from ours, but it's
373
+ * more likely to be right than ignoring the information.)
374
+ */
375
+ if (vardata -> isunique && vardata -> rel && vardata -> rel -> tuples >= 1.0 )
376
+ return 1.0 / vardata -> rel -> tuples ;
377
+
360
378
if (HeapTupleIsValid (vardata -> statsTuple ))
361
379
{
362
380
Form_pg_statistic stats ;
@@ -3969,6 +3987,8 @@ get_join_variables(PlannerInfo *root, List *args, SpecialJoinInfo *sjinfo,
3969
3987
* atttype, atttypmod: type data to pass to get_attstatsslot(). This is
3970
3988
* commonly the same as the exposed type of the variable argument,
3971
3989
* but can be different in binary-compatible-type cases.
3990
+ * isunique: TRUE if we were able to match the var to a unique index,
3991
+ * implying its values are unique for this query.
3972
3992
*
3973
3993
* Caller is responsible for doing ReleaseVariableStats() before exiting.
3974
3994
*/
@@ -4005,6 +4025,7 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid,
4005
4025
vardata -> rel = find_base_rel (root , var -> varno );
4006
4026
vardata -> atttype = var -> vartype ;
4007
4027
vardata -> atttypmod = var -> vartypmod ;
4028
+ vardata -> isunique = has_unique_index (vardata -> rel , var -> varattno );
4008
4029
4009
4030
rte = root -> simple_rte_array [var -> varno ];
4010
4031
@@ -4121,13 +4142,6 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid,
4121
4142
if (indexpr_item == NULL )
4122
4143
continue ; /* no expressions here... */
4123
4144
4124
- /*
4125
- * Ignore partial indexes since they probably don't reflect
4126
- * whole-relation statistics. Possibly reconsider this later.
4127
- */
4128
- if (index -> indpred )
4129
- continue ;
4130
-
4131
4145
for (pos = 0 ; pos < index -> ncolumns ; pos ++ )
4132
4146
{
4133
4147
if (index -> indexkeys [pos ] == 0 )
@@ -4147,9 +4161,19 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid,
4147
4161
*/
4148
4162
if (index -> unique &&
4149
4163
index -> ncolumns == 1 &&
4150
- index -> indpred == NIL )
4164
+ ( index -> indpred == NIL || index -> predOK ) )
4151
4165
vardata -> isunique = true;
4152
- /* Has it got stats? */
4166
+
4167
+ /*
4168
+ * Has it got stats? We only consider stats for
4169
+ * non-partial indexes, since partial indexes
4170
+ * probably don't reflect whole-relation statistics;
4171
+ * the above check for uniqueness is the only info
4172
+ * we take from a partial index.
4173
+ *
4174
+ * An index stats hook, however, must make its own
4175
+ * decisions about what to do with partial indexes.
4176
+ */
4153
4177
if (get_index_stats_hook &&
4154
4178
(* get_index_stats_hook ) (root , index -> indexoid ,
4155
4179
pos + 1 , vardata ))
@@ -4163,7 +4187,7 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid,
4163
4187
!vardata -> freefunc )
4164
4188
elog (ERROR , "no function provided to release variable stats with" );
4165
4189
}
4166
- else
4190
+ else if ( index -> indpred == NIL )
4167
4191
{
4168
4192
vardata -> statsTuple =
4169
4193
SearchSysCache (STATRELATT ,
@@ -4254,19 +4278,12 @@ get_variable_numdistinct(VariableStatData *vardata)
4254
4278
4255
4279
/*
4256
4280
* If there is a unique index for the variable, assume it is unique no
4257
- * matter what pg_statistic says (the statistics could be out of date).
4258
- * Can skip search if we already think it's unique.
4281
+ * matter what pg_statistic says; the statistics could be out of date,
4282
+ * or we might have found a partial unique index that proves the var
4283
+ * is unique for this query.
4259
4284
*/
4260
- if (stadistinct != -1.0 )
4261
- {
4262
- if (vardata -> isunique )
4263
- stadistinct = -1.0 ;
4264
- else if (vardata -> var && IsA (vardata -> var , Var ) &&
4265
- vardata -> rel &&
4266
- has_unique_index (vardata -> rel ,
4267
- ((Var * ) vardata -> var )-> varattno ))
4268
- stadistinct = -1.0 ;
4269
- }
4285
+ if (vardata -> isunique )
4286
+ stadistinct = -1.0 ;
4270
4287
4271
4288
/*
4272
4289
* If we had an absolute estimate, use that.
0 commit comments