diff options
Diffstat (limited to 'src/backend/utils')
-rw-r--r-- | src/backend/utils/adt/pgstatfuncs.c | 19 | ||||
-rw-r--r-- | src/backend/utils/cache/plancache.c | 42 | ||||
-rw-r--r-- | src/backend/utils/cache/relcache.c | 96 |
3 files changed, 154 insertions, 3 deletions
diff --git a/src/backend/utils/adt/pgstatfuncs.c b/src/backend/utils/adt/pgstatfuncs.c index 55951cf71b9..954e174bb71 100644 --- a/src/backend/utils/adt/pgstatfuncs.c +++ b/src/backend/utils/adt/pgstatfuncs.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/adt/pgstatfuncs.c,v 1.44 2007/09/11 03:28:05 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/adt/pgstatfuncs.c,v 1.45 2007/09/20 17:56:31 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -28,6 +28,7 @@ extern Datum pg_stat_get_tuples_fetched(PG_FUNCTION_ARGS); extern Datum pg_stat_get_tuples_inserted(PG_FUNCTION_ARGS); extern Datum pg_stat_get_tuples_updated(PG_FUNCTION_ARGS); extern Datum pg_stat_get_tuples_deleted(PG_FUNCTION_ARGS); +extern Datum pg_stat_get_tuples_hot_updated(PG_FUNCTION_ARGS); extern Datum pg_stat_get_live_tuples(PG_FUNCTION_ARGS); extern Datum pg_stat_get_dead_tuples(PG_FUNCTION_ARGS); extern Datum pg_stat_get_blocks_fetched(PG_FUNCTION_ARGS); @@ -170,6 +171,22 @@ pg_stat_get_tuples_deleted(PG_FUNCTION_ARGS) Datum +pg_stat_get_tuples_hot_updated(PG_FUNCTION_ARGS) +{ + Oid relid = PG_GETARG_OID(0); + int64 result; + PgStat_StatTabEntry *tabentry; + + if ((tabentry = pgstat_fetch_stat_tabentry(relid)) == NULL) + result = 0; + else + result = (int64) (tabentry->tuples_hot_updated); + + PG_RETURN_INT64(result); +} + + +Datum pg_stat_get_live_tuples(PG_FUNCTION_ARGS) { Oid relid = PG_GETARG_OID(0); diff --git a/src/backend/utils/cache/plancache.c b/src/backend/utils/cache/plancache.c index 21aed6eadbe..43297281f5f 100644 --- a/src/backend/utils/cache/plancache.c +++ b/src/backend/utils/cache/plancache.c @@ -33,13 +33,14 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/cache/plancache.c,v 1.10 2007/06/05 20:00:41 wieck Exp $ + * $PostgreSQL: pgsql/src/backend/utils/cache/plancache.c,v 1.11 2007/09/20 17:56:31 tgl Exp $ * *------------------------------------------------------------------------- */ #include "postgres.h" #include "utils/plancache.h" +#include "access/transam.h" #include "catalog/namespace.h" #include "executor/executor.h" #include "optimizer/clauses.h" @@ -79,6 +80,7 @@ static void ScanQueryForRelids(Query *parsetree, void *arg); static bool ScanQueryWalker(Node *node, ScanQueryWalkerContext *context); static bool rowmark_member(List *rowMarks, int rt_index); +static bool plan_list_is_transient(List *stmt_list); static void PlanCacheCallback(Datum arg, Oid relid); static void InvalRelid(Oid relid, LOCKMODE lockmode, InvalRelidContext *context); @@ -322,6 +324,13 @@ StoreCachedPlan(CachedPlanSource *plansource, plan->stmt_list = stmt_list; plan->fully_planned = plansource->fully_planned; plan->dead = false; + if (plansource->fully_planned && plan_list_is_transient(stmt_list)) + { + Assert(TransactionIdIsNormal(TransactionXmin)); + plan->saved_xmin = TransactionXmin; + } + else + plan->saved_xmin = InvalidTransactionId; plan->refcount = 1; /* for the parent's link */ plan->generation = ++(plansource->generation); plan->context = plan_context; @@ -412,6 +421,15 @@ RevalidateCachedPlan(CachedPlanSource *plansource, bool useResOwner) AcquirePlannerLocks(plan->stmt_list, true); /* + * If plan was transient, check to see if TransactionXmin has + * advanced, and if so invalidate it. + */ + if (!plan->dead && + TransactionIdIsValid(plan->saved_xmin) && + !TransactionIdEquals(plan->saved_xmin, TransactionXmin)) + plan->dead = true; + + /* * By now, if any invalidation has happened, PlanCacheCallback * will have marked the plan dead. */ @@ -790,6 +808,28 @@ rowmark_member(List *rowMarks, int rt_index) } /* + * plan_list_is_transient: check if any of the plans in the list are transient. + */ +static bool +plan_list_is_transient(List *stmt_list) +{ + ListCell *lc; + + foreach(lc, stmt_list) + { + PlannedStmt *plannedstmt = (PlannedStmt *) lfirst(lc); + + if (!IsA(plannedstmt, PlannedStmt)) + continue; /* Ignore utility statements */ + + if (plannedstmt->transientPlan) + return true; + } + + return false; +} + +/* * PlanCacheComputeResultDesc: given a list of either fully-planned statements * or Queries, determine the result tupledesc it will produce. Returns NULL * if the execution will not return tuples. diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index f69fb0c9362..8efa9e6c4e7 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.262 2007/07/25 22:16:18 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.263 2007/09/20 17:56:31 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -34,6 +34,7 @@ #include "access/reloptions.h" #include "access/xact.h" #include "catalog/catalog.h" +#include "catalog/index.h" #include "catalog/indexing.h" #include "catalog/namespace.h" #include "catalog/pg_amop.h" @@ -51,6 +52,7 @@ #include "optimizer/clauses.h" #include "optimizer/planmain.h" #include "optimizer/prep.h" +#include "optimizer/var.h" #include "rewrite/rewriteDefine.h" #include "storage/fd.h" #include "storage/smgr.h" @@ -1658,6 +1660,10 @@ RelationReloadIndexInfo(Relation relation) index = (Form_pg_index) GETSTRUCT(tuple); relation->rd_index->indisvalid = index->indisvalid; + relation->rd_index->indcheckxmin = index->indcheckxmin; + relation->rd_index->indisready = index->indisready; + HeapTupleHeaderSetXmin(relation->rd_indextuple->t_data, + HeapTupleHeaderGetXmin(tuple->t_data)); ReleaseSysCache(tuple); } @@ -1762,6 +1768,7 @@ RelationClearRelation(Relation relation, bool rebuild) if (relation->rd_options) pfree(relation->rd_options); list_free(relation->rd_indexlist); + bms_free(relation->rd_indexattr); if (relation->rd_indexcxt) MemoryContextDelete(relation->rd_indexcxt); @@ -2969,6 +2976,7 @@ RelationSetIndexList(Relation relation, List *indexIds, Oid oidIndex) relation->rd_indexvalid = 2; /* mark list as forced */ /* must flag that we have a forced index list */ need_eoxact_work = true; + /* we deliberately do not change rd_indexattr */ } /* @@ -3140,6 +3148,91 @@ RelationGetIndexPredicate(Relation relation) return result; } +/* + * RelationGetIndexAttrBitmap -- get a bitmap of index attribute numbers + * + * The result has a bit set for each attribute used anywhere in the index + * definitions of all the indexes on this relation. (This includes not only + * simple index keys, but attributes used in expressions and partial-index + * predicates.) + * + * Attribute numbers are offset by FirstLowInvalidHeapAttributeNumber so that + * we can include system attributes (e.g., OID) in the bitmap representation. + * + * The returned result is palloc'd in the caller's memory context and should + * be bms_free'd when not needed anymore. + */ +Bitmapset * +RelationGetIndexAttrBitmap(Relation relation) +{ + Bitmapset *indexattrs; + List *indexoidlist; + ListCell *l; + MemoryContext oldcxt; + + /* Quick exit if we already computed the result. */ + if (relation->rd_indexattr != NULL) + return bms_copy(relation->rd_indexattr); + + /* Fast path if definitely no indexes */ + if (!RelationGetForm(relation)->relhasindex) + return NULL; + + /* + * Get cached list of index OIDs + */ + indexoidlist = RelationGetIndexList(relation); + + /* Fall out if no indexes (but relhasindex was set) */ + if (indexoidlist == NIL) + return NULL; + + /* + * For each index, add referenced attributes to indexattrs. + */ + indexattrs = NULL; + foreach(l, indexoidlist) + { + Oid indexOid = lfirst_oid(l); + Relation indexDesc; + IndexInfo *indexInfo; + int i; + + indexDesc = index_open(indexOid, AccessShareLock); + + /* Extract index key information from the index's pg_index row */ + indexInfo = BuildIndexInfo(indexDesc); + + /* Collect simple attribute references */ + for (i = 0; i < indexInfo->ii_NumIndexAttrs; i++) + { + int attrnum = indexInfo->ii_KeyAttrNumbers[i]; + + if (attrnum != 0) + indexattrs = bms_add_member(indexattrs, + attrnum - FirstLowInvalidHeapAttributeNumber); + } + + /* Collect all attributes used in expressions, too */ + pull_varattnos((Node *) indexInfo->ii_Expressions, &indexattrs); + + /* Collect all attributes in the index predicate, too */ + pull_varattnos((Node *) indexInfo->ii_Predicate, &indexattrs); + + index_close(indexDesc, AccessShareLock); + } + + list_free(indexoidlist); + + /* Now save a copy of the bitmap in the relcache entry. */ + oldcxt = MemoryContextSwitchTo(CacheMemoryContext); + relation->rd_indexattr = bms_copy(indexattrs); + MemoryContextSwitchTo(oldcxt); + + /* We return our original working copy for caller to play with */ + return indexattrs; +} + /* * load_relcache_init_file, write_relcache_init_file @@ -3465,6 +3558,7 @@ load_relcache_init_file(void) rel->rd_refcnt = 0; rel->rd_indexvalid = 0; rel->rd_indexlist = NIL; + rel->rd_indexattr = NULL; rel->rd_oidindex = InvalidOid; rel->rd_createSubid = InvalidSubTransactionId; rel->rd_newRelfilenodeSubid = InvalidSubTransactionId; |