Commit ddeab225 authored by Tom Lane's avatar Tom Lane

Clean up syscache so that recursive invocation is safe, and remove error

message about recursive use of a syscache.  Also remove most of the
specialized indexscan routines in indexing.c --- it turns out that
catcache.c is perfectly able to perform the indexscan for itself,
in fact has already looked up all the information needed to do so!
This should be faster as well as needing far less boilerplate code.
parent 700032ad
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.81 2000/11/08 22:09:55 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/access/transam/xact.c,v 1.82 2000/11/10 00:33:08 tgl Exp $
*
* NOTES
* Transaction aborts can now occur two ways:
......@@ -863,7 +863,6 @@ static void
AtAbort_Cache(void)
{
RelationCacheAbort();
SystemCacheAbort();
RegisterInvalid(false);
}
......
This diff is collapsed.
This diff is collapsed.
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.115 2000/11/08 22:10:01 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.116 2000/11/10 00:33:10 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -27,15 +27,14 @@
* careful....
*
*/
#include "postgres.h"
#include <sys/types.h>
#include <errno.h>
#include <sys/file.h>
#include <fcntl.h>
#include <unistd.h>
#include "postgres.h"
#include "utils/builtins.h"
#include "access/genam.h"
#include "access/heapam.h"
#include "access/istrat.h"
......@@ -55,6 +54,7 @@
#include "lib/hasht.h"
#include "miscadmin.h"
#include "storage/smgr.h"
#include "utils/builtins.h"
#include "utils/catcache.h"
#include "utils/fmgroids.h"
#include "utils/memutils.h"
......@@ -1127,7 +1127,9 @@ IndexedAccessMethodInitialize(Relation relation)
* This is a special cut-down version of RelationBuildDesc()
* used by RelationCacheInitialize() in initializing the relcache.
* The relation descriptor is built just from the supplied parameters,
* without actually looking at any system table entries.
* without actually looking at any system table entries. We cheat
* quite a lot since we only need to work for a few basic system
* catalogs...
*
* NOTE: we assume we are already switched into CacheMemoryContext.
* --------------------------------
......@@ -1219,7 +1221,7 @@ formrdesc(char *relationName,
RelationGetRelid(relation) = relation->rd_att->attrs[0]->attrelid;
/* ----------------
* initialize the relation lock manager information
* initialize the relation's lock manager and RelFileNode information
* ----------------
*/
RelationInitLockInfo(relation); /* see lmgr.c */
......@@ -1232,22 +1234,29 @@ formrdesc(char *relationName,
relation->rd_rel->relfilenode = RelationGetRelid(relation);
/* ----------------
* add new reldesc to relcache
* initialize the rel-has-index flag, using hardwired knowledge
* ----------------
*/
RelationCacheInsert(relation);
relation->rd_rel->relhasindex = false;
/*
* Determining this requires a scan on pg_class, but to do the scan
* the rdesc for pg_class must already exist. Therefore we must do
* the check (and possible set) after cache insertion.
*
* XXX I believe the above comment is misguided; we should be running
* in bootstrap or init processing mode here, and CatalogHasIndex
* relies on hard-wired info in those cases.
/* In bootstrap mode, we have no indexes */
if (!IsBootstrapProcessingMode())
{
for (i = 0; IndexedCatalogNames[i] != NULL; i++)
{
if (strcmp(IndexedCatalogNames[i], relationName) == 0)
{
relation->rd_rel->relhasindex = true;
break;
}
}
}
/* ----------------
* add new reldesc to relcache
* ----------------
*/
relation->rd_rel->relhasindex =
CatalogHasIndex(relationName, RelationGetRelid(relation));
RelationCacheInsert(relation);
}
......
......@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
* $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.55 2000/06/20 01:41:22 tgl Exp $
* $Header: /cvsroot/pgsql/src/backend/utils/cache/syscache.c,v 1.56 2000/11/10 00:33:10 tgl Exp $
*
* NOTES
* These routines allow the parser/planner/executor to perform
......@@ -55,19 +55,16 @@
Add your entry to the cacheinfo[] array below. All cache lists are
alphabetical, so add it in the proper place. Specify the relation
name, number of arguments, argument attribute numbers, index name,
and index lookup function.
name, index name, number of keys, and key attribute numbers.
In include/catalog/indexing.h, add a define for the number of indexes
on the relation, add define(s) for the index name(s), add an extern
array to hold the index names, define the index lookup function
prototype, and use DECLARE_UNIQUE_INDEX to define the index. Cache
lookups return only one row, so the index should be unique.
array to hold the index names, and use DECLARE_UNIQUE_INDEX to define
the index. Cache lookups return only one row, so the index should be
unique in most cases.
In backend/catalog/indexing.c, initialize the relation array with
the index names for the relation, and create the index lookup function.
Pick one that has similar arguments and copy that one, but keep the
function names in the same order as the cache list for clarity.
the index names for the relation.
Finally, any place your relation gets heap_insert() or
heap_update calls, include code to do a CatalogIndexInsert() to update
......@@ -85,293 +82,264 @@
struct cachedesc
{
char *name; /* name of the relation being cached */
char *indname; /* name of index relation for this cache */
int nkeys; /* # of keys needed for cache lookup */
int key[4]; /* attribute numbers of key attrs */
char *indname; /* name of index relation for this cache */
ScanFunc iScanFunc; /* function to handle index scans */
};
static struct cachedesc cacheinfo[] = {
{AggregateRelationName, /* AGGNAME */
AggregateNameTypeIndex,
2,
{
Anum_pg_aggregate_aggname,
Anum_pg_aggregate_aggbasetype,
0,
0
},
AggregateNameTypeIndex,
(ScanFunc) AggregateNameTypeIndexScan},
}},
{AccessMethodRelationName, /* AMNAME */
AmNameIndex,
1,
{
Anum_pg_am_amname,
0,
0,
0
},
AmNameIndex,
(ScanFunc) AmNameIndexScan},
}},
{AccessMethodOperatorRelationName, /* AMOPOPID */
AccessMethodOpidIndex,
3,
{
Anum_pg_amop_amopclaid,
Anum_pg_amop_amopopr,
Anum_pg_amop_amopid,
0
},
AccessMethodOpidIndex,
(ScanFunc) AccessMethodOpidIndexScan},
}},
{AccessMethodOperatorRelationName, /* AMOPSTRATEGY */
AccessMethodStrategyIndex,
3,
{
Anum_pg_amop_amopid,
Anum_pg_amop_amopclaid,
Anum_pg_amop_amopstrategy,
0
},
AccessMethodStrategyIndex,
(ScanFunc) AccessMethodStrategyIndexScan},
}},
{AttributeRelationName, /* ATTNAME */
AttributeRelidNameIndex,
2,
{
Anum_pg_attribute_attrelid,
Anum_pg_attribute_attname,
0,
0
},
AttributeRelidNameIndex,
(ScanFunc) AttributeRelidNameIndexScan},
}},
{AttributeRelationName, /* ATTNUM */
AttributeRelidNumIndex,
2,
{
Anum_pg_attribute_attrelid,
Anum_pg_attribute_attnum,
0,
0
},
AttributeRelidNumIndex,
(ScanFunc) AttributeRelidNumIndexScan},
}},
{OperatorClassRelationName, /* CLADEFTYPE */
OpclassDeftypeIndex,
1,
{
Anum_pg_opclass_opcdeftype,
0,
0,
0
},
OpclassDeftypeIndex,
(ScanFunc) OpclassDeftypeIndexScan},
}},
{OperatorClassRelationName, /* CLANAME */
OpclassNameIndex,
1,
{
Anum_pg_opclass_opcname,
0,
0,
0
},
OpclassNameIndex,
(ScanFunc) OpclassNameIndexScan},
}},
{GroupRelationName, /* GRONAME */
GroupNameIndex,
1,
{
Anum_pg_group_groname,
0,
0,
0
},
GroupNameIndex,
(ScanFunc) GroupNameIndexScan},
}},
{GroupRelationName, /* GROSYSID */
GroupSysidIndex,
1,
{
Anum_pg_group_grosysid,
0,
0,
0
},
GroupSysidIndex,
(ScanFunc) GroupSysidIndexScan},
}},
{IndexRelationName, /* INDEXRELID */
IndexRelidIndex,
1,
{
Anum_pg_index_indexrelid,
0,
0,
0
},
IndexRelidIndex,
(ScanFunc) IndexRelidIndexScan},
}},
{InheritsRelationName, /* INHRELID */
InheritsRelidSeqnoIndex,
2,
{
Anum_pg_inherits_inhrelid,
Anum_pg_inherits_inhseqno,
0,
0
},
InheritsRelidSeqnoIndex,
(ScanFunc) InheritsRelidSeqnoIndexScan},
}},
{LanguageRelationName, /* LANGNAME */
LanguageNameIndex,
1,
{
Anum_pg_language_lanname,
0,
0,
0
},
LanguageNameIndex,
(ScanFunc) LanguageNameIndexScan},
}},
{LanguageRelationName, /* LANGOID */
LanguageOidIndex,
1,
{
ObjectIdAttributeNumber,
0,
0,
0
},
LanguageOidIndex,
(ScanFunc) LanguageOidIndexScan},
}},
{ListenerRelationName, /* LISTENREL */
ListenerPidRelnameIndex,
2,
{
Anum_pg_listener_pid,
Anum_pg_listener_relname,
0,
0
},
ListenerPidRelnameIndex,
(ScanFunc) ListenerPidRelnameIndexScan},
}},
{OperatorRelationName, /* OPERNAME */
OperatorNameIndex,
4,
{
Anum_pg_operator_oprname,
Anum_pg_operator_oprleft,
Anum_pg_operator_oprright,
Anum_pg_operator_oprkind
},
OperatorNameIndex,
(ScanFunc) OperatorNameIndexScan},
}},
{OperatorRelationName, /* OPEROID */
OperatorOidIndex,
1,
{
ObjectIdAttributeNumber,
0,
0,
0
},
OperatorOidIndex,
(ScanFunc) OperatorOidIndexScan},
}},
{ProcedureRelationName, /* PROCNAME */
ProcedureNameIndex,
3,
{
Anum_pg_proc_proname,
Anum_pg_proc_pronargs,
Anum_pg_proc_proargtypes,
0
},
ProcedureNameIndex,
(ScanFunc) ProcedureNameIndexScan},
}},
{ProcedureRelationName, /* PROCOID */
ProcedureOidIndex,
1,
{
ObjectIdAttributeNumber,
0,
0,
0
},
ProcedureOidIndex,
(ScanFunc) ProcedureOidIndexScan},
}},
{RelationRelationName, /* RELNAME */
ClassNameIndex,
1,
{
Anum_pg_class_relname,
0,
0,
0
},
ClassNameIndex,
(ScanFunc) ClassNameIndexScan},
}},
{RelationRelationName, /* RELOID */
ClassOidIndex,
1,
{
ObjectIdAttributeNumber,
0,
0,
0
},
ClassOidIndex,
(ScanFunc) ClassOidIndexScan},
}},
{RewriteRelationName, /* REWRITENAME */
RewriteRulenameIndex,
1,
{
Anum_pg_rewrite_rulename,
0,
0,
0
},
RewriteRulenameIndex,
(ScanFunc) RewriteRulenameIndexScan},
}},
{RewriteRelationName, /* RULEOID */
RewriteOidIndex,
1,
{
ObjectIdAttributeNumber,
0,
0,
0
},
RewriteOidIndex,
(ScanFunc) RewriteOidIndexScan},
}},
{ShadowRelationName, /* SHADOWNAME */
ShadowNameIndex,
1,
{
Anum_pg_shadow_usename,
0,
0,
0
},
ShadowNameIndex,
(ScanFunc) ShadowNameIndexScan},
}},
{ShadowRelationName, /* SHADOWSYSID */
ShadowSysidIndex,
1,
{
Anum_pg_shadow_usesysid,
0,
0,
0
},
ShadowSysidIndex,
(ScanFunc) ShadowSysidIndexScan},
}},
{StatisticRelationName, /* STATRELID */
StatisticRelidAttnumIndex,
2,
{
Anum_pg_statistic_starelid,
Anum_pg_statistic_staattnum,
0,
0
},
StatisticRelidAttnumIndex,
(ScanFunc) StatisticRelidAttnumIndexScan},
}},
{TypeRelationName, /* TYPENAME */
TypeNameIndex,
1,
{
Anum_pg_type_typname,
0,
0,
0
},
TypeNameIndex,
(ScanFunc) TypeNameIndexScan},
}},
{TypeRelationName, /* TYPEOID */
TypeOidIndex,
1,
{
ObjectIdAttributeNumber,
0,
0,
0
},
TypeOidIndex,
(ScanFunc) TypeOidIndexScan}
}}
};
static CatCache *SysCache[lengthof(cacheinfo)];
......@@ -412,12 +380,11 @@ InitCatalogCache()
{
Assert(!PointerIsValid(SysCache[cacheId]));
SysCache[cacheId] = InitSysCache(cacheinfo[cacheId].name,
SysCache[cacheId] = InitSysCache(cacheId,
cacheinfo[cacheId].name,
cacheinfo[cacheId].indname,
cacheId,
cacheinfo[cacheId].nkeys,
cacheinfo[cacheId].key,
cacheinfo[cacheId].iScanFunc);
cacheinfo[cacheId].key);
if (!PointerIsValid(SysCache[cacheId]))
{
elog(ERROR,
......@@ -469,12 +436,11 @@ SearchSysCacheTuple(int cacheId,/* cache selection code */
if (!PointerIsValid(SysCache[cacheId]))
{
SysCache[cacheId] = InitSysCache(cacheinfo[cacheId].name,
SysCache[cacheId] = InitSysCache(cacheId,
cacheinfo[cacheId].name,
cacheinfo[cacheId].indname,
cacheId,
cacheinfo[cacheId].nkeys,
cacheinfo[cacheId].key,
cacheinfo[cacheId].iScanFunc);
cacheinfo[cacheId].key);
if (!PointerIsValid(SysCache[cacheId]))
elog(ERROR,
"InitCatalogCache: Can't init cache %s(%d)",
......@@ -569,7 +535,6 @@ SysCacheGetAttr(int cacheId, HeapTuple tup,
if (cacheId < 0 || cacheId >= SysCacheSize)
elog(ERROR, "SysCacheGetAttr: Bad cache id %d", cacheId);
if (!PointerIsValid(SysCache[cacheId]) ||
SysCache[cacheId]->relationId == InvalidOid ||
!PointerIsValid(SysCache[cacheId]->cc_tupdesc))
elog(ERROR, "SysCacheGetAttr: missing cache data for id %d", cacheId);
......
/*-------------------------------------------------------------------------
*
* indexing.h
* This include provides some definitions to support indexing
* This file provides some definitions to support indexing
* on system catalogs
*
*
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: indexing.h,v 1.45 2000/10/24 01:38:41 tgl Exp $
* $Id: indexing.h,v 1.46 2000/11/10 00:33:11 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -116,55 +116,15 @@ extern void CatalogOpenIndices(int nIndices, char **names, Relation *idescs);
extern void CatalogCloseIndices(int nIndices, Relation *idescs);
extern void CatalogIndexInsert(Relation *idescs, int nIndices,
Relation heapRelation, HeapTuple heapTuple);
extern bool CatalogHasIndex(char *catName, Oid catId);
/*
* Functions for each index to perform the necessary scan on a cache miss.
* Canned functions for indexscans on certain system indexes.
* All index-value arguments should be passed as Datum for portability!
*/
extern HeapTuple AccessMethodOpidIndexScan(Relation heapRelation,
Datum claid, Datum opopr, Datum opid);
extern HeapTuple AccessMethodStrategyIndexScan(Relation heapRelation,
Datum opid, Datum claid, Datum opstrategy);
extern HeapTuple AggregateNameTypeIndexScan(Relation heapRelation,
Datum aggName, Datum aggType);
extern HeapTuple AmNameIndexScan(Relation heapRelation, Datum amName);
extern HeapTuple AttributeRelidNameIndexScan(Relation heapRelation,
Datum relid, Datum attname);
extern HeapTuple AttributeRelidNumIndexScan(Relation heapRelation,
Datum relid, Datum attnum);
extern HeapTuple ClassNameIndexScan(Relation heapRelation, Datum relName);
Datum relid, Datum attnum);
extern HeapTuple ClassNameIndexScan(Relation heapRelation, Datum relName);
extern HeapTuple ClassOidIndexScan(Relation heapRelation, Datum relId);
extern HeapTuple GroupNameIndexScan(Relation heapRelation, Datum groName);
extern HeapTuple GroupSysidIndexScan(Relation heapRelation, Datum sysId);
extern HeapTuple IndexRelidIndexScan(Relation heapRelation, Datum relid);
extern HeapTuple InheritsRelidSeqnoIndexScan(Relation heapRelation,
Datum relid, Datum seqno);
extern HeapTuple LanguageNameIndexScan(Relation heapRelation, Datum lanName);
extern HeapTuple LanguageOidIndexScan(Relation heapRelation, Datum lanId);
extern HeapTuple ListenerPidRelnameIndexScan(Relation heapRelation,
Datum pid, Datum relName);
extern HeapTuple OpclassDeftypeIndexScan(Relation heapRelation, Datum defType);
extern HeapTuple OpclassNameIndexScan(Relation heapRelation, Datum opcName);
extern HeapTuple OperatorNameIndexScan(Relation heapRelation,
Datum oprName, Datum oprLeft,
Datum oprRight, Datum oprKind);
extern HeapTuple OperatorOidIndexScan(Relation heapRelation, Datum oprId);
extern HeapTuple ProcedureNameIndexScan(Relation heapRelation,
Datum procName, Datum nargs, Datum argTypes);
extern HeapTuple ProcedureOidIndexScan(Relation heapRelation, Datum procId);
extern HeapTuple RewriteOidIndexScan(Relation heapRelation, Datum rewriteId);
extern HeapTuple RewriteRulenameIndexScan(Relation heapRelation,
Datum ruleName);
extern HeapTuple ShadowNameIndexScan(Relation heapRelation, Datum useName);
extern HeapTuple ShadowSysidIndexScan(Relation heapRelation, Datum sysId);
extern HeapTuple StatisticRelidAttnumIndexScan(Relation heapRelation,
Datum relId, Datum attNum);
extern HeapTuple TypeNameIndexScan(Relation heapRelation, Datum typeName);
extern HeapTuple TypeOidIndexScan(Relation heapRelation, Datum typeId);
/*
......
......@@ -3,11 +3,17 @@
* catcache.h
* Low-level catalog cache definitions.
*
* NOTE: every catalog cache must have a corresponding unique index on
* the system table that it caches --- ie, the index must match the keys
* used to do lookups in this cache. All cache fetches are done with
* indexscans (under normal conditions). The index should be unique to
* guarantee that there can only be one matching row for a key combination.
*
*
* Portions Copyright (c) 1996-2000, PostgreSQL, Inc
* Portions Copyright (c) 1994, Regents of the University of California
*
* $Id: catcache.h,v 1.26 2000/08/06 04:16:40 tgl Exp $
* $Id: catcache.h,v 1.27 2000/11/10 00:33:12 tgl Exp $
*
*-------------------------------------------------------------------------
*/
......@@ -20,18 +26,7 @@
#include "lib/dllist.h"
/*
* Functions that implement index scans for caches must match this signature
* (except we allow unused key arguments to be omitted --- is that really
* portable?)
*/
typedef HeapTuple (*ScanFunc) (Relation heapRelation,
Datum key1,
Datum key2,
Datum key3,
Datum key4);
/*
* struct catctup: tuples in the cache.
* struct catctup: individual tuple in the cache.
* struct catcache: information for managing a cache.
*/
......@@ -53,22 +48,18 @@ typedef struct catctup
typedef struct catcache
{
Oid relationId;
Oid indexId;
char *cc_relname; /* relation name for defered open */
char *cc_indname; /* index name for defered open */
ScanFunc cc_iscanfunc; /* index scan function */
TupleDesc cc_tupdesc; /* tuple descriptor from reldesc */
int id; /* XXX could be improved -hirohama */
bool busy; /* for detecting recursive lookups */
short cc_ntup; /* # of tuples in this cache */
int id; /* cache identifier --- see syscache.h */
struct catcache *cc_next; /* link to next catcache */
char *cc_relname; /* name of relation the tuples come from */
char *cc_indname; /* name of index matching cache keys */
TupleDesc cc_tupdesc; /* tuple descriptor (copied from reldesc) */
short cc_ntup; /* # of tuples in this cache */
short cc_maxtup; /* max # of tuples allowed (LRU) */
short cc_nkeys;
short cc_size;
short cc_size; /* # of hash buckets in this cache */
short cc_nkeys; /* number of keys (1..4) */
short cc_key[4]; /* AttrNumber of each key */
PGFunction cc_hashfunc[4]; /* hash function to use for each key */
ScanKeyData cc_skey[4];
struct catcache *cc_next;
ScanKeyData cc_skey[4]; /* precomputed key info for indexscans */
Dllist *cc_lrulist; /* LRU list, most recent first */
Dllist *cc_cache[NCCBUCK + 1]; /* hash buckets */
} CatCache;
......@@ -79,17 +70,17 @@ typedef struct catcache
extern MemoryContext CacheMemoryContext;
extern void CreateCacheMemoryContext(void);
extern void CatalogCacheIdInvalidate(int cacheId, Index hashIndex,
ItemPointer pointer);
extern void ResetSystemCache(void);
extern void SystemCacheRelationFlushed(Oid relId);
extern void SystemCacheAbort(void);
extern CatCache *InitSysCache(char *relname, char *indname, int id,
int nkeys, int *key,
ScanFunc iScanfuncP);
extern HeapTuple SearchSysCache(CatCache * cache,
extern CatCache *InitSysCache(int id, char *relname, char *indname,
int nkeys, int *key);
extern HeapTuple SearchSysCache(CatCache *cache,
Datum v1, Datum v2,
Datum v3, Datum v4);
extern void ResetSystemCache(void);
extern void SystemCacheRelationFlushed(Oid relId);
extern void CatalogCacheIdInvalidate(int cacheId, Index hashIndex,
ItemPointer pointer);
extern void RelationInvalidateCatalogCacheTuple(Relation relation,
HeapTuple tuple,
void (*function) (int, Index, ItemPointer));
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment