1515 *
1616 *
1717 * 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 $
1919 *
2020 *-------------------------------------------------------------------------
2121 */
119119#include "utils/syscache.h"
120120
121121
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+
122126static double var_eq_const (VariableStatData * vardata , Oid operator ,
123127 Datum constval , bool constisnull ,
124128 bool varonleft );
@@ -2935,7 +2939,7 @@ estimate_num_groups(PlannerInfo *root, List *groupExprs, double input_rows)
29352939 * complicated.
29362940 */
29372941 examine_variable (root , groupexpr , 0 , & vardata );
2938- if (vardata .statsTuple != NULL || vardata .isunique )
2942+ if (HeapTupleIsValid ( vardata .statsTuple ) || vardata .isunique )
29392943 {
29402944 varinfos = add_unique_group_var (root , varinfos ,
29412945 groupexpr , & vardata );
@@ -3942,6 +3946,7 @@ get_join_variables(PlannerInfo *root, List *args, SpecialJoinInfo *sjinfo,
39423946 * subquery, not one in the current query).
39433947 * statsTuple: the pg_statistic entry for the variable, if one exists;
39443948 * otherwise NULL.
3949+ * freefunc: pointer to a function to release statsTuple with.
39453950 * vartype: exposed type of the expression; this should always match
39463951 * the declared input type of the operator we are estimating for.
39473952 * atttype, atttypmod: type data to pass to get_attstatsslot(). This is
@@ -3986,7 +3991,18 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid,
39863991
39873992 rte = root -> simple_rte_array [var -> varno ];
39883993
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 )
39904006 {
39914007 /*
39924008 * XXX This means the Var represents a column of an append
@@ -4000,6 +4016,7 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid,
40004016 ObjectIdGetDatum (rte -> relid ),
40014017 Int16GetDatum (var -> varattno ),
40024018 0 , 0 );
4019+ vardata -> freefunc = ReleaseSysCache ;
40034020 }
40044021 else
40054022 {
@@ -4116,10 +4133,28 @@ examine_variable(PlannerInfo *root, Node *node, int varRelid,
41164133 index -> indpred == NIL )
41174134 vardata -> isunique = true;
41184135 /* 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+ }
41234158 if (vardata -> statsTuple )
41244159 break ;
41254160 }
@@ -5551,7 +5586,7 @@ btcostestimate(PG_FUNCTION_ARGS)
55515586 double * indexCorrelation = (double * ) PG_GETARG_POINTER (7 );
55525587 Oid relid ;
55535588 AttrNumber colnum ;
5554- HeapTuple tuple ;
5589+ VariableStatData vardata ;
55555590 double numIndexTuples ;
55565591 List * indexBoundQuals ;
55575592 int indexcol ;
@@ -5756,17 +5791,34 @@ btcostestimate(PG_FUNCTION_ARGS)
57565791 colnum = 1 ;
57575792 }
57585793
5759- tuple = SearchSysCache (STATRELATT ,
5760- ObjectIdGetDatum (relid ),
5761- Int16GetDatum (colnum ),
5762- 0 , 0 );
5794+ MemSet (& vardata , 0 , sizeof (vardata ));
57635795
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 ))
57655817 {
57665818 float4 * numbers ;
57675819 int nnumbers ;
57685820
5769- if (get_attstatsslot (tuple , InvalidOid , 0 ,
5821+ if (get_attstatsslot (vardata . statsTuple , InvalidOid , 0 ,
57705822 STATISTIC_KIND_CORRELATION ,
57715823 index -> fwdsortop [0 ],
57725824 NULL , NULL , & numbers , & nnumbers ))
@@ -5783,7 +5835,7 @@ btcostestimate(PG_FUNCTION_ARGS)
57835835
57845836 free_attstatsslot (InvalidOid , NULL , 0 , numbers , nnumbers );
57855837 }
5786- else if (get_attstatsslot (tuple , InvalidOid , 0 ,
5838+ else if (get_attstatsslot (vardata . statsTuple , InvalidOid , 0 ,
57875839 STATISTIC_KIND_CORRELATION ,
57885840 index -> revsortop [0 ],
57895841 NULL , NULL , & numbers , & nnumbers ))
@@ -5800,9 +5852,10 @@ btcostestimate(PG_FUNCTION_ARGS)
58005852
58015853 free_attstatsslot (InvalidOid , NULL , 0 , numbers , nnumbers );
58025854 }
5803- ReleaseSysCache (tuple );
58045855 }
58055856
5857+ ReleaseVariableStats (vardata );
5858+
58065859 PG_RETURN_VOID ();
58075860}
58085861
0 commit comments