aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/cache/relcache.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/cache/relcache.c')
-rw-r--r--src/backend/utils/cache/relcache.c232
1 files changed, 113 insertions, 119 deletions
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c
index d10569fd7ce..4894cd27795 100644
--- a/src/backend/utils/cache/relcache.c
+++ b/src/backend/utils/cache/relcache.c
@@ -8,7 +8,7 @@
*
*
* IDENTIFICATION
- * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.157 2002/03/19 02:18:22 momjian Exp $
+ * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.158 2002/03/26 19:16:10 tgl Exp $
*
*-------------------------------------------------------------------------
*/
@@ -16,10 +16,9 @@
* INTERFACE ROUTINES
* RelationCacheInitialize - initialize relcache
* RelationCacheInitializePhase2 - finish initializing relcache
- * RelationIdCacheGetRelation - get a reldesc from the cache (id)
- * RelationNameCacheGetRelation - get a reldesc from the cache (name)
* RelationIdGetRelation - get a reldesc by relation id
- * RelationNameGetRelation - get a reldesc by relation name
+ * RelationSysNameGetRelation - get a reldesc by system rel name
+ * RelationIdCacheGetRelation - get a cached reldesc by relid
* RelationClose - close an open relation
*
* NOTES
@@ -39,13 +38,13 @@
#include "access/istrat.h"
#include "catalog/catalog.h"
#include "catalog/catname.h"
-#include "catalog/index.h"
#include "catalog/indexing.h"
#include "catalog/pg_amop.h"
#include "catalog/pg_amproc.h"
#include "catalog/pg_attrdef.h"
#include "catalog/pg_attribute.h"
#include "catalog/pg_index.h"
+#include "catalog/pg_namespace.h"
#include "catalog/pg_opclass.h"
#include "catalog/pg_proc.h"
#include "catalog/pg_relcheck.h"
@@ -70,7 +69,7 @@
#define RELCACHE_INIT_FILENAME "pg_internal.init"
/*
- * hardcoded tuple descriptors. see lib/backend/catalog/pg_attribute.h
+ * hardcoded tuple descriptors. see include/catalog/pg_attribute.h
*/
static FormData_pg_attribute Desc_pg_class[Natts_pg_class] = {Schema_pg_class};
static FormData_pg_attribute Desc_pg_attribute[Natts_pg_attribute] = {Schema_pg_attribute};
@@ -80,11 +79,14 @@ static FormData_pg_attribute Desc_pg_type[Natts_pg_type] = {Schema_pg_type};
/*
* Hash tables that index the relation cache
*
- * Relations are looked up two ways, by name and by id,
+ * Relations are looked up two ways, by OID and by name,
* thus there are two hash tables for referencing them.
+ *
+ * The OID index covers all relcache entries. The name index
+ * covers *only* system relations (only those in PG_CATALOG_NAMESPACE).
*/
-static HTAB *RelationNameCache;
static HTAB *RelationIdCache;
+static HTAB *RelationSysNameCache;
/*
* Bufmgr uses RelFileNode for lookup. Actually, I would like to do
@@ -128,7 +130,7 @@ static List *initFileRelationIds = NIL;
/*
* RelationBuildDescInfo exists so code can be shared
- * between RelationIdGetRelation() and RelationNameGetRelation()
+ * between RelationIdGetRelation() and RelationSysNameGetRelation()
*/
typedef struct RelationBuildDescInfo
{
@@ -138,22 +140,22 @@ typedef struct RelationBuildDescInfo
union
{
Oid info_id; /* relation object id */
- char *info_name; /* relation name */
+ char *info_name; /* system relation name */
} i;
} RelationBuildDescInfo;
-typedef struct relnamecacheent
-{
- NameData relname;
- Relation reldesc;
-} RelNameCacheEnt;
-
typedef struct relidcacheent
{
Oid reloid;
Relation reldesc;
} RelIdCacheEnt;
+typedef struct relnamecacheent
+{
+ NameData relname;
+ Relation reldesc;
+} RelNameCacheEnt;
+
typedef struct relnodecacheent
{
RelFileNode relnode;
@@ -165,24 +167,14 @@ typedef struct relnodecacheent
*/
#define RelationCacheInsert(RELATION) \
do { \
- RelIdCacheEnt *idhentry; RelNameCacheEnt *namehentry; \
- char *relname; RelNodeCacheEnt *nodentry; bool found; \
- relname = RelationGetPhysicalRelationName(RELATION); \
- namehentry = (RelNameCacheEnt*)hash_search(RelationNameCache, \
- relname, \
- HASH_ENTER, \
- &found); \
- if (namehentry == NULL) \
- elog(ERROR, "out of memory for relation descriptor cache"); \
- /* used to give notice if found -- now just keep quiet */ ; \
- namehentry->reldesc = RELATION; \
+ RelIdCacheEnt *idhentry; RelNodeCacheEnt *nodentry; bool found; \
idhentry = (RelIdCacheEnt*)hash_search(RelationIdCache, \
(void *) &(RELATION->rd_id), \
HASH_ENTER, \
&found); \
if (idhentry == NULL) \
elog(ERROR, "out of memory for relation descriptor cache"); \
- /* used to give notice if found -- now just keep quiet */ ; \
+ /* used to give notice if found -- now just keep quiet */ \
idhentry->reldesc = RELATION; \
nodentry = (RelNodeCacheEnt*)hash_search(RelationNodeCache, \
(void *) &(RELATION->rd_node), \
@@ -190,26 +182,39 @@ do { \
&found); \
if (nodentry == NULL) \
elog(ERROR, "out of memory for relation descriptor cache"); \
- /* used to give notice if found -- now just keep quiet */ ; \
+ /* used to give notice if found -- now just keep quiet */ \
nodentry->reldesc = RELATION; \
+ if (RelationGetNamespace(RELATION) == PG_CATALOG_NAMESPACE) \
+ { \
+ char *relname = RelationGetPhysicalRelationName(RELATION); \
+ RelNameCacheEnt *namehentry; \
+ namehentry = (RelNameCacheEnt*)hash_search(RelationSysNameCache, \
+ relname, \
+ HASH_ENTER, \
+ &found); \
+ if (namehentry == NULL) \
+ elog(ERROR, "out of memory for relation descriptor cache"); \
+ /* used to give notice if found -- now just keep quiet */ \
+ namehentry->reldesc = RELATION; \
+ } \
} while(0)
-#define RelationNameCacheLookup(NAME, RELATION) \
+#define RelationIdCacheLookup(ID, RELATION) \
do { \
- RelNameCacheEnt *hentry; \
- hentry = (RelNameCacheEnt*)hash_search(RelationNameCache, \
- (void *) (NAME), HASH_FIND,NULL); \
+ RelIdCacheEnt *hentry; \
+ hentry = (RelIdCacheEnt*)hash_search(RelationIdCache, \
+ (void *)&(ID), HASH_FIND,NULL); \
if (hentry) \
RELATION = hentry->reldesc; \
else \
RELATION = NULL; \
} while(0)
-#define RelationIdCacheLookup(ID, RELATION) \
+#define RelationSysNameCacheLookup(NAME, RELATION) \
do { \
- RelIdCacheEnt *hentry; \
- hentry = (RelIdCacheEnt*)hash_search(RelationIdCache, \
- (void *)&(ID), HASH_FIND,NULL); \
+ RelNameCacheEnt *hentry; \
+ hentry = (RelNameCacheEnt*)hash_search(RelationSysNameCache, \
+ (void *) (NAME), HASH_FIND,NULL); \
if (hentry) \
RELATION = hentry->reldesc; \
else \
@@ -229,14 +234,7 @@ do { \
#define RelationCacheDelete(RELATION) \
do { \
- RelNameCacheEnt *namehentry; RelIdCacheEnt *idhentry; \
- char *relname; RelNodeCacheEnt *nodentry; \
- relname = RelationGetPhysicalRelationName(RELATION); \
- namehentry = (RelNameCacheEnt*)hash_search(RelationNameCache, \
- relname, \
- HASH_REMOVE, NULL); \
- if (namehentry == NULL) \
- elog(WARNING, "trying to delete a reldesc that does not exist."); \
+ RelIdCacheEnt *idhentry; RelNodeCacheEnt *nodentry; \
idhentry = (RelIdCacheEnt*)hash_search(RelationIdCache, \
(void *)&(RELATION->rd_id), \
HASH_REMOVE, NULL); \
@@ -247,6 +245,16 @@ do { \
HASH_REMOVE, NULL); \
if (nodentry == NULL) \
elog(WARNING, "trying to delete a reldesc that does not exist."); \
+ if (RelationGetNamespace(RELATION) == PG_CATALOG_NAMESPACE) \
+ { \
+ char *relname = RelationGetPhysicalRelationName(RELATION); \
+ RelNameCacheEnt *namehentry; \
+ namehentry = (RelNameCacheEnt*)hash_search(RelationSysNameCache, \
+ relname, \
+ HASH_REMOVE, NULL); \
+ if (namehentry == NULL) \
+ elog(WARNING, "trying to delete a reldesc that does not exist."); \
+ } \
} while(0)
@@ -275,11 +283,11 @@ static void RelationClearRelation(Relation relation, bool rebuildIt);
static void RelationReloadClassinfo(Relation relation);
#endif /* ENABLE_REINDEX_NAILED_RELATIONS */
static void RelationFlushRelation(Relation relation);
-static Relation RelationNameCacheGetRelation(const char *relationName);
+static Relation RelationSysNameCacheGetRelation(const char *relationName);
static bool load_relcache_init_file(void);
static void write_relcache_init_file(void);
-static void formrdesc(char *relationName, int natts,
+static void formrdesc(const char *relationName, int natts,
FormData_pg_attribute *att);
static HeapTuple ScanPgRelation(RelationBuildDescInfo buildinfo);
@@ -304,12 +312,6 @@ static OpClassCacheEnt *LookupOpclassInfo(Oid operatorClassOid,
/*
- * RelationIdGetRelation() and RelationNameGetRelation()
- * support functions
- */
-
-
-/*
* ScanPgRelation
*
* this is used by RelationBuildDesc to find a pg_class
@@ -326,7 +328,8 @@ ScanPgRelation(RelationBuildDescInfo buildinfo)
Relation pg_class_desc;
const char *indexRelname;
SysScanDesc pg_class_scan;
- ScanKeyData key;
+ ScanKeyData key[2];
+ int nkeys;
/*
* form a scan key
@@ -334,19 +337,25 @@ ScanPgRelation(RelationBuildDescInfo buildinfo)
switch (buildinfo.infotype)
{
case INFO_RELID:
- ScanKeyEntryInitialize(&key, 0,
+ ScanKeyEntryInitialize(&key[0], 0,
ObjectIdAttributeNumber,
F_OIDEQ,
ObjectIdGetDatum(buildinfo.i.info_id));
+ nkeys = 1;
indexRelname = ClassOidIndex;
break;
case INFO_RELNAME:
- ScanKeyEntryInitialize(&key, 0,
+ ScanKeyEntryInitialize(&key[0], 0,
Anum_pg_class_relname,
F_NAMEEQ,
NameGetDatum(buildinfo.i.info_name));
- indexRelname = ClassNameIndex;
+ ScanKeyEntryInitialize(&key[1], 0,
+ Anum_pg_class_relnamespace,
+ F_OIDEQ,
+ ObjectIdGetDatum(PG_CATALOG_NAMESPACE));
+ nkeys = 2;
+ indexRelname = ClassNameNspIndex;
break;
default:
@@ -363,7 +372,7 @@ ScanPgRelation(RelationBuildDescInfo buildinfo)
pg_class_scan = systable_beginscan(pg_class_desc, indexRelname,
criticalRelcachesBuilt,
SnapshotNow,
- 1, &key);
+ nkeys, key);
pg_class_tuple = systable_getnext(pg_class_scan);
@@ -512,12 +521,8 @@ RelationBuildTupleDesc(RelationBuildDescInfo buildinfo,
(char *) attp,
ATTRIBUTE_TUPLE_SIZE);
-
-
- /*
- * Update constraint/default info
- */
- if (attp->attnotnull)
+ /* Update constraint/default info */
+ if (attp->attnotnull)
constr->has_not_null = true;
if (attp->atthasdef)
@@ -1333,7 +1338,7 @@ LookupOpclassInfo(Oid operatorClassOid,
* NOTE: we assume we are already switched into CacheMemoryContext.
*/
static void
-formrdesc(char *relationName,
+formrdesc(const char *relationName,
int natts,
FormData_pg_attribute *att)
{
@@ -1374,7 +1379,8 @@ formrdesc(char *relationName,
relation->rd_rel = (Form_pg_class) palloc(CLASS_TUPLE_SIZE);
MemSet(relation->rd_rel, 0, CLASS_TUPLE_SIZE);
- strcpy(RelationGetPhysicalRelationName(relation), relationName);
+ namestrcpy(&relation->rd_rel->relname, relationName);
+ relation->rd_rel->relnamespace = PG_CATALOG_NAMESPACE;
/*
* It's important to distinguish between shared and non-shared
@@ -1488,12 +1494,12 @@ RelationIdCacheGetRelation(Oid relationId)
}
/*
- * RelationNameCacheGetRelation
+ * RelationSysNameCacheGetRelation
*
- * As above, but lookup by name.
+ * As above, but lookup by name; only works for system catalogs.
*/
static Relation
-RelationNameCacheGetRelation(const char *relationName)
+RelationSysNameCacheGetRelation(const char *relationName)
{
Relation rd;
NameData name;
@@ -1503,7 +1509,7 @@ RelationNameCacheGetRelation(const char *relationName)
* null-padded
*/
namestrcpy(&name, relationName);
- RelationNameCacheLookup(NameStr(name), rd);
+ RelationSysNameCacheLookup(NameStr(name), rd);
if (RelationIsValid(rd))
RelationIncrementReferenceCount(rd);
@@ -1540,12 +1546,6 @@ RelationIdGetRelation(Oid relationId)
RelationBuildDescInfo buildinfo;
/*
- * increment access statistics
- */
- IncrHeapAccessStat(local_RelationIdGetRelation);
- IncrHeapAccessStat(global_RelationIdGetRelation);
-
- /*
* first try and get a reldesc from the cache
*/
rd = RelationIdCacheGetRelation(relationId);
@@ -1564,24 +1564,18 @@ RelationIdGetRelation(Oid relationId)
}
/*
- * RelationNameGetRelation
+ * RelationSysNameGetRelation
*
- * As above, but lookup by name.
+ * As above, but lookup by name; only works for system catalogs.
*/
Relation
-RelationNameGetRelation(const char *relationName)
+RelationSysNameGetRelation(const char *relationName)
{
char *temprelname;
Relation rd;
RelationBuildDescInfo buildinfo;
/*
- * increment access statistics
- */
- IncrHeapAccessStat(local_RelationNameGetRelation);
- IncrHeapAccessStat(global_RelationNameGetRelation);
-
- /*
* if caller is looking for a temp relation, substitute its real name;
* we only index temp rels by their real names.
*/
@@ -1592,7 +1586,7 @@ RelationNameGetRelation(const char *relationName)
/*
* first try and get a reldesc from the cache
*/
- rd = RelationNameCacheGetRelation(relationName);
+ rd = RelationSysNameCacheGetRelation(relationName);
if (RelationIsValid(rd))
return rd;
@@ -1951,17 +1945,17 @@ void
RelationCacheInvalidate(void)
{
HASH_SEQ_STATUS status;
- RelNameCacheEnt *namehentry;
+ RelIdCacheEnt *idhentry;
Relation relation;
List *rebuildList = NIL;
List *l;
/* Phase 1 */
- hash_seq_init(&status, RelationNameCache);
+ hash_seq_init(&status, RelationIdCache);
- while ((namehentry = (RelNameCacheEnt *) hash_seq_search(&status)) != NULL)
+ while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
{
- relation = namehentry->reldesc;
+ relation = idhentry->reldesc;
/* Ignore xact-local relations, since they are never SI targets */
if (relation->rd_myxactonly)
@@ -2007,13 +2001,13 @@ void
RelationCacheAbort(void)
{
HASH_SEQ_STATUS status;
- RelNameCacheEnt *namehentry;
+ RelIdCacheEnt *idhentry;
- hash_seq_init(&status, RelationNameCache);
+ hash_seq_init(&status, RelationIdCache);
- while ((namehentry = (RelNameCacheEnt *) hash_seq_search(&status)) != NULL)
+ while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
{
- Relation relation = namehentry->reldesc;
+ Relation relation = idhentry->reldesc;
if (relation->rd_isnailed)
RelationSetReferenceCount(relation, 1);
@@ -2029,8 +2023,10 @@ RelationCacheAbort(void)
*/
Relation
RelationBuildLocalRelation(const char *relname,
+ Oid relnamespace,
TupleDesc tupDesc,
Oid relid, Oid dbid,
+ RelFileNode rnode,
bool nailit)
{
Relation rel;
@@ -2086,7 +2082,8 @@ RelationBuildLocalRelation(const char *relname,
rel->rd_rel = (Form_pg_class) palloc(CLASS_TUPLE_SIZE);
MemSet((char *) rel->rd_rel, 0, CLASS_TUPLE_SIZE);
- strcpy(RelationGetPhysicalRelationName(rel), relname);
+ namestrcpy(&rel->rd_rel->relname, relname);
+ rel->rd_rel->relnamespace = relnamespace;
rel->rd_rel->relkind = RELKIND_UNCATALOGED;
rel->rd_rel->relhasoids = true;
@@ -2094,10 +2091,8 @@ RelationBuildLocalRelation(const char *relname,
rel->rd_rel->reltype = InvalidOid;
/*
- * Insert relation OID and database/tablespace ID into the right
- * places. XXX currently we assume physical tblspace/relnode are same
- * as logical dbid/reloid. Probably should pass an extra pair of
- * parameters.
+ * Insert relation physical and logical identifiers (OIDs) into the
+ * right places.
*/
rel->rd_rel->relisshared = (dbid == InvalidOid);
@@ -2106,11 +2101,10 @@ RelationBuildLocalRelation(const char *relname,
for (i = 0; i < natts; i++)
rel->rd_att->attrs[i]->attrelid = relid;
- RelationInitLockInfo(rel); /* see lmgr.c */
+ rel->rd_node = rnode;
+ rel->rd_rel->relfilenode = rnode.relNode;
- rel->rd_node.tblNode = dbid;
- rel->rd_node.relNode = relid;
- rel->rd_rel->relfilenode = relid;
+ RelationInitLockInfo(rel); /* see lmgr.c */
/*
* Okay to insert into the relcache hash tables.
@@ -2201,8 +2195,8 @@ RelationCacheInitialize(void)
MemSet(&ctl, 0, sizeof(ctl));
ctl.keysize = sizeof(NameData);
ctl.entrysize = sizeof(RelNameCacheEnt);
- RelationNameCache = hash_create("Relcache by name", INITRELCACHESIZE,
- &ctl, HASH_ELEM);
+ RelationSysNameCache = hash_create("Relcache by name", INITRELCACHESIZE,
+ &ctl, HASH_ELEM);
ctl.keysize = sizeof(Oid);
ctl.entrysize = sizeof(RelIdCacheEnt);
@@ -2252,7 +2246,7 @@ void
RelationCacheInitializePhase2(void)
{
HASH_SEQ_STATUS status;
- RelNameCacheEnt *namehentry;
+ RelIdCacheEnt *idhentry;
if (IsBootstrapProcessingMode())
return;
@@ -2290,7 +2284,7 @@ RelationCacheInitializePhase2(void)
RelationSetReferenceCount(ird, 1); \
} while (0)
- LOAD_CRIT_INDEX(ClassNameIndex);
+ LOAD_CRIT_INDEX(ClassNameNspIndex);
LOAD_CRIT_INDEX(ClassOidIndex);
LOAD_CRIT_INDEX(AttributeRelidNumIndex);
LOAD_CRIT_INDEX(IndexRelidIndex);
@@ -2311,11 +2305,11 @@ RelationCacheInitializePhase2(void)
* Also, if any of the relcache entries have rules or triggers,
* load that info the hard way since it isn't recorded in the cache file.
*/
- hash_seq_init(&status, RelationNameCache);
+ hash_seq_init(&status, RelationIdCache);
- while ((namehentry = (RelNameCacheEnt *) hash_seq_search(&status)) != NULL)
+ while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
{
- Relation relation = namehentry->reldesc;
+ Relation relation = idhentry->reldesc;
/*
* If it's a faked-up entry, read the real pg_class tuple.
@@ -2399,8 +2393,8 @@ CreateDummyCaches(void)
MemSet(&ctl, 0, sizeof(ctl));
ctl.keysize = sizeof(NameData);
ctl.entrysize = sizeof(RelNameCacheEnt);
- RelationNameCache = hash_create("Relcache by name", INITRELCACHESIZE,
- &ctl, HASH_ELEM);
+ RelationSysNameCache = hash_create("Relcache by name", INITRELCACHESIZE,
+ &ctl, HASH_ELEM);
ctl.keysize = sizeof(Oid);
ctl.entrysize = sizeof(RelIdCacheEnt);
@@ -2427,14 +2421,14 @@ DestroyDummyCaches(void)
oldcxt = MemoryContextSwitchTo(CacheMemoryContext);
- if (RelationNameCache)
- hash_destroy(RelationNameCache);
if (RelationIdCache)
hash_destroy(RelationIdCache);
+ if (RelationSysNameCache)
+ hash_destroy(RelationSysNameCache);
if (RelationNodeCache)
hash_destroy(RelationNodeCache);
- RelationNameCache = RelationIdCache = RelationNodeCache = NULL;
+ RelationIdCache = RelationSysNameCache = RelationNodeCache = NULL;
MemoryContextSwitchTo(oldcxt);
}
@@ -3001,7 +2995,7 @@ write_relcache_init_file(void)
char tempfilename[MAXPGPATH];
char finalfilename[MAXPGPATH];
HASH_SEQ_STATUS status;
- RelNameCacheEnt *namehentry;
+ RelIdCacheEnt *idhentry;
MemoryContext oldcxt;
int i;
@@ -3031,13 +3025,13 @@ write_relcache_init_file(void)
/*
* Write all the reldescs (in no particular order).
*/
- hash_seq_init(&status, RelationNameCache);
+ hash_seq_init(&status, RelationIdCache);
initFileRelationIds = NIL;
- while ((namehentry = (RelNameCacheEnt *) hash_seq_search(&status)) != NULL)
+ while ((idhentry = (RelIdCacheEnt *) hash_seq_search(&status)) != NULL)
{
- Relation rel = namehentry->reldesc;
+ Relation rel = idhentry->reldesc;
Form_pg_class relform = rel->rd_rel;
Size len;