Index: src/backend/utils/adt/selfuncs.c =================================================================== RCS file: /home/sriggs/pg/REPOSITORY/pgsql/src/backend/utils/adt/selfuncs.c,v retrieving revision 1.250 diff -c -r1.250 selfuncs.c *** src/backend/utils/adt/selfuncs.c 7 Jul 2008 20:24:55 -0000 1.250 --- src/backend/utils/adt/selfuncs.c 6 Aug 2008 22:24:08 -0000 *************** *** 103,108 **** --- 103,111 ---- #include "utils/selfuncs.h" #include "utils/syscache.h" + /* Hook for plugins to get control when we ask for stats */ + get_relation_stats_hook_type get_relation_stats_hook = NULL; + release_relation_stats_hook_type release_relation_stats_hook = NULL; static double var_eq_const(VariableStatData *vardata, Oid operator, Datum constval, bool constisnull, *************** *** 3769,3775 **** } else if (rte->rtekind == RTE_RELATION) { ! vardata->statsTuple = SearchSysCache(STATRELATT, ObjectIdGetDatum(rte->relid), Int16GetDatum(var->varattno), 0, 0); --- 3772,3786 ---- } else if (rte->rtekind == RTE_RELATION) { ! if (get_relation_stats_hook) ! vardata->statsTuple = (*get_relation_stats_hook) ! (rte->relid, ! var->varattno); ! ! if (vardata->statsTuple) ! vardata->free_using_plugin = true; ! else ! vardata->statsTuple = SearchSysCache(STATRELATT, ObjectIdGetDatum(rte->relid), Int16GetDatum(var->varattno), 0, 0); *************** *** 3889,3898 **** index->indpred == NIL) vardata->isunique = true; /* Has it got stats? */ ! vardata->statsTuple = SearchSysCache(STATRELATT, ObjectIdGetDatum(index->indexoid), ! Int16GetDatum(pos + 1), ! 0, 0); if (vardata->statsTuple) break; } --- 3900,3918 ---- index->indpred == NIL) vardata->isunique = true; /* Has it got stats? */ ! if (get_relation_stats_hook) ! { ! vardata->statsTuple = (*get_relation_stats_hook) ! (index->indexoid, ! pos + 1); ! vardata->free_using_plugin = true; ! } ! ! if (!vardata->statsTuple) ! vardata->statsTuple = SearchSysCache(STATRELATT, ObjectIdGetDatum(index->indexoid), ! Int16GetDatum(pos + 1), ! 0, 0); if (vardata->statsTuple) break; } *************** *** 5323,5329 **** double *indexCorrelation = (double *) PG_GETARG_POINTER(7); Oid relid; AttrNumber colnum; ! HeapTuple tuple; double numIndexTuples; List *indexBoundQuals; int indexcol; --- 5343,5349 ---- double *indexCorrelation = (double *) PG_GETARG_POINTER(7); Oid relid; AttrNumber colnum; ! HeapTuple tuple = NULL; double numIndexTuples; List *indexBoundQuals; int indexcol; *************** *** 5332,5337 **** --- 5352,5358 ---- bool found_null_op; double num_sa_scans; ListCell *l; + bool free_using_plugin = false; /* * For a btree scan, only leading '=' quals plus inequality quals for the *************** *** 5527,5536 **** colnum = 1; } ! tuple = SearchSysCache(STATRELATT, ! ObjectIdGetDatum(relid), ! Int16GetDatum(colnum), ! 0, 0); if (HeapTupleIsValid(tuple)) { --- 5548,5563 ---- colnum = 1; } ! if (get_relation_stats_hook) ! tuple = (*get_relation_stats_hook) (relid, colnum); ! ! if (tuple) ! free_using_plugin = true; ! else ! tuple = SearchSysCache(STATRELATT, ! ObjectIdGetDatum(relid), ! Int16GetDatum(colnum), ! 0, 0); if (HeapTupleIsValid(tuple)) { *************** *** 5571,5577 **** free_attstatsslot(InvalidOid, NULL, 0, numbers, nnumbers); } ! ReleaseSysCache(tuple); } PG_RETURN_VOID(); --- 5598,5605 ---- free_attstatsslot(InvalidOid, NULL, 0, numbers, nnumbers); } ! ! ReleaseStatsTuple(tuple, free_using_plugin); } PG_RETURN_VOID(); Index: src/backend/utils/cache/lsyscache.c =================================================================== RCS file: /home/sriggs/pg/REPOSITORY/pgsql/src/backend/utils/cache/lsyscache.c,v retrieving revision 1.157 diff -c -r1.157 lsyscache.c *** src/backend/utils/cache/lsyscache.c 13 Apr 2008 20:51:21 -0000 1.157 --- src/backend/utils/cache/lsyscache.c 6 Aug 2008 17:45:35 -0000 *************** *** 27,32 **** --- 27,33 ---- #include "catalog/pg_proc.h" #include "catalog/pg_statistic.h" #include "catalog/pg_type.h" + #include "optimizer/plancat.h" #include "miscadmin.h" #include "nodes/makefuncs.h" #include "utils/array.h" *************** *** 35,40 **** --- 36,43 ---- #include "utils/lsyscache.h" #include "utils/syscache.h" + /* Hook for plugins to get control in get_attavgwidth() */ + get_attavgwidth_hook_type get_attavgwidth_hook = NULL; /* ---------- AMOP CACHES ---------- */ *************** *** 2451,2466 **** * * Given the table and attribute number of a column, get the average * width of entries in the column. Return zero if no data available. */ int32 get_attavgwidth(Oid relid, AttrNumber attnum) { HeapTuple tp; tp = SearchSysCache(STATRELATT, ! ObjectIdGetDatum(relid), ! Int16GetDatum(attnum), ! 0, 0); if (HeapTupleIsValid(tp)) { int32 stawidth = ((Form_pg_statistic) GETSTRUCT(tp))->stawidth; --- 2454,2483 ---- * * Given the table and attribute number of a column, get the average * width of entries in the column. Return zero if no data available. + * + * Calling a hook at this point looks somewhat strange, but is required + * because the optimizer handles inheritance relations by calling for + * the avg width later in the planner than get_relation_info_hook(). + * So the APIs and call points of hooks must match the optimizer. */ int32 get_attavgwidth(Oid relid, AttrNumber attnum) { HeapTuple tp; + int32 stawidth; + + if (get_attavgwidth_hook) + { + stawidth = (*get_attavgwidth_hook) (relid, attnum); + if (stawidth > 0) + return stawidth; + } tp = SearchSysCache(STATRELATT, ! ObjectIdGetDatum(relid), ! Int16GetDatum(attnum), ! 0, 0); ! if (HeapTupleIsValid(tp)) { int32 stawidth = ((Form_pg_statistic) GETSTRUCT(tp))->stawidth; Index: src/include/optimizer/plancat.h =================================================================== RCS file: /home/sriggs/pg/REPOSITORY/pgsql/src/include/optimizer/plancat.h,v retrieving revision 1.50 diff -c -r1.50 plancat.h *** src/include/optimizer/plancat.h 19 Jun 2008 00:46:06 -0000 1.50 --- src/include/optimizer/plancat.h 6 Aug 2008 21:51:09 -0000 *************** *** 14,19 **** --- 14,20 ---- #ifndef PLANCAT_H #define PLANCAT_H + #include "access/htup.h" #include "nodes/relation.h" #include "utils/relcache.h" *************** *** 24,29 **** --- 25,41 ---- RelOptInfo *rel); extern PGDLLIMPORT get_relation_info_hook_type get_relation_info_hook; + /* Hooks for plugins to get control in lsyscache.c and selfuncs.c */ + typedef HeapTuple (*get_relation_stats_hook_type) (Oid relid, AttrNumber attnum); + extern PGDLLIMPORT get_relation_stats_hook_type get_relation_stats_hook; + + typedef void (*release_relation_stats_hook_type) (HeapTuple statstup); + extern PGDLLIMPORT release_relation_stats_hook_type release_relation_stats_hook; + + typedef int32 (*get_attavgwidth_hook_type) (Oid relid, AttrNumber attnum); + extern PGDLLIMPORT get_attavgwidth_hook_type get_attavgwidth_hook; + + extern void get_relation_info(PlannerInfo *root, Oid relationObjectId, bool inhparent, RelOptInfo *rel); Index: src/include/utils/selfuncs.h =================================================================== RCS file: /home/sriggs/pg/REPOSITORY/pgsql/src/include/utils/selfuncs.h,v retrieving revision 1.44 diff -c -r1.44 selfuncs.h *** src/include/utils/selfuncs.h 9 Mar 2008 00:32:09 -0000 1.44 --- src/include/utils/selfuncs.h 6 Aug 2008 21:53:53 -0000 *************** *** 74,85 **** Oid atttype; /* type to pass to get_attstatsslot */ int32 atttypmod; /* typmod to pass to get_attstatsslot */ bool isunique; /* true if matched to a unique index */ } VariableStatData; #define ReleaseVariableStats(vardata) \ do { \ if (HeapTupleIsValid((vardata).statsTuple)) \ ! ReleaseSysCache((vardata).statsTuple); \ } while(0) --- 74,112 ---- Oid atttype; /* type to pass to get_attstatsslot */ int32 atttypmod; /* typmod to pass to get_attstatsslot */ bool isunique; /* true if matched to a unique index */ + bool free_using_plugin; } VariableStatData; + #define ReleaseStatsTuple(tuple, free_using_plugin) \ + do { \ + if (HeapTupleIsValid(tuple)) \ + { \ + if (free_using_plugin) \ + { \ + if (release_relation_stats_hook) \ + (* release_relation_stats_hook)(tuple); \ + else \ + elog(ERROR, "unable to release variable stats correctly"); \ + } \ + else \ + ReleaseSysCache(tuple); \ + } \ + } while(0) + #define ReleaseVariableStats(vardata) \ do { \ if (HeapTupleIsValid((vardata).statsTuple)) \ ! { \ ! if ((vardata).free_using_plugin) \ ! { \ ! if (release_relation_stats_hook) \ ! (* release_relation_stats_hook)((vardata).statsTuple); \ ! else \ ! elog(ERROR, "unable to release variable stats correctly"); \ ! } \ ! else \ ! ReleaseSysCache((vardata).statsTuple); \ ! } \ } while(0)