15
15
*
16
16
*
17
17
* IDENTIFICATION
18
- * $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.253 2008/08/25 22:42:34 tgl Exp $
18
+ * $PostgreSQL: pgsql/src/backend/utils/adt/selfuncs.c,v 1.254 2008/09/28 19:51:40 tgl Exp $
19
19
*
20
20
*-------------------------------------------------------------------------
21
21
*/
119
119
#include "utils/syscache.h"
120
120
121
121
122
+ /* Hooks for plugins to get control when we ask for stats */
123
+ get_relation_stats_hook_type get_relation_stats_hook = NULL ;
124
+ get_index_stats_hook_type get_index_stats_hook = NULL ;
125
+
122
126
static double var_eq_const (VariableStatData * vardata , Oid operator ,
123
127
Datum constval , bool constisnull ,
124
128
bool varonleft );
@@ -2935,7 +2939,7 @@ estimate_num_groups(PlannerInfo *root, List *groupExprs, double input_rows)
2935
2939
* complicated.
2936
2940
*/
2937
2941
examine_variable (root , groupexpr , 0 , & vardata );
2938
- if (vardata .statsTuple != NULL || vardata .isunique )
2942
+ if (HeapTupleIsValid ( vardata .statsTuple ) || vardata .isunique )
2939
2943
{
2940
2944
varinfos = add_unique_group_var (root , varinfos ,
2941
2945
groupexpr , & vardata );
@@ -3942,6 +3946,7 @@ get_join_variables(PlannerInfo *root, List *args, SpecialJoinInfo *sjinfo,
3942
3946
* subquery, not one in the current query).
3943
3947
* statsTuple: the pg_statistic entry for the variable, if one exists;
3944
3948
* otherwise NULL.
3949
+ * freefunc: pointer to a function to release statsTuple with.
3945
3950
* vartype: exposed type of the expression; this should always match
3946
3951
* the declared input type of the operator we are estimating for.
3947
3952
* atttype, atttypmod: type data to pass to get_attstatsslot(). This is
@@ -3986,7 +3991,18 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid,
3986
3991
3987
3992
rte = root -> simple_rte_array [var -> varno ];
3988
3993
3989
- if (rte -> inh )
3994
+ if (get_relation_stats_hook &&
3995
+ (* get_relation_stats_hook ) (root , rte , var -> varattno , vardata ))
3996
+ {
3997
+ /*
3998
+ * The hook took control of acquiring a stats tuple. If it
3999
+ * did supply a tuple, it'd better have supplied a freefunc.
4000
+ */
4001
+ if (HeapTupleIsValid (vardata -> statsTuple ) &&
4002
+ !vardata -> freefunc )
4003
+ elog (ERROR , "no function provided to release variable stats with" );
4004
+ }
4005
+ else if (rte -> inh )
3990
4006
{
3991
4007
/*
3992
4008
* XXX This means the Var represents a column of an append
@@ -4000,6 +4016,7 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid,
4000
4016
ObjectIdGetDatum (rte -> relid ),
4001
4017
Int16GetDatum (var -> varattno ),
4002
4018
0 , 0 );
4019
+ vardata -> freefunc = ReleaseSysCache ;
4003
4020
}
4004
4021
else
4005
4022
{
@@ -4116,10 +4133,28 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid,
4116
4133
index -> indpred == NIL )
4117
4134
vardata -> isunique = true;
4118
4135
/* Has it got stats? */
4119
- vardata -> statsTuple = SearchSysCache (STATRELATT ,
4120
- ObjectIdGetDatum (index -> indexoid ),
4121
- Int16GetDatum (pos + 1 ),
4122
- 0 , 0 );
4136
+ if (get_index_stats_hook &&
4137
+ (* get_index_stats_hook ) (root , index -> indexoid ,
4138
+ pos + 1 , vardata ))
4139
+ {
4140
+ /*
4141
+ * The hook took control of acquiring a stats
4142
+ * tuple. If it did supply a tuple, it'd better
4143
+ * have supplied a freefunc.
4144
+ */
4145
+ if (HeapTupleIsValid (vardata -> statsTuple ) &&
4146
+ !vardata -> freefunc )
4147
+ elog (ERROR , "no function provided to release variable stats with" );
4148
+ }
4149
+ else
4150
+ {
4151
+ vardata -> statsTuple =
4152
+ SearchSysCache (STATRELATT ,
4153
+ ObjectIdGetDatum (index -> indexoid ),
4154
+ Int16GetDatum (pos + 1 ),
4155
+ 0 , 0 );
4156
+ vardata -> freefunc = ReleaseSysCache ;
4157
+ }
4123
4158
if (vardata -> statsTuple )
4124
4159
break ;
4125
4160
}
@@ -5551,7 +5586,7 @@ btcostestimate(PG_FUNCTION_ARGS)
5551
5586
double * indexCorrelation = (double * ) PG_GETARG_POINTER (7 );
5552
5587
Oid relid ;
5553
5588
AttrNumber colnum ;
5554
- HeapTuple tuple ;
5589
+ VariableStatData vardata ;
5555
5590
double numIndexTuples ;
5556
5591
List * indexBoundQuals ;
5557
5592
int indexcol ;
@@ -5756,17 +5791,34 @@ btcostestimate(PG_FUNCTION_ARGS)
5756
5791
colnum = 1 ;
5757
5792
}
5758
5793
5759
- tuple = SearchSysCache (STATRELATT ,
5760
- ObjectIdGetDatum (relid ),
5761
- Int16GetDatum (colnum ),
5762
- 0 , 0 );
5794
+ MemSet (& vardata , 0 , sizeof (vardata ));
5763
5795
5764
- if (HeapTupleIsValid (tuple ))
5796
+ if (get_index_stats_hook &&
5797
+ (* get_index_stats_hook ) (root , relid , colnum , & vardata ))
5798
+ {
5799
+ /*
5800
+ * The hook took control of acquiring a stats tuple. If it did supply
5801
+ * a tuple, it'd better have supplied a freefunc.
5802
+ */
5803
+ if (HeapTupleIsValid (vardata .statsTuple ) &&
5804
+ !vardata .freefunc )
5805
+ elog (ERROR , "no function provided to release variable stats with" );
5806
+ }
5807
+ else
5808
+ {
5809
+ vardata .statsTuple = SearchSysCache (STATRELATT ,
5810
+ ObjectIdGetDatum (relid ),
5811
+ Int16GetDatum (colnum ),
5812
+ 0 , 0 );
5813
+ vardata .freefunc = ReleaseSysCache ;
5814
+ }
5815
+
5816
+ if (HeapTupleIsValid (vardata .statsTuple ))
5765
5817
{
5766
5818
float4 * numbers ;
5767
5819
int nnumbers ;
5768
5820
5769
- if (get_attstatsslot (tuple , InvalidOid , 0 ,
5821
+ if (get_attstatsslot (vardata . statsTuple , InvalidOid , 0 ,
5770
5822
STATISTIC_KIND_CORRELATION ,
5771
5823
index -> fwdsortop [0 ],
5772
5824
NULL , NULL , & numbers , & nnumbers ))
@@ -5783,7 +5835,7 @@ btcostestimate(PG_FUNCTION_ARGS)
5783
5835
5784
5836
free_attstatsslot (InvalidOid , NULL , 0 , numbers , nnumbers );
5785
5837
}
5786
- else if (get_attstatsslot (tuple , InvalidOid , 0 ,
5838
+ else if (get_attstatsslot (vardata . statsTuple , InvalidOid , 0 ,
5787
5839
STATISTIC_KIND_CORRELATION ,
5788
5840
index -> revsortop [0 ],
5789
5841
NULL , NULL , & numbers , & nnumbers ))
@@ -5800,9 +5852,10 @@ btcostestimate(PG_FUNCTION_ARGS)
5800
5852
5801
5853
free_attstatsslot (InvalidOid , NULL , 0 , numbers , nnumbers );
5802
5854
}
5803
- ReleaseSysCache (tuple );
5804
5855
}
5805
5856
5857
+ ReleaseVariableStats (vardata );
5858
+
5806
5859
PG_RETURN_VOID ();
5807
5860
}
5808
5861
0 commit comments