diff options
author | Bruce Momjian <bruce@momjian.us> | 1997-09-07 05:04:48 +0000 |
---|---|---|
committer | Bruce Momjian <bruce@momjian.us> | 1997-09-07 05:04:48 +0000 |
commit | 1ccd423235a48739d6f7a4d7889705b5f9ecc69b (patch) | |
tree | 8001c4e839dfad8f29ceda7f8c5f5dbb8759b564 /src/backend/utils/cache/relcache.c | |
parent | 8fecd4febf8357f3cc20383ed29ced484877d5ac (diff) | |
download | postgresql-1ccd423235a48739d6f7a4d7889705b5f9ecc69b.tar.gz postgresql-1ccd423235a48739d6f7a4d7889705b5f9ecc69b.zip |
Massive commit to run PGINDENT on all *.c and *.h files.
Diffstat (limited to 'src/backend/utils/cache/relcache.c')
-rw-r--r-- | src/backend/utils/cache/relcache.c | 3493 |
1 files changed, 1791 insertions, 1702 deletions
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index a54f1d81387..704d673279b 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -1,41 +1,41 @@ /*------------------------------------------------------------------------- * * relcache.c-- - * POSTGRES relation descriptor cache code + * POSTGRES relation descriptor cache code * * Copyright (c) 1994, Regents of the University of California * * * IDENTIFICATION - * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.20 1997/09/01 08:04:38 vadim Exp $ + * $Header: /cvsroot/pgsql/src/backend/utils/cache/relcache.c,v 1.21 1997/09/07 04:53:08 momjian Exp $ * *------------------------------------------------------------------------- */ /* * INTERFACE ROUTINES - * RelationInitialize - initialize 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 - * RelationClose - close an open relation - * RelationFlushRelation - flush relation information + * RelationInitialize - initialize 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 + * RelationClose - close an open relation + * RelationFlushRelation - flush relation information * * NOTES - * This file is in the process of being cleaned up - * before I add system attribute indexing. -cim 1/13/91 + * This file is in the process of being cleaned up + * before I add system attribute indexing. -cim 1/13/91 * - * The following code contains many undocumented hacks. Please be - * careful.... + * The following code contains many undocumented hacks. Please be + * careful.... * */ #include <sys/types.h> -#include <stdio.h> /* for sprintf() */ +#include <stdio.h> /* for sprintf() */ #include <errno.h> #include <sys/file.h> #include <fcntl.h> #include <string.h> - + #include "postgres.h" #include "miscadmin.h" @@ -51,21 +51,21 @@ #include "access/tupdesc.h" #include "access/tupmacs.h" #include "access/xact.h" - + #include "storage/buf.h" -#include "storage/fd.h" /* for SEEK_ */ +#include "storage/fd.h" /* for SEEK_ */ #include "storage/lmgr.h" #include "storage/bufmgr.h" - + #include "lib/hasht.h" - + #include "utils/memutils.h" #include "utils/mcxt.h" #include "utils/rel.h" #include "utils/relcache.h" #include "utils/hsearch.h" #include "utils/relcache.h" - + #include "catalog/catname.h" #include "catalog/catalog.h" #include "utils/syscache.h" @@ -87,1744 +87,1813 @@ #include "catalog/index.h" #include "fmgr.h" -static void RelationFlushRelation(Relation *relationPtr, - bool onlyFlushReferenceCountZero); +static void +RelationFlushRelation(Relation * relationPtr, + bool onlyFlushReferenceCountZero); static Relation RelationNameCacheGetRelation(char *relationName); -static void init_irels(void); -static void write_irels(void); +static void init_irels(void); +static void write_irels(void); /* ---------------- - * defines + * defines * ---------------- */ #define private static #define INIT_FILENAME "pg_internal.init" /* ---------------- - * externs + * externs * ---------------- */ -extern bool AMI_OVERRIDE; /* XXX style */ +extern bool AMI_OVERRIDE; /* XXX style */ extern GlobalMemory CacheCxt; /* from utils/cache/catcache.c */ /* ---------------- - * hardcoded tuple descriptors. see lib/backend/catalog/pg_attribute.h + * hardcoded tuple descriptors. see lib/backend/catalog/pg_attribute.h * ---------------- */ -FormData_pg_attribute Desc_pg_class[Natts_pg_class] = { Schema_pg_class }; -FormData_pg_attribute Desc_pg_attribute[Natts_pg_attribute] = { Schema_pg_attribute }; -FormData_pg_attribute Desc_pg_proc[Natts_pg_proc] = { Schema_pg_proc }; -FormData_pg_attribute Desc_pg_type[Natts_pg_type] = { Schema_pg_type }; -FormData_pg_attribute Desc_pg_variable[Natts_pg_variable] = { Schema_pg_variable }; -FormData_pg_attribute Desc_pg_log[Natts_pg_log] = { Schema_pg_log }; -FormData_pg_attribute Desc_pg_time[Natts_pg_time] = { Schema_pg_time }; +FormData_pg_attribute Desc_pg_class[Natts_pg_class] = {Schema_pg_class}; +FormData_pg_attribute Desc_pg_attribute[Natts_pg_attribute] = {Schema_pg_attribute}; +FormData_pg_attribute Desc_pg_proc[Natts_pg_proc] = {Schema_pg_proc}; +FormData_pg_attribute Desc_pg_type[Natts_pg_type] = {Schema_pg_type}; +FormData_pg_attribute Desc_pg_variable[Natts_pg_variable] = {Schema_pg_variable}; +FormData_pg_attribute Desc_pg_log[Natts_pg_log] = {Schema_pg_log}; +FormData_pg_attribute Desc_pg_time[Natts_pg_time] = {Schema_pg_time}; /* ---------------- - * global variables + * global variables * - * Relations are cached two ways, by name and by id, - * thus there are two hash tables for referencing them. + * Relations are cached two ways, by name and by id, + * thus there are two hash tables for referencing them. * ---------------- */ -HTAB *RelationNameCache; -HTAB *RelationIdCache; +HTAB *RelationNameCache; +HTAB *RelationIdCache; /* ---------------- - * RelationBuildDescInfo exists so code can be shared - * between RelationIdGetRelation() and RelationNameGetRelation() + * RelationBuildDescInfo exists so code can be shared + * between RelationIdGetRelation() and RelationNameGetRelation() * ---------------- */ -typedef struct RelationBuildDescInfo { - int infotype; /* lookup by id or by name */ +typedef struct RelationBuildDescInfo +{ + int infotype; /* lookup by id or by name */ #define INFO_RELID 1 #define INFO_RELNAME 2 - union { - Oid info_id; /* relation object id */ - char *info_name; /* relation name */ - } i; -} RelationBuildDescInfo; - -typedef struct relidcacheent { - Oid reloid; - Relation reldesc; -} RelIdCacheEnt; - -typedef struct relnamecacheent { - NameData relname; - Relation reldesc; -} RelNameCacheEnt; + union + { + Oid info_id;/* relation object id */ + char *info_name; /* relation name */ + } i; +} RelationBuildDescInfo; + +typedef struct relidcacheent +{ + Oid reloid; + Relation reldesc; +} RelIdCacheEnt; + +typedef struct relnamecacheent +{ + NameData relname; + Relation reldesc; +} RelNameCacheEnt; /* ----------------- - * macros to manipulate name cache and id cache + * macros to manipulate name cache and id cache * ----------------- */ #define RelationCacheInsert(RELATION) \ - { RelIdCacheEnt *idhentry; RelNameCacheEnt *namehentry; \ - char *relname; Oid reloid; bool found; \ - relname = (RELATION->rd_rel->relname).data; \ - namehentry = (RelNameCacheEnt*)hash_search(RelationNameCache, \ - relname, \ - HASH_ENTER, \ - &found); \ - if (namehentry == NULL) { \ - elog(FATAL, "can't insert into relation descriptor cache"); \ - } \ - if (found && !IsBootstrapProcessingMode()) { \ - /* used to give notice -- now just keep quiet */ ; \ - } \ - namehentry->reldesc = RELATION; \ - reloid = RELATION->rd_id; \ - idhentry = (RelIdCacheEnt*)hash_search(RelationIdCache, \ - (char *)&reloid, \ - HASH_ENTER, \ - &found); \ - if (idhentry == NULL) { \ - elog(FATAL, "can't insert into relation descriptor cache"); \ - } \ - if (found && !IsBootstrapProcessingMode()) { \ - /* used to give notice -- now just keep quiet */ ; \ - } \ - idhentry->reldesc = RELATION; \ - } -#define RelationNameCacheLookup(NAME, RELATION) \ - { RelNameCacheEnt *hentry; bool found; \ - hentry = (RelNameCacheEnt*)hash_search(RelationNameCache, \ - (char *)NAME,HASH_FIND,&found); \ - if (hentry == NULL) { \ - elog(FATAL, "error in CACHE"); \ - } \ - if (found) { \ - RELATION = hentry->reldesc; \ - } \ - else { \ - RELATION = NULL; \ - } \ - } -#define RelationIdCacheLookup(ID, RELATION) \ - { RelIdCacheEnt *hentry; bool found; \ - hentry = (RelIdCacheEnt*)hash_search(RelationIdCache, \ - (char *)&(ID),HASH_FIND, &found); \ - if (hentry == NULL) { \ - elog(FATAL, "error in CACHE"); \ - } \ - if (found) { \ - RELATION = hentry->reldesc; \ - } \ - else { \ - RELATION = NULL; \ - } \ - } + { RelIdCacheEnt *idhentry; RelNameCacheEnt *namehentry; \ + char *relname; Oid reloid; bool found; \ + relname = (RELATION->rd_rel->relname).data; \ + namehentry = (RelNameCacheEnt*)hash_search(RelationNameCache, \ + relname, \ + HASH_ENTER, \ + &found); \ + if (namehentry == NULL) { \ + elog(FATAL, "can't insert into relation descriptor cache"); \ + } \ + if (found && !IsBootstrapProcessingMode()) { \ + /* used to give notice -- now just keep quiet */ ; \ + } \ + namehentry->reldesc = RELATION; \ + reloid = RELATION->rd_id; \ + idhentry = (RelIdCacheEnt*)hash_search(RelationIdCache, \ + (char *)&reloid, \ + HASH_ENTER, \ + &found); \ + if (idhentry == NULL) { \ + elog(FATAL, "can't insert into relation descriptor cache"); \ + } \ + if (found && !IsBootstrapProcessingMode()) { \ + /* used to give notice -- now just keep quiet */ ; \ + } \ + idhentry->reldesc = RELATION; \ + } +#define RelationNameCacheLookup(NAME, RELATION) \ + { RelNameCacheEnt *hentry; bool found; \ + hentry = (RelNameCacheEnt*)hash_search(RelationNameCache, \ + (char *)NAME,HASH_FIND,&found); \ + if (hentry == NULL) { \ + elog(FATAL, "error in CACHE"); \ + } \ + if (found) { \ + RELATION = hentry->reldesc; \ + } \ + else { \ + RELATION = NULL; \ + } \ + } +#define RelationIdCacheLookup(ID, RELATION) \ + { RelIdCacheEnt *hentry; bool found; \ + hentry = (RelIdCacheEnt*)hash_search(RelationIdCache, \ + (char *)&(ID),HASH_FIND, &found); \ + if (hentry == NULL) { \ + elog(FATAL, "error in CACHE"); \ + } \ + if (found) { \ + RELATION = hentry->reldesc; \ + } \ + else { \ + RELATION = NULL; \ + } \ + } #define RelationCacheDelete(RELATION) \ - { RelNameCacheEnt *namehentry; RelIdCacheEnt *idhentry; \ - char *relname; Oid reloid; bool found; \ - relname = (RELATION->rd_rel->relname).data; \ - namehentry = (RelNameCacheEnt*)hash_search(RelationNameCache, \ - relname, \ - HASH_REMOVE, \ - &found); \ - if (namehentry == NULL) { \ - elog(FATAL, "can't delete from relation descriptor cache"); \ - } \ - if (!found) { \ - elog(NOTICE, "trying to delete a reldesc that does not exist."); \ - } \ - reloid = RELATION->rd_id; \ - idhentry = (RelIdCacheEnt*)hash_search(RelationIdCache, \ - (char *)&reloid, \ - HASH_REMOVE, &found); \ - if (idhentry == NULL) { \ - elog(FATAL, "can't delete from relation descriptor cache"); \ - } \ - if (!found) { \ - elog(NOTICE, "trying to delete a reldesc that does not exist."); \ - } \ - } + { RelNameCacheEnt *namehentry; RelIdCacheEnt *idhentry; \ + char *relname; Oid reloid; bool found; \ + relname = (RELATION->rd_rel->relname).data; \ + namehentry = (RelNameCacheEnt*)hash_search(RelationNameCache, \ + relname, \ + HASH_REMOVE, \ + &found); \ + if (namehentry == NULL) { \ + elog(FATAL, "can't delete from relation descriptor cache"); \ + } \ + if (!found) { \ + elog(NOTICE, "trying to delete a reldesc that does not exist."); \ + } \ + reloid = RELATION->rd_id; \ + idhentry = (RelIdCacheEnt*)hash_search(RelationIdCache, \ + (char *)&reloid, \ + HASH_REMOVE, &found); \ + if (idhentry == NULL) { \ + elog(FATAL, "can't delete from relation descriptor cache"); \ + } \ + if (!found) { \ + elog(NOTICE, "trying to delete a reldesc that does not exist."); \ + } \ + } /* non-export function prototypes */ -static void formrdesc(char *relationName, u_int natts, - FormData_pg_attribute att[]); +static void +formrdesc(char *relationName, u_int natts, + FormData_pg_attribute att[]); + +#if 0 /* See comments at line 1304 */ +static void RelationFlushIndexes(Relation * r, Oid accessMethodId); -#if 0 /* See comments at line 1304 */ -static void RelationFlushIndexes(Relation *r, Oid accessMethodId); #endif static HeapTuple ScanPgRelation(RelationBuildDescInfo buildinfo); static HeapTuple scan_pg_rel_seq(RelationBuildDescInfo buildinfo); static HeapTuple scan_pg_rel_ind(RelationBuildDescInfo buildinfo); static Relation AllocateRelationDesc(u_int natts, Form_pg_class relp); -static void RelationBuildTupleDesc(RelationBuildDescInfo buildinfo, - Relation relation, u_int natts); -static void build_tupdesc_seq(RelationBuildDescInfo buildinfo, - Relation relation, u_int natts); -static void build_tupdesc_ind(RelationBuildDescInfo buildinfo, - Relation relation, u_int natts); +static void +RelationBuildTupleDesc(RelationBuildDescInfo buildinfo, + Relation relation, u_int natts); +static void +build_tupdesc_seq(RelationBuildDescInfo buildinfo, + Relation relation, u_int natts); +static void +build_tupdesc_ind(RelationBuildDescInfo buildinfo, + Relation relation, u_int natts); static Relation RelationBuildDesc(RelationBuildDescInfo buildinfo); -static void IndexedAccessMethodInitialize(Relation relation); -static void AttrDefaultFetch (Relation relation); -static void RelCheckFetch (Relation relation); +static void IndexedAccessMethodInitialize(Relation relation); +static void AttrDefaultFetch(Relation relation); +static void RelCheckFetch(Relation relation); -extern void RelationBuildTriggers (Relation relation); -extern void FreeTriggerDesc (Relation relation); +extern void RelationBuildTriggers(Relation relation); +extern void FreeTriggerDesc(Relation relation); /* * newlyCreatedRelns - - * relations created during this transaction. We need to keep track of - * these. + * relations created during this transaction. We need to keep track of + * these. */ -static List *newlyCreatedRelns = NULL; +static List *newlyCreatedRelns = NULL; /* ---------------------------------------------------------------- - * RelationIdGetRelation() and RelationNameGetRelation() - * support functions + * RelationIdGetRelation() and RelationNameGetRelation() + * support functions * ---------------------------------------------------------------- */ - -#if NOT_USED /* XXX This doesn't seem to be used anywhere */ + +#if NOT_USED /* XXX This doesn't seem to be used + * anywhere */ /* -------------------------------- - * BuildDescInfoError returns a string appropriate to - * the buildinfo passed to it + * BuildDescInfoError returns a string appropriate to + * the buildinfo passed to it * -------------------------------- */ -static char * +static char * BuildDescInfoError(RelationBuildDescInfo buildinfo) { - static char errBuf[64]; - - memset(errBuf, 0, (int) sizeof(errBuf)); - switch(buildinfo.infotype) { - case INFO_RELID: - sprintf(errBuf, "(relation id %d)", buildinfo.i.info_id); - break; - case INFO_RELNAME: - sprintf(errBuf, "(relation name %s)", buildinfo.i.info_name); - break; - } - - return errBuf; + static char errBuf[64]; + + memset(errBuf, 0, (int) sizeof(errBuf)); + switch (buildinfo.infotype) + { + case INFO_RELID: + sprintf(errBuf, "(relation id %d)", buildinfo.i.info_id); + break; + case INFO_RELNAME: + sprintf(errBuf, "(relation name %s)", buildinfo.i.info_name); + break; + } + + return errBuf; } + #endif /* -------------------------------- - * ScanPgRelation + * ScanPgRelation * - * this is used by RelationBuildDesc to find a pg_class - * tuple matching either a relation name or a relation id - * as specified in buildinfo. + * this is used by RelationBuildDesc to find a pg_class + * tuple matching either a relation name or a relation id + * as specified in buildinfo. * -------------------------------- */ -static HeapTuple +static HeapTuple ScanPgRelation(RelationBuildDescInfo buildinfo) { - /* - * If this is bootstrap time (initdb), then we can't use the system - * catalog indices, because they may not exist yet. Otherwise, we - * can, and do. - */ - - if (IsBootstrapProcessingMode()) - return (scan_pg_rel_seq(buildinfo)); - else - return (scan_pg_rel_ind(buildinfo)); + + /* + * If this is bootstrap time (initdb), then we can't use the system + * catalog indices, because they may not exist yet. Otherwise, we + * can, and do. + */ + + if (IsBootstrapProcessingMode()) + return (scan_pg_rel_seq(buildinfo)); + else + return (scan_pg_rel_ind(buildinfo)); } -static HeapTuple +static HeapTuple scan_pg_rel_seq(RelationBuildDescInfo buildinfo) { - HeapTuple pg_class_tuple; - HeapTuple return_tuple; - Relation pg_class_desc; - HeapScanDesc pg_class_scan; - ScanKeyData key; - Buffer buf; - - /* ---------------- - * form a scan key - * ---------------- - */ - switch (buildinfo.infotype) { - case INFO_RELID: - ScanKeyEntryInitialize(&key, 0, - ObjectIdAttributeNumber, - ObjectIdEqualRegProcedure, - ObjectIdGetDatum(buildinfo.i.info_id)); - break; - - case INFO_RELNAME: - ScanKeyEntryInitialize(&key, 0, - Anum_pg_class_relname, - Character16EqualRegProcedure, - NameGetDatum(buildinfo.i.info_name)); - break; - - default: - elog(WARN, "ScanPgRelation: bad buildinfo"); - return NULL; - } - - /* ---------------- - * open pg_class and fetch a tuple - * ---------------- - */ - pg_class_desc = heap_openr(RelationRelationName); - if (!IsInitProcessingMode()) - RelationSetLockForRead(pg_class_desc); - pg_class_scan = - heap_beginscan(pg_class_desc, 0, NowTimeQual, 1, &key); - pg_class_tuple = heap_getnext(pg_class_scan, 0, &buf); - - /* ---------------- - * get set to return tuple - * ---------------- - */ - if (! HeapTupleIsValid(pg_class_tuple)) { - return_tuple = pg_class_tuple; - } else { - /* ------------------ - * a satanic bug used to live here: pg_class_tuple used to be - * returned here without having the corresponding buffer pinned. - * so when the buffer gets replaced, all hell breaks loose. - * this bug is discovered and killed by wei on 9/27/91. - * ------------------- + HeapTuple pg_class_tuple; + HeapTuple return_tuple; + Relation pg_class_desc; + HeapScanDesc pg_class_scan; + ScanKeyData key; + Buffer buf; + + /* ---------------- + * form a scan key + * ---------------- */ - return_tuple = (HeapTuple) palloc((Size) pg_class_tuple->t_len); - memmove((char *) return_tuple, - (char *) pg_class_tuple, - (int) pg_class_tuple->t_len); - ReleaseBuffer(buf); - } - - /* all done */ - heap_endscan(pg_class_scan); - if (!IsInitProcessingMode()) - RelationUnsetLockForRead(pg_class_desc); - heap_close(pg_class_desc); - - return return_tuple; + switch (buildinfo.infotype) + { + case INFO_RELID: + ScanKeyEntryInitialize(&key, 0, + ObjectIdAttributeNumber, + ObjectIdEqualRegProcedure, + ObjectIdGetDatum(buildinfo.i.info_id)); + break; + + case INFO_RELNAME: + ScanKeyEntryInitialize(&key, 0, + Anum_pg_class_relname, + Character16EqualRegProcedure, + NameGetDatum(buildinfo.i.info_name)); + break; + + default: + elog(WARN, "ScanPgRelation: bad buildinfo"); + return NULL; + } + + /* ---------------- + * open pg_class and fetch a tuple + * ---------------- + */ + pg_class_desc = heap_openr(RelationRelationName); + if (!IsInitProcessingMode()) + RelationSetLockForRead(pg_class_desc); + pg_class_scan = + heap_beginscan(pg_class_desc, 0, NowTimeQual, 1, &key); + pg_class_tuple = heap_getnext(pg_class_scan, 0, &buf); + + /* ---------------- + * get set to return tuple + * ---------------- + */ + if (!HeapTupleIsValid(pg_class_tuple)) + { + return_tuple = pg_class_tuple; + } + else + { + /* ------------------ + * a satanic bug used to live here: pg_class_tuple used to be + * returned here without having the corresponding buffer pinned. + * so when the buffer gets replaced, all hell breaks loose. + * this bug is discovered and killed by wei on 9/27/91. + * ------------------- + */ + return_tuple = (HeapTuple) palloc((Size) pg_class_tuple->t_len); + memmove((char *) return_tuple, + (char *) pg_class_tuple, + (int) pg_class_tuple->t_len); + ReleaseBuffer(buf); + } + + /* all done */ + heap_endscan(pg_class_scan); + if (!IsInitProcessingMode()) + RelationUnsetLockForRead(pg_class_desc); + heap_close(pg_class_desc); + + return return_tuple; } -static HeapTuple +static HeapTuple scan_pg_rel_ind(RelationBuildDescInfo buildinfo) { - Relation pg_class_desc; - HeapTuple return_tuple; - - pg_class_desc = heap_openr(RelationRelationName); - if (!IsInitProcessingMode()) - RelationSetLockForRead(pg_class_desc); - - switch (buildinfo.infotype) { - case INFO_RELID: - return_tuple = ClassOidIndexScan(pg_class_desc, buildinfo.i.info_id); - break; - - case INFO_RELNAME: - return_tuple = ClassNameIndexScan(pg_class_desc, - buildinfo.i.info_name); - break; - - default: - elog(WARN, "ScanPgRelation: bad buildinfo"); - /* XXX I hope this is right. It seems better than returning - * an uninitialized value */ - return_tuple = NULL; - } - - /* all done */ - if (!IsInitProcessingMode()) - RelationUnsetLockForRead(pg_class_desc); - heap_close(pg_class_desc); - - return return_tuple; + Relation pg_class_desc; + HeapTuple return_tuple; + + pg_class_desc = heap_openr(RelationRelationName); + if (!IsInitProcessingMode()) + RelationSetLockForRead(pg_class_desc); + + switch (buildinfo.infotype) + { + case INFO_RELID: + return_tuple = ClassOidIndexScan(pg_class_desc, buildinfo.i.info_id); + break; + + case INFO_RELNAME: + return_tuple = ClassNameIndexScan(pg_class_desc, + buildinfo.i.info_name); + break; + + default: + elog(WARN, "ScanPgRelation: bad buildinfo"); + + /* + * XXX I hope this is right. It seems better than returning an + * uninitialized value + */ + return_tuple = NULL; + } + + /* all done */ + if (!IsInitProcessingMode()) + RelationUnsetLockForRead(pg_class_desc); + heap_close(pg_class_desc); + + return return_tuple; } /* ---------------- - * AllocateRelationDesc + * AllocateRelationDesc * - * This is used to allocate memory for a new relation descriptor - * and initialize the rd_rel field. + * This is used to allocate memory for a new relation descriptor + * and initialize the rd_rel field. * ---------------- */ -static Relation +static Relation AllocateRelationDesc(u_int natts, Form_pg_class relp) { - Relation relation; - Size len; - Form_pg_class relationTupleForm; - - /* ---------------- - * allocate space for the relation tuple form - * ---------------- - */ - relationTupleForm = (Form_pg_class) - palloc((Size) (sizeof(FormData_pg_class))); - - memmove((char *) relationTupleForm, (char *) relp, CLASS_TUPLE_SIZE); - - /* ---------------- - * allocate space for new relation descriptor - */ - len = sizeof(RelationData) + 10; /* + 10 is voodoo XXX mao */ - - relation = (Relation) palloc(len); - - /* ---------------- - * clear new reldesc - * ---------------- - */ - memset((char *) relation, 0, len); - - /* initialize attribute tuple form */ - relation->rd_att = CreateTemplateTupleDesc(natts); - - /*and initialize relation tuple form */ - relation->rd_rel = relationTupleForm; - - return relation; + Relation relation; + Size len; + Form_pg_class relationTupleForm; + + /* ---------------- + * allocate space for the relation tuple form + * ---------------- + */ + relationTupleForm = (Form_pg_class) + palloc((Size) (sizeof(FormData_pg_class))); + + memmove((char *) relationTupleForm, (char *) relp, CLASS_TUPLE_SIZE); + + /* ---------------- + * allocate space for new relation descriptor + */ + len = sizeof(RelationData) + 10; /* + 10 is voodoo XXX mao */ + + relation = (Relation) palloc(len); + + /* ---------------- + * clear new reldesc + * ---------------- + */ + memset((char *) relation, 0, len); + + /* initialize attribute tuple form */ + relation->rd_att = CreateTemplateTupleDesc(natts); + + /* and initialize relation tuple form */ + relation->rd_rel = relationTupleForm; + + return relation; } /* -------------------------------- - * RelationBuildTupleDesc + * RelationBuildTupleDesc * - * Form the relation's tuple descriptor from information in - * the pg_attribute, pg_attrdef & pg_relcheck system cataloges. + * Form the relation's tuple descriptor from information in + * the pg_attribute, pg_attrdef & pg_relcheck system cataloges. * -------------------------------- */ static void -RelationBuildTupleDesc(RelationBuildDescInfo buildinfo, - Relation relation, - u_int natts) +RelationBuildTupleDesc(RelationBuildDescInfo buildinfo, + Relation relation, + u_int natts) { - /* - * If this is bootstrap time (initdb), then we can't use the system - * catalog indices, because they may not exist yet. Otherwise, we - * can, and do. - */ - - if (IsBootstrapProcessingMode()) - build_tupdesc_seq(buildinfo, relation, natts); - else - build_tupdesc_ind(buildinfo, relation, natts); + + /* + * If this is bootstrap time (initdb), then we can't use the system + * catalog indices, because they may not exist yet. Otherwise, we + * can, and do. + */ + + if (IsBootstrapProcessingMode()) + build_tupdesc_seq(buildinfo, relation, natts); + else + build_tupdesc_ind(buildinfo, relation, natts); } static void build_tupdesc_seq(RelationBuildDescInfo buildinfo, - Relation relation, - u_int natts) + Relation relation, + u_int natts) { - HeapTuple pg_attribute_tuple; - Relation pg_attribute_desc; - HeapScanDesc pg_attribute_scan; - AttributeTupleForm attp; - ScanKeyData key; - int need; - - /* ---------------- - * form a scan key - * ---------------- - */ - ScanKeyEntryInitialize(&key, 0, - Anum_pg_attribute_attrelid, - ObjectIdEqualRegProcedure, - ObjectIdGetDatum(relation->rd_id)); - - /* ---------------- - * open pg_attribute and begin a scan - * ---------------- - */ - pg_attribute_desc = heap_openr(AttributeRelationName); - pg_attribute_scan = - heap_beginscan(pg_attribute_desc, 0, NowTimeQual, 1, &key); - - /* ---------------- - * add attribute data to relation->rd_att - * ---------------- - */ - need = natts; - - pg_attribute_tuple = heap_getnext(pg_attribute_scan, 0, (Buffer *) NULL); - while (HeapTupleIsValid(pg_attribute_tuple) && need > 0) { - attp = (AttributeTupleForm) GETSTRUCT(pg_attribute_tuple); - - if (attp->attnum > 0) { - relation->rd_att->attrs[attp->attnum - 1] = - (AttributeTupleForm)palloc(ATTRIBUTE_TUPLE_SIZE); - - memmove((char *) (relation->rd_att->attrs[attp->attnum - 1]), - (char *) attp, - ATTRIBUTE_TUPLE_SIZE); - need--; + HeapTuple pg_attribute_tuple; + Relation pg_attribute_desc; + HeapScanDesc pg_attribute_scan; + AttributeTupleForm attp; + ScanKeyData key; + int need; + + /* ---------------- + * form a scan key + * ---------------- + */ + ScanKeyEntryInitialize(&key, 0, + Anum_pg_attribute_attrelid, + ObjectIdEqualRegProcedure, + ObjectIdGetDatum(relation->rd_id)); + + /* ---------------- + * open pg_attribute and begin a scan + * ---------------- + */ + pg_attribute_desc = heap_openr(AttributeRelationName); + pg_attribute_scan = + heap_beginscan(pg_attribute_desc, 0, NowTimeQual, 1, &key); + + /* ---------------- + * add attribute data to relation->rd_att + * ---------------- + */ + need = natts; + + pg_attribute_tuple = heap_getnext(pg_attribute_scan, 0, (Buffer *) NULL); + while (HeapTupleIsValid(pg_attribute_tuple) && need > 0) + { + attp = (AttributeTupleForm) GETSTRUCT(pg_attribute_tuple); + + if (attp->attnum > 0) + { + relation->rd_att->attrs[attp->attnum - 1] = + (AttributeTupleForm) palloc(ATTRIBUTE_TUPLE_SIZE); + + memmove((char *) (relation->rd_att->attrs[attp->attnum - 1]), + (char *) attp, + ATTRIBUTE_TUPLE_SIZE); + need--; + } + pg_attribute_tuple = heap_getnext(pg_attribute_scan, + 0, (Buffer *) NULL); } - pg_attribute_tuple = heap_getnext(pg_attribute_scan, - 0, (Buffer *) NULL); - } - - if (need > 0) - elog(WARN, "catalog is missing %d attribute%s for relid %d", - need, (need == 1 ? "" : "s"), relation->rd_id); - - /* ---------------- - * end the scan and close the attribute relation - * ---------------- - */ - heap_endscan(pg_attribute_scan); - heap_close(pg_attribute_desc); + + if (need > 0) + elog(WARN, "catalog is missing %d attribute%s for relid %d", + need, (need == 1 ? "" : "s"), relation->rd_id); + + /* ---------------- + * end the scan and close the attribute relation + * ---------------- + */ + heap_endscan(pg_attribute_scan); + heap_close(pg_attribute_desc); } static void build_tupdesc_ind(RelationBuildDescInfo buildinfo, - Relation relation, - u_int natts) + Relation relation, + u_int natts) { - Relation attrel; - HeapTuple atttup; - AttributeTupleForm attp; - TupleConstr *constr = (TupleConstr *) palloc(sizeof(TupleConstr)); - AttrDefault *attrdef = NULL; - int ndef = 0; - int i; - - constr->has_not_null = false; - - attrel = heap_openr(AttributeRelationName); - - for (i = 1; i <= relation->rd_rel->relnatts; i++) { - - atttup = (HeapTuple) AttributeNumIndexScan(attrel, relation->rd_id, i); - - if (!HeapTupleIsValid(atttup)) - elog(WARN, "cannot find attribute %d of relation %.*s", i, - NAMEDATALEN, &(relation->rd_rel->relname.data[0])); - attp = (AttributeTupleForm) GETSTRUCT(atttup); - - relation->rd_att->attrs[i - 1] = - (AttributeTupleForm) palloc(ATTRIBUTE_TUPLE_SIZE); - - memmove((char *) (relation->rd_att->attrs[i - 1]), - (char *) attp, - ATTRIBUTE_TUPLE_SIZE); - - /* Update if this attribute have a constraint */ - if (attp->attnotnull) - constr->has_not_null = true; - - if (attp->atthasdef) + Relation attrel; + HeapTuple atttup; + AttributeTupleForm attp; + TupleConstr *constr = (TupleConstr *) palloc(sizeof(TupleConstr)); + AttrDefault *attrdef = NULL; + int ndef = 0; + int i; + + constr->has_not_null = false; + + attrel = heap_openr(AttributeRelationName); + + for (i = 1; i <= relation->rd_rel->relnatts; i++) { - if ( attrdef == NULL ) - attrdef = (AttrDefault*) palloc (relation->rd_rel->relnatts * - sizeof (AttrDefault)); - attrdef[ndef].adnum = i; - attrdef[ndef].adbin = NULL; - attrdef[ndef].adsrc = NULL; - ndef++; + + atttup = (HeapTuple) AttributeNumIndexScan(attrel, relation->rd_id, i); + + if (!HeapTupleIsValid(atttup)) + elog(WARN, "cannot find attribute %d of relation %.*s", i, + NAMEDATALEN, &(relation->rd_rel->relname.data[0])); + attp = (AttributeTupleForm) GETSTRUCT(atttup); + + relation->rd_att->attrs[i - 1] = + (AttributeTupleForm) palloc(ATTRIBUTE_TUPLE_SIZE); + + memmove((char *) (relation->rd_att->attrs[i - 1]), + (char *) attp, + ATTRIBUTE_TUPLE_SIZE); + + /* Update if this attribute have a constraint */ + if (attp->attnotnull) + constr->has_not_null = true; + + if (attp->atthasdef) + { + if (attrdef == NULL) + attrdef = (AttrDefault *) palloc(relation->rd_rel->relnatts * + sizeof(AttrDefault)); + attrdef[ndef].adnum = i; + attrdef[ndef].adbin = NULL; + attrdef[ndef].adsrc = NULL; + ndef++; + } } - } - - heap_close(attrel); - - if ( constr->has_not_null || ndef > 0 || relation->rd_rel->relchecks ) - { - relation->rd_att->constr = constr; - - if ( ndef > 0 ) /* DEFAULTs */ - { - if ( ndef < relation->rd_rel->relnatts ) - constr->defval = (AttrDefault*) - repalloc (attrdef, ndef * sizeof (AttrDefault)); - else - constr->defval = attrdef; - constr->num_defval = ndef; - AttrDefaultFetch (relation); - } - else - constr->num_defval = 0; - - if ( relation->rd_rel->relchecks > 0 ) /* CHECKs */ + + heap_close(attrel); + + if (constr->has_not_null || ndef > 0 || relation->rd_rel->relchecks) { - constr->num_check = relation->rd_rel->relchecks; - constr->check = (ConstrCheck *) palloc (constr->num_check * - sizeof (ConstrCheck)); - memset (constr->check, 0, constr->num_check * sizeof (ConstrCheck)); - RelCheckFetch (relation); + relation->rd_att->constr = constr; + + if (ndef > 0) /* DEFAULTs */ + { + if (ndef < relation->rd_rel->relnatts) + constr->defval = (AttrDefault *) + repalloc(attrdef, ndef * sizeof(AttrDefault)); + else + constr->defval = attrdef; + constr->num_defval = ndef; + AttrDefaultFetch(relation); + } + else + constr->num_defval = 0; + + if (relation->rd_rel->relchecks > 0) /* CHECKs */ + { + constr->num_check = relation->rd_rel->relchecks; + constr->check = (ConstrCheck *) palloc(constr->num_check * + sizeof(ConstrCheck)); + memset(constr->check, 0, constr->num_check * sizeof(ConstrCheck)); + RelCheckFetch(relation); + } + else + constr->num_check = 0; } else - constr->num_check = 0; - } - else - { - pfree (constr); - relation->rd_att->constr = NULL; - } - + { + pfree(constr); + relation->rd_att->constr = NULL; + } + } /* -------------------------------- - * RelationBuildRuleLock + * RelationBuildRuleLock * - * Form the relation's rewrite rules from information in - * the pg_rewrite system catalog. + * Form the relation's rewrite rules from information in + * the pg_rewrite system catalog. * -------------------------------- */ static void RelationBuildRuleLock(Relation relation) { - HeapTuple pg_rewrite_tuple; - Relation pg_rewrite_desc; - TupleDesc pg_rewrite_tupdesc; - HeapScanDesc pg_rewrite_scan; - ScanKeyData key; - RuleLock *rulelock; - int numlocks; - RewriteRule **rules; - int maxlocks; - - /* ---------------- - * form an array to hold the rewrite rules (the array is extended if - * necessary) - * ---------------- - */ - maxlocks = 4; - rules = (RewriteRule **)palloc(sizeof(RewriteRule*)*maxlocks); - numlocks = 0; - - /* ---------------- - * form a scan key - * ---------------- - */ - ScanKeyEntryInitialize(&key, 0, - Anum_pg_rewrite_ev_class, - ObjectIdEqualRegProcedure, - ObjectIdGetDatum(relation->rd_id)); - - /* ---------------- - * open pg_attribute and begin a scan - * ---------------- - */ - pg_rewrite_desc = heap_openr(RewriteRelationName); - pg_rewrite_scan = - heap_beginscan(pg_rewrite_desc, 0, NowTimeQual, 1, &key); - pg_rewrite_tupdesc = - RelationGetTupleDescriptor(pg_rewrite_desc); - - /* ---------------- - * add attribute data to relation->rd_att - * ---------------- - */ - while ((pg_rewrite_tuple = heap_getnext(pg_rewrite_scan, 0, - (Buffer *) NULL)) != NULL) { - bool isnull; - char *ruleaction = NULL; - char *rule_evqual_string; - RewriteRule *rule; - - rule = (RewriteRule *)palloc(sizeof(RewriteRule)); - - rule->ruleId = pg_rewrite_tuple->t_oid; - - rule->event = - (int)heap_getattr(pg_rewrite_tuple, InvalidBuffer, - Anum_pg_rewrite_ev_type, pg_rewrite_tupdesc, - &isnull) - 48; - rule->attrno = - (int)heap_getattr(pg_rewrite_tuple, InvalidBuffer, - Anum_pg_rewrite_ev_attr, pg_rewrite_tupdesc, - &isnull); - rule->isInstead = - !!heap_getattr(pg_rewrite_tuple, InvalidBuffer, - Anum_pg_rewrite_is_instead, pg_rewrite_tupdesc, - &isnull); - - ruleaction = - heap_getattr(pg_rewrite_tuple, InvalidBuffer, - Anum_pg_rewrite_action, pg_rewrite_tupdesc, - &isnull); - rule_evqual_string = - heap_getattr(pg_rewrite_tuple, InvalidBuffer, - Anum_pg_rewrite_ev_qual, pg_rewrite_tupdesc, - &isnull); - - ruleaction = textout((struct varlena *)ruleaction); - rule_evqual_string = textout((struct varlena *)rule_evqual_string); - - rule->actions = (List*)stringToNode(ruleaction); - rule->qual = (Node*)stringToNode(rule_evqual_string); - - rules[numlocks++] = rule; - if (numlocks==maxlocks) { - maxlocks *= 2; - rules = - (RewriteRule **)repalloc(rules, sizeof(RewriteRule*)*maxlocks); + HeapTuple pg_rewrite_tuple; + Relation pg_rewrite_desc; + TupleDesc pg_rewrite_tupdesc; + HeapScanDesc pg_rewrite_scan; + ScanKeyData key; + RuleLock *rulelock; + int numlocks; + RewriteRule **rules; + int maxlocks; + + /* ---------------- + * form an array to hold the rewrite rules (the array is extended if + * necessary) + * ---------------- + */ + maxlocks = 4; + rules = (RewriteRule **) palloc(sizeof(RewriteRule *) * maxlocks); + numlocks = 0; + + /* ---------------- + * form a scan key + * ---------------- + */ + ScanKeyEntryInitialize(&key, 0, + Anum_pg_rewrite_ev_class, + ObjectIdEqualRegProcedure, + ObjectIdGetDatum(relation->rd_id)); + + /* ---------------- + * open pg_attribute and begin a scan + * ---------------- + */ + pg_rewrite_desc = heap_openr(RewriteRelationName); + pg_rewrite_scan = + heap_beginscan(pg_rewrite_desc, 0, NowTimeQual, 1, &key); + pg_rewrite_tupdesc = + RelationGetTupleDescriptor(pg_rewrite_desc); + + /* ---------------- + * add attribute data to relation->rd_att + * ---------------- + */ + while ((pg_rewrite_tuple = heap_getnext(pg_rewrite_scan, 0, + (Buffer *) NULL)) != NULL) + { + bool isnull; + char *ruleaction = NULL; + char *rule_evqual_string; + RewriteRule *rule; + + rule = (RewriteRule *) palloc(sizeof(RewriteRule)); + + rule->ruleId = pg_rewrite_tuple->t_oid; + + rule->event = + (int) heap_getattr(pg_rewrite_tuple, InvalidBuffer, + Anum_pg_rewrite_ev_type, pg_rewrite_tupdesc, + &isnull) - 48; + rule->attrno = + (int) heap_getattr(pg_rewrite_tuple, InvalidBuffer, + Anum_pg_rewrite_ev_attr, pg_rewrite_tupdesc, + &isnull); + rule->isInstead = + !!heap_getattr(pg_rewrite_tuple, InvalidBuffer, + Anum_pg_rewrite_is_instead, pg_rewrite_tupdesc, + &isnull); + + ruleaction = + heap_getattr(pg_rewrite_tuple, InvalidBuffer, + Anum_pg_rewrite_action, pg_rewrite_tupdesc, + &isnull); + rule_evqual_string = + heap_getattr(pg_rewrite_tuple, InvalidBuffer, + Anum_pg_rewrite_ev_qual, pg_rewrite_tupdesc, + &isnull); + + ruleaction = textout((struct varlena *) ruleaction); + rule_evqual_string = textout((struct varlena *) rule_evqual_string); + + rule->actions = (List *) stringToNode(ruleaction); + rule->qual = (Node *) stringToNode(rule_evqual_string); + + rules[numlocks++] = rule; + if (numlocks == maxlocks) + { + maxlocks *= 2; + rules = + (RewriteRule **) repalloc(rules, sizeof(RewriteRule *) * maxlocks); + } } - } - - /* ---------------- - * end the scan and close the attribute relation - * ---------------- - */ - heap_endscan(pg_rewrite_scan); - heap_close(pg_rewrite_desc); - - /* ---------------- - * form a RuleLock and insert into relation - * ---------------- - */ - rulelock = (RuleLock *)palloc(sizeof(RuleLock)); - rulelock->numLocks = numlocks; - rulelock->rules = rules; - - relation->rd_rules = rulelock; - return; + + /* ---------------- + * end the scan and close the attribute relation + * ---------------- + */ + heap_endscan(pg_rewrite_scan); + heap_close(pg_rewrite_desc); + + /* ---------------- + * form a RuleLock and insert into relation + * ---------------- + */ + rulelock = (RuleLock *) palloc(sizeof(RuleLock)); + rulelock->numLocks = numlocks; + rulelock->rules = rules; + + relation->rd_rules = rulelock; + return; } /* -------------------------------- - * RelationBuildDesc - * - * To build a relation descriptor, we have to allocate space, - * open the underlying unix file and initialize the following - * fields: + * RelationBuildDesc + * + * To build a relation descriptor, we have to allocate space, + * open the underlying unix file and initialize the following + * fields: * - * File rd_fd; open file descriptor - * int rd_nblocks; number of blocks in rel - * it will be set in ambeginscan() - * uint16 rd_refcnt; reference count - * Form_pg_am rd_am; AM tuple - * Form_pg_class rd_rel; RELATION tuple - * Oid rd_id; relations's object id - * Pointer lockInfo; ptr. to misc. info. - * TupleDesc rd_att; tuple desciptor + * File rd_fd; open file descriptor + * int rd_nblocks; number of blocks in rel + * it will be set in ambeginscan() + * uint16 rd_refcnt; reference count + * Form_pg_am rd_am; AM tuple + * Form_pg_class rd_rel; RELATION tuple + * Oid rd_id; relations's object id + * Pointer lockInfo; ptr. to misc. info. + * TupleDesc rd_att; tuple desciptor * - * Note: rd_ismem (rel is in-memory only) is currently unused - * by any part of the system. someday this will indicate that - * the relation lives only in the main-memory buffer pool - * -cim 2/4/91 + * Note: rd_ismem (rel is in-memory only) is currently unused + * by any part of the system. someday this will indicate that + * the relation lives only in the main-memory buffer pool + * -cim 2/4/91 * -------------------------------- */ -static Relation +static Relation RelationBuildDesc(RelationBuildDescInfo buildinfo) { - File fd; - Relation relation; - u_int natts; - Oid relid; - Oid relam; - Form_pg_class relp; - - MemoryContext oldcxt; - - HeapTuple pg_class_tuple; - - oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); - - /* ---------------- - * find the tuple in pg_class corresponding to the given relation id - * ---------------- - */ - pg_class_tuple = ScanPgRelation(buildinfo); - - /* ---------------- - * if no such tuple exists, return NULL - * ---------------- - */ - if (! HeapTupleIsValid(pg_class_tuple)) { - - MemoryContextSwitchTo(oldcxt); - - return NULL; - } - - /* ---------------- - * get information from the pg_class_tuple - * ---------------- - */ - relid = pg_class_tuple->t_oid; - relp = (Form_pg_class) GETSTRUCT(pg_class_tuple); - natts = relp->relnatts; - - /* ---------------- - * allocate storage for the relation descriptor, - * initialize relation->rd_rel and get the access method id. - * ---------------- - */ - relation = AllocateRelationDesc(natts, relp); - relam = relation->rd_rel->relam; - - /* ---------------- - * initialize the relation's relation id (relation->rd_id) - * ---------------- - */ - relation->rd_id = relid; - - /* ---------------- - * initialize relation->rd_refcnt - * ---------------- - */ - RelationSetReferenceCount(relation, 1); - - /* ---------------- - * normal relations are not nailed into the cache - * ---------------- - */ - relation->rd_isnailed = false; - - /* ---------------- - * initialize the access method information (relation->rd_am) - * ---------------- - */ - if (OidIsValid(relam)) { - relation->rd_am = (Form_pg_am) - AccessMethodObjectIdGetAccessMethodTupleForm(relam); - } - - /* ---------------- - * initialize the tuple descriptor (relation->rd_att). - * remember, rd_att is an array of attribute pointers that lives - * off the end of the relation descriptor structure so space was - * already allocated for it by AllocateRelationDesc. - * ---------------- - */ - RelationBuildTupleDesc(buildinfo, relation, natts); - - /* ---------------- - * initialize rules that affect this relation - * ---------------- - */ - if (relp->relhasrules) { - RelationBuildRuleLock(relation); - } else { - relation->rd_rules = NULL; - } - - /* Triggers */ - if ( relp->reltriggers > 0 ) - RelationBuildTriggers (relation); - else - relation->trigdesc = NULL; - - /* ---------------- - * initialize index strategy and support information for this relation - * ---------------- - */ - if (OidIsValid(relam)) { - IndexedAccessMethodInitialize(relation); - } - - /* ---------------- - * initialize the relation lock manager information - * ---------------- - */ - RelationInitLockInfo(relation); /* see lmgr.c */ - - /* ---------------- - * open the relation and assign the file descriptor returned - * by the storage manager code to rd_fd. - * ---------------- - */ - fd = smgropen(relp->relsmgr, relation); - - Assert (fd >= -1); - if (fd == -1) - elog(NOTICE, "RelationIdBuildRelation: smgropen(%s): %m", - &relp->relname); - - relation->rd_fd = fd; - - /* ---------------- - * insert newly created relation into proper relcaches, - * restore memory context and return the new reldesc. - * ---------------- - */ - - RelationCacheInsert(relation); - - /* ------------------- - * free the memory allocated for pg_class_tuple - * and for lock data pointed to by pg_class_tuple - * ------------------- - */ - pfree(pg_class_tuple); - - MemoryContextSwitchTo(oldcxt); - - return relation; + File fd; + Relation relation; + u_int natts; + Oid relid; + Oid relam; + Form_pg_class relp; + + MemoryContext oldcxt; + + HeapTuple pg_class_tuple; + + oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); + + /* ---------------- + * find the tuple in pg_class corresponding to the given relation id + * ---------------- + */ + pg_class_tuple = ScanPgRelation(buildinfo); + + /* ---------------- + * if no such tuple exists, return NULL + * ---------------- + */ + if (!HeapTupleIsValid(pg_class_tuple)) + { + + MemoryContextSwitchTo(oldcxt); + + return NULL; + } + + /* ---------------- + * get information from the pg_class_tuple + * ---------------- + */ + relid = pg_class_tuple->t_oid; + relp = (Form_pg_class) GETSTRUCT(pg_class_tuple); + natts = relp->relnatts; + + /* ---------------- + * allocate storage for the relation descriptor, + * initialize relation->rd_rel and get the access method id. + * ---------------- + */ + relation = AllocateRelationDesc(natts, relp); + relam = relation->rd_rel->relam; + + /* ---------------- + * initialize the relation's relation id (relation->rd_id) + * ---------------- + */ + relation->rd_id = relid; + + /* ---------------- + * initialize relation->rd_refcnt + * ---------------- + */ + RelationSetReferenceCount(relation, 1); + + /* ---------------- + * normal relations are not nailed into the cache + * ---------------- + */ + relation->rd_isnailed = false; + + /* ---------------- + * initialize the access method information (relation->rd_am) + * ---------------- + */ + if (OidIsValid(relam)) + { + relation->rd_am = (Form_pg_am) + AccessMethodObjectIdGetAccessMethodTupleForm(relam); + } + + /* ---------------- + * initialize the tuple descriptor (relation->rd_att). + * remember, rd_att is an array of attribute pointers that lives + * off the end of the relation descriptor structure so space was + * already allocated for it by AllocateRelationDesc. + * ---------------- + */ + RelationBuildTupleDesc(buildinfo, relation, natts); + + /* ---------------- + * initialize rules that affect this relation + * ---------------- + */ + if (relp->relhasrules) + { + RelationBuildRuleLock(relation); + } + else + { + relation->rd_rules = NULL; + } + + /* Triggers */ + if (relp->reltriggers > 0) + RelationBuildTriggers(relation); + else + relation->trigdesc = NULL; + + /* ---------------- + * initialize index strategy and support information for this relation + * ---------------- + */ + if (OidIsValid(relam)) + { + IndexedAccessMethodInitialize(relation); + } + + /* ---------------- + * initialize the relation lock manager information + * ---------------- + */ + RelationInitLockInfo(relation); /* see lmgr.c */ + + /* ---------------- + * open the relation and assign the file descriptor returned + * by the storage manager code to rd_fd. + * ---------------- + */ + fd = smgropen(relp->relsmgr, relation); + + Assert(fd >= -1); + if (fd == -1) + elog(NOTICE, "RelationIdBuildRelation: smgropen(%s): %m", + &relp->relname); + + relation->rd_fd = fd; + + /* ---------------- + * insert newly created relation into proper relcaches, + * restore memory context and return the new reldesc. + * ---------------- + */ + + RelationCacheInsert(relation); + + /* ------------------- + * free the memory allocated for pg_class_tuple + * and for lock data pointed to by pg_class_tuple + * ------------------- + */ + pfree(pg_class_tuple); + + MemoryContextSwitchTo(oldcxt); + + return relation; } static void IndexedAccessMethodInitialize(Relation relation) { - IndexStrategy strategy; - RegProcedure *support; - int natts; - Size stratSize; - Size supportSize; - uint16 relamstrategies; - uint16 relamsupport; - - natts = relation->rd_rel->relnatts; - relamstrategies = relation->rd_am->amstrategies; - stratSize = AttributeNumberGetIndexStrategySize(natts, relamstrategies); - strategy = (IndexStrategy) palloc(stratSize); - relamsupport = relation->rd_am->amsupport; - - if (relamsupport > 0) { - supportSize = natts * (relamsupport * sizeof (RegProcedure)); - support = (RegProcedure *) palloc(supportSize); - } else { - support = (RegProcedure *) NULL; - } - - IndexSupportInitialize(strategy, support, - relation->rd_att->attrs[0]->attrelid, - relation->rd_rel->relam, - relamstrategies, relamsupport, natts); - - RelationSetIndexSupport(relation, strategy, support); + IndexStrategy strategy; + RegProcedure *support; + int natts; + Size stratSize; + Size supportSize; + uint16 relamstrategies; + uint16 relamsupport; + + natts = relation->rd_rel->relnatts; + relamstrategies = relation->rd_am->amstrategies; + stratSize = AttributeNumberGetIndexStrategySize(natts, relamstrategies); + strategy = (IndexStrategy) palloc(stratSize); + relamsupport = relation->rd_am->amsupport; + + if (relamsupport > 0) + { + supportSize = natts * (relamsupport * sizeof(RegProcedure)); + support = (RegProcedure *) palloc(supportSize); + } + else + { + support = (RegProcedure *) NULL; + } + + IndexSupportInitialize(strategy, support, + relation->rd_att->attrs[0]->attrelid, + relation->rd_rel->relam, + relamstrategies, relamsupport, natts); + + RelationSetIndexSupport(relation, strategy, support); } /* -------------------------------- - * formrdesc + * formrdesc * - * This is a special version of RelationBuildDesc() - * used by RelationInitialize() in initializing the - * relcache. The system relation descriptors built - * here are all nailed in the descriptor caches, for - * bootstrapping. + * This is a special version of RelationBuildDesc() + * used by RelationInitialize() in initializing the + * relcache. The system relation descriptors built + * here are all nailed in the descriptor caches, for + * bootstrapping. * -------------------------------- */ static void formrdesc(char *relationName, - u_int natts, - FormData_pg_attribute att[]) + u_int natts, + FormData_pg_attribute att[]) { - Relation relation; - Size len; - int i; - - /* ---------------- - * allocate new relation desc - * ---------------- - */ - len = sizeof (RelationData); - relation = (Relation) palloc(len); - memset((char *)relation, 0,len); - - /* ---------------- - * don't open the unix file yet.. - * ---------------- - */ - relation->rd_fd = -1; - - /* ---------------- - * initialize reference count - * ---------------- - */ - RelationSetReferenceCount(relation, 1); - - /* ---------------- - * initialize relation tuple form - * ---------------- - */ - relation->rd_rel = (Form_pg_class) - palloc((Size) (sizeof(*relation->rd_rel))); - memset(relation->rd_rel, 0, sizeof(FormData_pg_class)); - namestrcpy(&relation->rd_rel->relname, relationName); - - /* ---------------- - initialize attribute tuple form - */ - relation->rd_att = CreateTemplateTupleDesc(natts); - - /* - * For debugging purposes, it's important to distinguish between - * shared and non-shared relations, even at bootstrap time. There's - * code in the buffer manager that traces allocations that has to - * know about this. - */ - - if (IsSystemRelationName(relationName)) { - relation->rd_rel->relowner = 6; /* XXX use sym const */ - relation->rd_rel->relisshared = - IsSharedSystemRelationName(relationName); - } else { - relation->rd_rel->relowner = InvalidOid; /* XXX incorrect*/ - relation->rd_rel->relisshared = false; - } - - relation->rd_rel->relpages = 1; /* XXX */ - relation->rd_rel->reltuples = 1; /* XXX */ - relation->rd_rel->relkind = RELKIND_RELATION; - relation->rd_rel->relarch = 'n'; - relation->rd_rel->relnatts = (uint16) natts; - relation->rd_isnailed = true; - - /* ---------------- - * initialize tuple desc info - * ---------------- - */ - for (i = 0; i < natts; i++) { - relation->rd_att->attrs[i] = - (AttributeTupleForm)palloc(ATTRIBUTE_TUPLE_SIZE); - - memset((char *)relation->rd_att->attrs[i], 0, - ATTRIBUTE_TUPLE_SIZE); - memmove((char *)relation->rd_att->attrs[i], - (char *)&att[i], - ATTRIBUTE_TUPLE_SIZE); - } - - /* ---------------- - * initialize relation id - * ---------------- - */ - relation->rd_id = relation->rd_att->attrs[0]->attrelid; - - /* ---------------- - * add new reldesc to relcache - * ---------------- - */ - RelationCacheInsert(relation); - /* - * 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. - */ - relation->rd_rel->relhasindex = - CatalogHasIndex(relationName, relation->rd_id); + Relation relation; + Size len; + int i; + + /* ---------------- + * allocate new relation desc + * ---------------- + */ + len = sizeof(RelationData); + relation = (Relation) palloc(len); + memset((char *) relation, 0, len); + + /* ---------------- + * don't open the unix file yet.. + * ---------------- + */ + relation->rd_fd = -1; + + /* ---------------- + * initialize reference count + * ---------------- + */ + RelationSetReferenceCount(relation, 1); + + /* ---------------- + * initialize relation tuple form + * ---------------- + */ + relation->rd_rel = (Form_pg_class) + palloc((Size) (sizeof(*relation->rd_rel))); + memset(relation->rd_rel, 0, sizeof(FormData_pg_class)); + namestrcpy(&relation->rd_rel->relname, relationName); + + /* ---------------- + initialize attribute tuple form + */ + relation->rd_att = CreateTemplateTupleDesc(natts); + + /* + * For debugging purposes, it's important to distinguish between + * shared and non-shared relations, even at bootstrap time. There's + * code in the buffer manager that traces allocations that has to know + * about this. + */ + + if (IsSystemRelationName(relationName)) + { + relation->rd_rel->relowner = 6; /* XXX use sym const */ + relation->rd_rel->relisshared = + IsSharedSystemRelationName(relationName); + } + else + { + relation->rd_rel->relowner = InvalidOid; /* XXX incorrect */ + relation->rd_rel->relisshared = false; + } + + relation->rd_rel->relpages = 1; /* XXX */ + relation->rd_rel->reltuples = 1; /* XXX */ + relation->rd_rel->relkind = RELKIND_RELATION; + relation->rd_rel->relarch = 'n'; + relation->rd_rel->relnatts = (uint16) natts; + relation->rd_isnailed = true; + + /* ---------------- + * initialize tuple desc info + * ---------------- + */ + for (i = 0; i < natts; i++) + { + relation->rd_att->attrs[i] = + (AttributeTupleForm) palloc(ATTRIBUTE_TUPLE_SIZE); + + memset((char *) relation->rd_att->attrs[i], 0, + ATTRIBUTE_TUPLE_SIZE); + memmove((char *) relation->rd_att->attrs[i], + (char *) &att[i], + ATTRIBUTE_TUPLE_SIZE); + } + + /* ---------------- + * initialize relation id + * ---------------- + */ + relation->rd_id = relation->rd_att->attrs[0]->attrelid; + + /* ---------------- + * add new reldesc to relcache + * ---------------- + */ + RelationCacheInsert(relation); + + /* + * 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. + */ + relation->rd_rel->relhasindex = + CatalogHasIndex(relationName, relation->rd_id); } /* ---------------------------------------------------------------- - * Relation Descriptor Lookup Interface + * Relation Descriptor Lookup Interface * ---------------------------------------------------------------- */ /* -------------------------------- - * RelationIdCacheGetRelation + * RelationIdCacheGetRelation * - * only try to get the reldesc by looking up the cache - * do not go to the disk. this is used by BlockPrepareFile() - * and RelationIdGetRelation below. + * only try to get the reldesc by looking up the cache + * do not go to the disk. this is used by BlockPrepareFile() + * and RelationIdGetRelation below. * -------------------------------- */ Relation RelationIdCacheGetRelation(Oid relationId) { - Relation rd; - - RelationIdCacheLookup(relationId, rd); - - if (RelationIsValid(rd)) { - if (rd->rd_fd == -1) { - rd->rd_fd = smgropen(rd->rd_rel->relsmgr, rd); - Assert(rd->rd_fd != -1); + Relation rd; + + RelationIdCacheLookup(relationId, rd); + + if (RelationIsValid(rd)) + { + if (rd->rd_fd == -1) + { + rd->rd_fd = smgropen(rd->rd_rel->relsmgr, rd); + Assert(rd->rd_fd != -1); + } + + RelationIncrementReferenceCount(rd); + RelationSetLockForDescriptorOpen(rd); + } - - RelationIncrementReferenceCount(rd); - RelationSetLockForDescriptorOpen(rd); - - } - - return(rd); + + return (rd); } /* -------------------------------- - * RelationNameCacheGetRelation + * RelationNameCacheGetRelation * -------------------------------- */ -static Relation +static Relation RelationNameCacheGetRelation(char *relationName) { - Relation rd; - NameData name; - - /* make sure that the name key used for hash lookup is properly - null-padded */ - namestrcpy(&name, relationName); - RelationNameCacheLookup(name.data, rd); - - if (RelationIsValid(rd)) { - if (rd->rd_fd == -1) { - rd->rd_fd = smgropen(rd->rd_rel->relsmgr, rd); - Assert(rd->rd_fd != -1); + Relation rd; + NameData name; + + /* + * make sure that the name key used for hash lookup is properly + * null-padded + */ + namestrcpy(&name, relationName); + RelationNameCacheLookup(name.data, rd); + + if (RelationIsValid(rd)) + { + if (rd->rd_fd == -1) + { + rd->rd_fd = smgropen(rd->rd_rel->relsmgr, rd); + Assert(rd->rd_fd != -1); + } + + RelationIncrementReferenceCount(rd); + RelationSetLockForDescriptorOpen(rd); + } - - RelationIncrementReferenceCount(rd); - RelationSetLockForDescriptorOpen(rd); - - } - - return(rd); + + return (rd); } /* -------------------------------- - * RelationIdGetRelation + * RelationIdGetRelation * - * return a relation descriptor based on its id. - * return a cached value if possible + * return a relation descriptor based on its id. + * return a cached value if possible * -------------------------------- */ Relation RelationIdGetRelation(Oid relationId) { - Relation rd; - RelationBuildDescInfo buildinfo; - - /* ---------------- - * increment access statistics - * ---------------- - */ - IncrHeapAccessStat(local_RelationIdGetRelation); - IncrHeapAccessStat(global_RelationIdGetRelation); - - /* ---------------- - * first try and get a reldesc from the cache - * ---------------- - */ - rd = RelationIdCacheGetRelation(relationId); - if (RelationIsValid(rd)) - return rd; - - /* ---------------- - * no reldesc in the cache, so have RelationBuildDesc() - * build one and add it. - * ---------------- - */ - buildinfo.infotype = INFO_RELID; - buildinfo.i.info_id = relationId; - - rd = RelationBuildDesc(buildinfo); - return - rd; + Relation rd; + RelationBuildDescInfo buildinfo; + + /* ---------------- + * increment access statistics + * ---------------- + */ + IncrHeapAccessStat(local_RelationIdGetRelation); + IncrHeapAccessStat(global_RelationIdGetRelation); + + /* ---------------- + * first try and get a reldesc from the cache + * ---------------- + */ + rd = RelationIdCacheGetRelation(relationId); + if (RelationIsValid(rd)) + return rd; + + /* ---------------- + * no reldesc in the cache, so have RelationBuildDesc() + * build one and add it. + * ---------------- + */ + buildinfo.infotype = INFO_RELID; + buildinfo.i.info_id = relationId; + + rd = RelationBuildDesc(buildinfo); + return + rd; } /* -------------------------------- - * RelationNameGetRelation + * RelationNameGetRelation * - * return a relation descriptor based on its name. - * return a cached value if possible + * return a relation descriptor based on its name. + * return a cached value if possible * -------------------------------- */ Relation RelationNameGetRelation(char *relationName) { - Relation rd; - RelationBuildDescInfo buildinfo; - - /* ---------------- - * increment access statistics - * ---------------- - */ - IncrHeapAccessStat(local_RelationNameGetRelation); - IncrHeapAccessStat(global_RelationNameGetRelation); - - /* ---------------- - * first try and get a reldesc from the cache - * ---------------- - */ - rd = RelationNameCacheGetRelation(relationName); - if (RelationIsValid(rd)) + Relation rd; + RelationBuildDescInfo buildinfo; + + /* ---------------- + * increment access statistics + * ---------------- + */ + IncrHeapAccessStat(local_RelationNameGetRelation); + IncrHeapAccessStat(global_RelationNameGetRelation); + + /* ---------------- + * first try and get a reldesc from the cache + * ---------------- + */ + rd = RelationNameCacheGetRelation(relationName); + if (RelationIsValid(rd)) + return rd; + + /* ---------------- + * no reldesc in the cache, so have RelationBuildDesc() + * build one and add it. + * ---------------- + */ + buildinfo.infotype = INFO_RELNAME; + buildinfo.i.info_name = relationName; + + rd = RelationBuildDesc(buildinfo); return rd; - - /* ---------------- - * no reldesc in the cache, so have RelationBuildDesc() - * build one and add it. - * ---------------- - */ - buildinfo.infotype = INFO_RELNAME; - buildinfo.i.info_name = relationName; - - rd = RelationBuildDesc(buildinfo); - return rd; } /* ---------------- - * old "getreldesc" interface. + * old "getreldesc" interface. * ---------------- */ #ifdef NOT_USED Relation getreldesc(char *relationName) { - /* ---------------- - * increment access statistics - * ---------------- - */ - IncrHeapAccessStat(local_getreldesc); - IncrHeapAccessStat(global_getreldesc); - - return RelationNameGetRelation(relationName); + /* ---------------- + * increment access statistics + * ---------------- + */ + IncrHeapAccessStat(local_getreldesc); + IncrHeapAccessStat(global_getreldesc); + + return RelationNameGetRelation(relationName); } + #endif /* ---------------------------------------------------------------- - * cache invalidation support routines + * cache invalidation support routines * ---------------------------------------------------------------- */ /* -------------------------------- - * RelationClose - close an open relation + * RelationClose - close an open relation * -------------------------------- */ void RelationClose(Relation relation) { - /* Note: no locking manipulations needed */ - RelationDecrementReferenceCount(relation); + /* Note: no locking manipulations needed */ + RelationDecrementReferenceCount(relation); } /* -------------------------------- * RelationFlushRelation * - * Actually blows away a relation... RelationFree doesn't do - * anything anymore. + * Actually blows away a relation... RelationFree doesn't do + * anything anymore. * -------------------------------- */ static void -RelationFlushRelation(Relation *relationPtr, - bool onlyFlushReferenceCountZero) +RelationFlushRelation(Relation * relationPtr, + bool onlyFlushReferenceCountZero) { - MemoryContext oldcxt; - Relation relation = *relationPtr; - - if (relation->rd_isnailed) { - /* this is a nailed special relation for bootstraping */ - return; - } - - if (!onlyFlushReferenceCountZero || - RelationHasReferenceCountZero(relation)) { - - oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); - - RelationCacheDelete(relation); - - FreeTupleDesc (relation->rd_att); - - FreeTriggerDesc (relation); + MemoryContext oldcxt; + Relation relation = *relationPtr; -#if 0 - if (relation->rd_rules) { - int j; - for(j=0; j < relation->rd_rules->numLocks; j++) { - pfree(relation->rd_rules->rules[j]); - } - pfree(relation->rd_rules->rules); - pfree(relation->rd_rules); + if (relation->rd_isnailed) + { + /* this is a nailed special relation for bootstraping */ + return; } + + if (!onlyFlushReferenceCountZero || + RelationHasReferenceCountZero(relation)) + { + + oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); + + RelationCacheDelete(relation); + + FreeTupleDesc(relation->rd_att); + + FreeTriggerDesc(relation); + +#if 0 + if (relation->rd_rules) + { + int j; + + for (j = 0; j < relation->rd_rules->numLocks; j++) + { + pfree(relation->rd_rules->rules[j]); + } + pfree(relation->rd_rules->rules); + pfree(relation->rd_rules); + } #endif - - pfree(RelationGetLockInfo(relation)); - pfree(RelationGetRelationTupleForm(relation)); - pfree(relation); - - MemoryContextSwitchTo(oldcxt); - } + + pfree(RelationGetLockInfo(relation)); + pfree(RelationGetRelationTupleForm(relation)); + pfree(relation); + + MemoryContextSwitchTo(oldcxt); + } } /* -------------------------------- - * RelationForgetRelation - - * RelationFlushRelation + if the relation is local then get rid of - * the relation descriptor from the newly created relation list. + * RelationForgetRelation - + * RelationFlushRelation + if the relation is local then get rid of + * the relation descriptor from the newly created relation list. * -------------------------------- */ void -RelationForgetRelation (Oid rid) +RelationForgetRelation(Oid rid) { - Relation relation; - - RelationIdCacheLookup (rid, relation); - Assert ( PointerIsValid (relation) ); - - if ( relation->rd_islocal ) - { - MemoryContext oldcxt; - List *curr; - List *prev = NIL; - - oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); - - foreach (curr, newlyCreatedRelns) - { - Relation reln = lfirst(curr); - - Assert ( reln != NULL && reln->rd_islocal ); - if ( reln->rd_id == rid ) - break; - prev = curr; - } - if ( curr == NIL ) - elog (FATAL, "Local relation %s not found in list", - (RelationGetRelationName(relation))->data); - if ( prev == NIL ) - newlyCreatedRelns = lnext (newlyCreatedRelns); - else - lnext (prev) = lnext (curr); - pfree (curr); - MemoryContextSwitchTo(oldcxt); - } - - RelationFlushRelation (&relation, false); + Relation relation; + + RelationIdCacheLookup(rid, relation); + Assert(PointerIsValid(relation)); + + if (relation->rd_islocal) + { + MemoryContext oldcxt; + List *curr; + List *prev = NIL; + + oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); + + foreach(curr, newlyCreatedRelns) + { + Relation reln = lfirst(curr); + + Assert(reln != NULL && reln->rd_islocal); + if (reln->rd_id == rid) + break; + prev = curr; + } + if (curr == NIL) + elog(FATAL, "Local relation %s not found in list", + (RelationGetRelationName(relation))->data); + if (prev == NIL) + newlyCreatedRelns = lnext(newlyCreatedRelns); + else + lnext(prev) = lnext(curr); + pfree(curr); + MemoryContextSwitchTo(oldcxt); + } + + RelationFlushRelation(&relation, false); } /* -------------------------------- - * RelationIdInvalidateRelationCacheByRelationId + * RelationIdInvalidateRelationCacheByRelationId * -------------------------------- */ void RelationIdInvalidateRelationCacheByRelationId(Oid relationId) { - Relation relation; - - RelationIdCacheLookup(relationId, relation); - - /* - * "local" relations are invalidated by RelationPurgeLocalRelation. - * (This is to make LocalBufferSync's life easier: want the descriptor - * to hang around for a while. In fact, won't we want this for - * BufferSync also? But I'll leave it for now since I don't want to - * break anything.) - ay 3/95 - */ - if (PointerIsValid(relation) && !relation->rd_islocal) { + Relation relation; + + RelationIdCacheLookup(relationId, relation); + /* - * The boolean onlyFlushReferenceCountZero in RelationFlushReln() - * should be set to true when we are incrementing the command - * counter and to false when we are starting a new xaction. This - * can be determined by checking the current xaction status. + * "local" relations are invalidated by RelationPurgeLocalRelation. + * (This is to make LocalBufferSync's life easier: want the descriptor + * to hang around for a while. In fact, won't we want this for + * BufferSync also? But I'll leave it for now since I don't want to + * break anything.) - ay 3/95 */ - RelationFlushRelation(&relation, CurrentXactInProgress()); - } + if (PointerIsValid(relation) && !relation->rd_islocal) + { + + /* + * The boolean onlyFlushReferenceCountZero in RelationFlushReln() + * should be set to true when we are incrementing the command + * counter and to false when we are starting a new xaction. This + * can be determined by checking the current xaction status. + */ + RelationFlushRelation(&relation, CurrentXactInProgress()); + } } -#if NOT_USED /* See comments at line 1304 */ +#if NOT_USED /* See comments at line 1304 */ /* -------------------------------- - * RelationIdInvalidateRelationCacheByAccessMethodId + * RelationIdInvalidateRelationCacheByAccessMethodId * - * RelationFlushIndexes is needed for use with HashTableWalk.. + * RelationFlushIndexes is needed for use with HashTableWalk.. * -------------------------------- */ static void -RelationFlushIndexes(Relation *r, - Oid accessMethodId) +RelationFlushIndexes(Relation * r, + Oid accessMethodId) { - Relation relation = *r; - - if (!RelationIsValid(relation)) { - elog(NOTICE, "inval call to RFI"); - return; - } - - if (relation->rd_rel->relkind == RELKIND_INDEX && /* XXX style */ - (!OidIsValid(accessMethodId) || - relation->rd_rel->relam == accessMethodId)) + Relation relation = *r; + + if (!RelationIsValid(relation)) + { + elog(NOTICE, "inval call to RFI"); + return; + } + + if (relation->rd_rel->relkind == RELKIND_INDEX && /* XXX style */ + (!OidIsValid(accessMethodId) || + relation->rd_rel->relam == accessMethodId)) { - RelationFlushRelation(&relation, false); + RelationFlushRelation(&relation, false); } } + #endif void RelationIdInvalidateRelationCacheByAccessMethodId(Oid accessMethodId) { -# if 0 - /* - * 25 aug 1992: mao commented out the ht walk below. it should be - * doing the right thing, in theory, but flushing reldescs for index - * relations apparently doesn't work. we want to cut 4.0.1, and i - * don't want to introduce new bugs. this code never executed before, - * so i'm turning it off for now. after the release is cut, i'll - * fix this up. - */ - - HashTableWalk(RelationNameCache, (HashtFunc) RelationFlushIndexes, - accessMethodId); -# else - return; -# endif +#if 0 + + /* + * 25 aug 1992: mao commented out the ht walk below. it should be + * doing the right thing, in theory, but flushing reldescs for index + * relations apparently doesn't work. we want to cut 4.0.1, and i + * don't want to introduce new bugs. this code never executed before, + * so i'm turning it off for now. after the release is cut, i'll fix + * this up. + */ + + HashTableWalk(RelationNameCache, (HashtFunc) RelationFlushIndexes, + accessMethodId); +#else + return; +#endif } /* * RelationCacheInvalidate * - * Will blow away either all the cached relation descriptors or - * those that have a zero reference count. + * Will blow away either all the cached relation descriptors or + * those that have a zero reference count. * */ void RelationCacheInvalidate(bool onlyFlushReferenceCountZero) { - HashTableWalk(RelationNameCache, (HashtFunc) RelationFlushRelation, - onlyFlushReferenceCountZero); - - /* - * nailed-in reldescs will still be in the cache... - * 7 hardwired heaps + 3 hardwired indices == 10 total. - */ - if (!onlyFlushReferenceCountZero) { - Assert(RelationNameCache->hctl->nkeys == 10); - Assert(RelationIdCache->hctl->nkeys == 10); - } + HashTableWalk(RelationNameCache, (HashtFunc) RelationFlushRelation, + onlyFlushReferenceCountZero); + + /* + * nailed-in reldescs will still be in the cache... 7 hardwired heaps + * + 3 hardwired indices == 10 total. + */ + if (!onlyFlushReferenceCountZero) + { + Assert(RelationNameCache->hctl->nkeys == 10); + Assert(RelationIdCache->hctl->nkeys == 10); + } } - + /* -------------------------------- - * RelationRegisterRelation - - * register the Relation descriptor of a newly created relation - * with the relation descriptor Cache. + * RelationRegisterRelation - + * register the Relation descriptor of a newly created relation + * with the relation descriptor Cache. * -------------------------------- */ void RelationRegisterRelation(Relation relation) { - MemoryContext oldcxt; - - oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); - - if (oldcxt != (MemoryContext)CacheCxt) - elog(NOIND,"RelationRegisterRelation: WARNING: Context != CacheCxt"); - - RelationCacheInsert(relation); - - RelationInitLockInfo(relation); - - /* - * we've just created the relation. It is invisible to anyone else - * before the transaction is committed. Setting rd_islocal allows us - * to use the local buffer manager for select/insert/etc before the end - * of transaction. (We also need to keep track of relations - * created during a transaction and does the necessary clean up at - * the end of the transaction.) - ay 3/95 - */ - relation->rd_islocal = TRUE; - newlyCreatedRelns = lcons(relation, newlyCreatedRelns); - - MemoryContextSwitchTo(oldcxt); + MemoryContext oldcxt; + + oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); + + if (oldcxt != (MemoryContext) CacheCxt) + elog(NOIND, "RelationRegisterRelation: WARNING: Context != CacheCxt"); + + RelationCacheInsert(relation); + + RelationInitLockInfo(relation); + + /* + * we've just created the relation. It is invisible to anyone else + * before the transaction is committed. Setting rd_islocal allows us + * to use the local buffer manager for select/insert/etc before the + * end of transaction. (We also need to keep track of relations + * created during a transaction and does the necessary clean up at the + * end of the transaction.) - ay 3/95 + */ + relation->rd_islocal = TRUE; + newlyCreatedRelns = lcons(relation, newlyCreatedRelns); + + MemoryContextSwitchTo(oldcxt); } /* * RelationPurgeLocalRelation - - * find all the Relation descriptors marked rd_islocal and reset them. - * This should be called at the end of a transaction (commit/abort) when - * the "local" relations will become visible to others and the multi-user - * buffer pool should be used. + * find all the Relation descriptors marked rd_islocal and reset them. + * This should be called at the end of a transaction (commit/abort) when + * the "local" relations will become visible to others and the multi-user + * buffer pool should be used. */ void RelationPurgeLocalRelation(bool xactCommitted) { - MemoryContext oldcxt; - - if (newlyCreatedRelns==NULL) - return; - - oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); - - while (newlyCreatedRelns) { - List *l = newlyCreatedRelns; - Relation reln = lfirst(l); - - Assert(reln!=NULL && reln->rd_islocal); - - if (!xactCommitted) { - /* - * remove the file if we abort. This is so that files for - * tables created inside a transaction block get removed. - */ - if(reln->rd_istemp) { - if(!(reln->rd_tmpunlinked)) { - smgrunlink(reln->rd_rel->relsmgr, reln); - reln->rd_tmpunlinked = TRUE; - } - } else { - smgrunlink(reln->rd_rel->relsmgr, reln); - } - } - else if ( !IsBootstrapProcessingMode () && !(reln->rd_istemp) ) - /* - * RelationFlushRelation () below will flush relation information - * from the cache. We must call smgrclose to flush relation - * information from SMGR & FMGR, too. We assume that for temp - * relations smgrunlink is already called by heap_destroyr - * and we skip smgrclose for them. - vadim 05/22/97 - */ - smgrclose(reln->rd_rel->relsmgr, reln); - - reln->rd_islocal = FALSE; + MemoryContext oldcxt; - if (!IsBootstrapProcessingMode()) - RelationFlushRelation(&reln, FALSE); - - newlyCreatedRelns = lnext(newlyCreatedRelns); - pfree(l); - } + if (newlyCreatedRelns == NULL) + return; + + oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); - MemoryContextSwitchTo(oldcxt); + while (newlyCreatedRelns) + { + List *l = newlyCreatedRelns; + Relation reln = lfirst(l); + + Assert(reln != NULL && reln->rd_islocal); + + if (!xactCommitted) + { + + /* + * remove the file if we abort. This is so that files for + * tables created inside a transaction block get removed. + */ + if (reln->rd_istemp) + { + if (!(reln->rd_tmpunlinked)) + { + smgrunlink(reln->rd_rel->relsmgr, reln); + reln->rd_tmpunlinked = TRUE; + } + } + else + { + smgrunlink(reln->rd_rel->relsmgr, reln); + } + } + else if (!IsBootstrapProcessingMode() && !(reln->rd_istemp)) + + /* + * RelationFlushRelation () below will flush relation + * information from the cache. We must call smgrclose to flush + * relation information from SMGR & FMGR, too. We assume that + * for temp relations smgrunlink is already called by + * heap_destroyr and we skip smgrclose for them. - + * vadim 05/22/97 + */ + smgrclose(reln->rd_rel->relsmgr, reln); + + reln->rd_islocal = FALSE; + + if (!IsBootstrapProcessingMode()) + RelationFlushRelation(&reln, FALSE); + + newlyCreatedRelns = lnext(newlyCreatedRelns); + pfree(l); + } + + MemoryContextSwitchTo(oldcxt); } /* -------------------------------- - * RelationInitialize + * RelationInitialize * - * This initializes the relation descriptor cache. + * This initializes the relation descriptor cache. * -------------------------------- */ -#define INITRELCACHESIZE 400 +#define INITRELCACHESIZE 400 void RelationInitialize(void) { - MemoryContext oldcxt; - HASHCTL ctl; - - /* ---------------- - * switch to cache memory context - * ---------------- - */ - if (!CacheCxt) - CacheCxt = CreateGlobalMemory("Cache"); - - oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); - - /* ---------------- - * create global caches - * ---------------- - */ - memset(&ctl,0, (int) sizeof(ctl)); - ctl.keysize = sizeof(NameData); - ctl.datasize = sizeof(Relation); - RelationNameCache = hash_create(INITRELCACHESIZE, &ctl, HASH_ELEM); - - ctl.keysize = sizeof(Oid); - ctl.hash = tag_hash; - RelationIdCache = hash_create(INITRELCACHESIZE, &ctl, - HASH_ELEM | HASH_FUNCTION); - - /* ---------------- - * initialize the cache with pre-made relation descriptors - * for some of the more important system relations. These - * relations should always be in the cache. - * ---------------- - */ - formrdesc(RelationRelationName, Natts_pg_class, Desc_pg_class); - formrdesc(AttributeRelationName, Natts_pg_attribute, Desc_pg_attribute); - formrdesc(ProcedureRelationName, Natts_pg_proc, Desc_pg_proc); - formrdesc(TypeRelationName, Natts_pg_type, Desc_pg_type); - formrdesc(VariableRelationName, Natts_pg_variable, Desc_pg_variable); - formrdesc(LogRelationName, Natts_pg_log, Desc_pg_log); - formrdesc(TimeRelationName, Natts_pg_time, Desc_pg_time); - - /* - * If this isn't initdb time, then we want to initialize some index - * relation descriptors, as well. The descriptors are for pg_attnumind - * (to make building relation descriptors fast) and possibly others, - * as they're added. - */ - - if (!IsBootstrapProcessingMode()) - init_irels(); - - MemoryContextSwitchTo(oldcxt); + MemoryContext oldcxt; + HASHCTL ctl; + + /* ---------------- + * switch to cache memory context + * ---------------- + */ + if (!CacheCxt) + CacheCxt = CreateGlobalMemory("Cache"); + + oldcxt = MemoryContextSwitchTo((MemoryContext) CacheCxt); + + /* ---------------- + * create global caches + * ---------------- + */ + memset(&ctl, 0, (int) sizeof(ctl)); + ctl.keysize = sizeof(NameData); + ctl.datasize = sizeof(Relation); + RelationNameCache = hash_create(INITRELCACHESIZE, &ctl, HASH_ELEM); + + ctl.keysize = sizeof(Oid); + ctl.hash = tag_hash; + RelationIdCache = hash_create(INITRELCACHESIZE, &ctl, + HASH_ELEM | HASH_FUNCTION); + + /* ---------------- + * initialize the cache with pre-made relation descriptors + * for some of the more important system relations. These + * relations should always be in the cache. + * ---------------- + */ + formrdesc(RelationRelationName, Natts_pg_class, Desc_pg_class); + formrdesc(AttributeRelationName, Natts_pg_attribute, Desc_pg_attribute); + formrdesc(ProcedureRelationName, Natts_pg_proc, Desc_pg_proc); + formrdesc(TypeRelationName, Natts_pg_type, Desc_pg_type); + formrdesc(VariableRelationName, Natts_pg_variable, Desc_pg_variable); + formrdesc(LogRelationName, Natts_pg_log, Desc_pg_log); + formrdesc(TimeRelationName, Natts_pg_time, Desc_pg_time); + + /* + * If this isn't initdb time, then we want to initialize some index + * relation descriptors, as well. The descriptors are for + * pg_attnumind (to make building relation descriptors fast) and + * possibly others, as they're added. + */ + + if (!IsBootstrapProcessingMode()) + init_irels(); + + MemoryContextSwitchTo(oldcxt); } static void -AttrDefaultFetch (Relation relation) +AttrDefaultFetch(Relation relation) { - AttrDefault *attrdef = relation->rd_att->constr->defval; - int ndef = relation->rd_att->constr->num_defval; - Relation adrel; - Relation irel; - ScanKeyData skey; - HeapTuple tuple; - Form_pg_attrdef adform; - IndexScanDesc sd; - RetrieveIndexResult indexRes; - Buffer buffer; - ItemPointer iptr; - struct varlena *val; - bool isnull; - int found; - int i; - - ScanKeyEntryInitialize(&skey, - (bits16)0x0, - (AttrNumber)1, - (RegProcedure)ObjectIdEqualRegProcedure, - ObjectIdGetDatum(relation->rd_id)); - - adrel = heap_openr(AttrDefaultRelationName); - irel = index_openr(AttrDefaultIndex); - sd = index_beginscan(irel, false, 1, &skey); - tuple = (HeapTuple)NULL; - - for (found = 0; ; ) - { - indexRes = index_getnext(sd, ForwardScanDirection); - if (!indexRes) - break; - - iptr = &indexRes->heap_iptr; - tuple = heap_fetch(adrel, NowTimeQual, iptr, &buffer); - pfree(indexRes); - if (!HeapTupleIsValid(tuple)) - continue; - found++; - adform = (Form_pg_attrdef) GETSTRUCT(tuple); - for (i = 0; i < ndef; i++) - { - if ( adform->adnum != attrdef[i].adnum ) - continue; - if ( attrdef[i].adsrc != NULL ) - elog (WARN, "AttrDefaultFetch: second record found for attr %.*s in rel %.*s", - NAMEDATALEN, relation->rd_att->attrs[adform->adnum - 1]->attname.data, - NAMEDATALEN, relation->rd_rel->relname.data); - - val = (struct varlena*) fastgetattr (tuple, - Anum_pg_attrdef_adbin, - adrel->rd_att, &isnull); - if ( isnull ) - elog (WARN, "AttrDefaultFetch: adbin IS NULL for attr %.*s in rel %.*s", - NAMEDATALEN, relation->rd_att->attrs[adform->adnum - 1]->attname.data, - NAMEDATALEN, relation->rd_rel->relname.data); - attrdef[i].adbin = textout (val); - val = (struct varlena*) fastgetattr (tuple, - Anum_pg_attrdef_adsrc, - adrel->rd_att, &isnull); - if ( isnull ) - elog (WARN, "AttrDefaultFetch: adsrc IS NULL for attr %.*s in rel %.*s", - NAMEDATALEN, relation->rd_att->attrs[adform->adnum - 1]->attname.data, - NAMEDATALEN, relation->rd_rel->relname.data); - attrdef[i].adsrc = textout (val); - break; - } - - if ( i >= ndef ) - elog (WARN, "AttrDefaultFetch: unexpected record found for attr %d in rel %.*s", - adform->adnum, - NAMEDATALEN, relation->rd_rel->relname.data); - ReleaseBuffer(buffer); - } - - if ( found < ndef ) - elog (WARN, "AttrDefaultFetch: %d record not found for rel %.*s", - ndef - found, - NAMEDATALEN, relation->rd_rel->relname.data); - - index_endscan (sd); - pfree (sd); - index_close (irel); - heap_close (adrel); - + AttrDefault *attrdef = relation->rd_att->constr->defval; + int ndef = relation->rd_att->constr->num_defval; + Relation adrel; + Relation irel; + ScanKeyData skey; + HeapTuple tuple; + Form_pg_attrdef adform; + IndexScanDesc sd; + RetrieveIndexResult indexRes; + Buffer buffer; + ItemPointer iptr; + struct varlena *val; + bool isnull; + int found; + int i; + + ScanKeyEntryInitialize(&skey, + (bits16) 0x0, + (AttrNumber) 1, + (RegProcedure) ObjectIdEqualRegProcedure, + ObjectIdGetDatum(relation->rd_id)); + + adrel = heap_openr(AttrDefaultRelationName); + irel = index_openr(AttrDefaultIndex); + sd = index_beginscan(irel, false, 1, &skey); + tuple = (HeapTuple) NULL; + + for (found = 0;;) + { + indexRes = index_getnext(sd, ForwardScanDirection); + if (!indexRes) + break; + + iptr = &indexRes->heap_iptr; + tuple = heap_fetch(adrel, NowTimeQual, iptr, &buffer); + pfree(indexRes); + if (!HeapTupleIsValid(tuple)) + continue; + found++; + adform = (Form_pg_attrdef) GETSTRUCT(tuple); + for (i = 0; i < ndef; i++) + { + if (adform->adnum != attrdef[i].adnum) + continue; + if (attrdef[i].adsrc != NULL) + elog(WARN, "AttrDefaultFetch: second record found for attr %.*s in rel %.*s", + NAMEDATALEN, relation->rd_att->attrs[adform->adnum - 1]->attname.data, + NAMEDATALEN, relation->rd_rel->relname.data); + + val = (struct varlena *) fastgetattr(tuple, + Anum_pg_attrdef_adbin, + adrel->rd_att, &isnull); + if (isnull) + elog(WARN, "AttrDefaultFetch: adbin IS NULL for attr %.*s in rel %.*s", + NAMEDATALEN, relation->rd_att->attrs[adform->adnum - 1]->attname.data, + NAMEDATALEN, relation->rd_rel->relname.data); + attrdef[i].adbin = textout(val); + val = (struct varlena *) fastgetattr(tuple, + Anum_pg_attrdef_adsrc, + adrel->rd_att, &isnull); + if (isnull) + elog(WARN, "AttrDefaultFetch: adsrc IS NULL for attr %.*s in rel %.*s", + NAMEDATALEN, relation->rd_att->attrs[adform->adnum - 1]->attname.data, + NAMEDATALEN, relation->rd_rel->relname.data); + attrdef[i].adsrc = textout(val); + break; + } + + if (i >= ndef) + elog(WARN, "AttrDefaultFetch: unexpected record found for attr %d in rel %.*s", + adform->adnum, + NAMEDATALEN, relation->rd_rel->relname.data); + ReleaseBuffer(buffer); + } + + if (found < ndef) + elog(WARN, "AttrDefaultFetch: %d record not found for rel %.*s", + ndef - found, + NAMEDATALEN, relation->rd_rel->relname.data); + + index_endscan(sd); + pfree(sd); + index_close(irel); + heap_close(adrel); + } static void -RelCheckFetch (Relation relation) +RelCheckFetch(Relation relation) { - ConstrCheck *check = relation->rd_att->constr->check; - int ncheck = relation->rd_att->constr->num_check; - Relation rcrel; - Relation irel; - ScanKeyData skey; - HeapTuple tuple; - IndexScanDesc sd; - RetrieveIndexResult indexRes; - Buffer buffer; - ItemPointer iptr; - Name rcname; - struct varlena *val; - bool isnull; - int found; - - ScanKeyEntryInitialize(&skey, - (bits16)0x0, - (AttrNumber)1, - (RegProcedure)ObjectIdEqualRegProcedure, - ObjectIdGetDatum(relation->rd_id)); - - rcrel = heap_openr(RelCheckRelationName); - irel = index_openr(RelCheckIndex); - sd = index_beginscan(irel, false, 1, &skey); - tuple = (HeapTuple)NULL; - - for (found = 0; ; ) - { - indexRes = index_getnext(sd, ForwardScanDirection); - if (!indexRes) - break; - - iptr = &indexRes->heap_iptr; - tuple = heap_fetch(rcrel, NowTimeQual, iptr, &buffer); - pfree(indexRes); - if (!HeapTupleIsValid(tuple)) - continue; - if ( found == ncheck ) - elog (WARN, "RelCheckFetch: unexpected record found for rel %.*s", - NAMEDATALEN, relation->rd_rel->relname.data); - - rcname = (Name) fastgetattr (tuple, - Anum_pg_relcheck_rcname, - rcrel->rd_att, &isnull); - if ( isnull ) - elog (WARN, "RelCheckFetch: rcname IS NULL for rel %.*s", - NAMEDATALEN, relation->rd_rel->relname.data); - check[found].ccname = nameout (rcname); - val = (struct varlena*) fastgetattr (tuple, - Anum_pg_relcheck_rcbin, - rcrel->rd_att, &isnull); - if ( isnull ) - elog (WARN, "RelCheckFetch: rcbin IS NULL for rel %.*s", - NAMEDATALEN, relation->rd_rel->relname.data); - check[found].ccbin = textout (val); - val = (struct varlena*) fastgetattr (tuple, - Anum_pg_relcheck_rcsrc, - rcrel->rd_att, &isnull); - if ( isnull ) - elog (WARN, "RelCheckFetch: rcsrc IS NULL for rel %.*s", - NAMEDATALEN, relation->rd_rel->relname.data); - check[found].ccsrc = textout (val); - found++; - - ReleaseBuffer(buffer); - } - - if ( found < ncheck ) - elog (WARN, "RelCheckFetch: %d record not found for rel %.*s", - ncheck - found, - NAMEDATALEN, relation->rd_rel->relname.data); - - index_endscan (sd); - pfree (sd); - index_close (irel); - heap_close (rcrel); - + ConstrCheck *check = relation->rd_att->constr->check; + int ncheck = relation->rd_att->constr->num_check; + Relation rcrel; + Relation irel; + ScanKeyData skey; + HeapTuple tuple; + IndexScanDesc sd; + RetrieveIndexResult indexRes; + Buffer buffer; + ItemPointer iptr; + Name rcname; + struct varlena *val; + bool isnull; + int found; + + ScanKeyEntryInitialize(&skey, + (bits16) 0x0, + (AttrNumber) 1, + (RegProcedure) ObjectIdEqualRegProcedure, + ObjectIdGetDatum(relation->rd_id)); + + rcrel = heap_openr(RelCheckRelationName); + irel = index_openr(RelCheckIndex); + sd = index_beginscan(irel, false, 1, &skey); + tuple = (HeapTuple) NULL; + + for (found = 0;;) + { + indexRes = index_getnext(sd, ForwardScanDirection); + if (!indexRes) + break; + + iptr = &indexRes->heap_iptr; + tuple = heap_fetch(rcrel, NowTimeQual, iptr, &buffer); + pfree(indexRes); + if (!HeapTupleIsValid(tuple)) + continue; + if (found == ncheck) + elog(WARN, "RelCheckFetch: unexpected record found for rel %.*s", + NAMEDATALEN, relation->rd_rel->relname.data); + + rcname = (Name) fastgetattr(tuple, + Anum_pg_relcheck_rcname, + rcrel->rd_att, &isnull); + if (isnull) + elog(WARN, "RelCheckFetch: rcname IS NULL for rel %.*s", + NAMEDATALEN, relation->rd_rel->relname.data); + check[found].ccname = nameout(rcname); + val = (struct varlena *) fastgetattr(tuple, + Anum_pg_relcheck_rcbin, + rcrel->rd_att, &isnull); + if (isnull) + elog(WARN, "RelCheckFetch: rcbin IS NULL for rel %.*s", + NAMEDATALEN, relation->rd_rel->relname.data); + check[found].ccbin = textout(val); + val = (struct varlena *) fastgetattr(tuple, + Anum_pg_relcheck_rcsrc, + rcrel->rd_att, &isnull); + if (isnull) + elog(WARN, "RelCheckFetch: rcsrc IS NULL for rel %.*s", + NAMEDATALEN, relation->rd_rel->relname.data); + check[found].ccsrc = textout(val); + found++; + + ReleaseBuffer(buffer); + } + + if (found < ncheck) + elog(WARN, "RelCheckFetch: %d record not found for rel %.*s", + ncheck - found, + NAMEDATALEN, relation->rd_rel->relname.data); + + index_endscan(sd); + pfree(sd); + index_close(irel); + heap_close(rcrel); + } /* - * init_irels(), write_irels() -- handle special-case initialization of - * index relation descriptors. + * init_irels(), write_irels() -- handle special-case initialization of + * index relation descriptors. * - * In late 1992, we started regularly having databases with more than - * a thousand classes in them. With this number of classes, it became - * critical to do indexed lookups on the system catalogs. + * In late 1992, we started regularly having databases with more than + * a thousand classes in them. With this number of classes, it became + * critical to do indexed lookups on the system catalogs. * - * Bootstrapping these lookups is very hard. We want to be able to - * use an index on pg_attribute, for example, but in order to do so, - * we must have read pg_attribute for the attributes in the index, - * which implies that we need to use the index. + * Bootstrapping these lookups is very hard. We want to be able to + * use an index on pg_attribute, for example, but in order to do so, + * we must have read pg_attribute for the attributes in the index, + * which implies that we need to use the index. * - * In order to get around the problem, we do the following: + * In order to get around the problem, we do the following: * - * + When the database system is initialized (at initdb time), we - * don't use indices on pg_attribute. We do sequential scans. + * + When the database system is initialized (at initdb time), we + * don't use indices on pg_attribute. We do sequential scans. * - * + When the backend is started up in normal mode, we load an image - * of the appropriate relation descriptors, in internal format, - * from an initialization file in the data/base/... directory. + * + When the backend is started up in normal mode, we load an image + * of the appropriate relation descriptors, in internal format, + * from an initialization file in the data/base/... directory. * - * + If the initialization file isn't there, then we create the - * relation descriptor using sequential scans and write it to - * the initialization file for use by subsequent backends. + * + If the initialization file isn't there, then we create the + * relation descriptor using sequential scans and write it to + * the initialization file for use by subsequent backends. * - * This is complicated and interferes with system changes, but - * performance is so bad that we're willing to pay the tax. + * This is complicated and interferes with system changes, but + * performance is so bad that we're willing to pay the tax. */ /* pg_attnumind, pg_classnameind, pg_classoidind */ @@ -1833,268 +1902,288 @@ RelCheckFetch (Relation relation) static void init_irels(void) { - Size len; - int nread; - File fd; - Relation irel[Num_indices_bootstrap]; - Relation ird; - Form_pg_am am; - Form_pg_class relform; - IndexStrategy strat; - RegProcedure *support; - int i; - int relno; - - if ((fd = FileNameOpenFile(INIT_FILENAME, O_RDONLY, 0600)) < 0) { - write_irels(); - return; - } - - FileSeek(fd, 0L, SEEK_SET); - - for (relno = 0; relno < Num_indices_bootstrap; relno++) { - /* first read the relation descriptor length*/ - if ((nread = FileRead(fd, (char*)&len, sizeof(int))) != sizeof(int)) { - write_irels(); - return; - } - - ird = irel[relno] = (Relation) palloc(len); - memset(ird, 0, len); - - /* then, read the Relation structure */ - if ((nread = FileRead(fd, (char*)ird, len)) != len) { - write_irels(); - return; - } - - /* the file descriptor is not yet opened */ - ird->rd_fd = -1; - - /* lock info is not initialized */ - ird->lockInfo = (char *) NULL; - - /* next, read the access method tuple form */ - if ((nread = FileRead(fd, (char*)&len, sizeof(int))) != sizeof(int)) { - write_irels(); - return; - } - - am = (Form_pg_am) palloc(len); - if ((nread = FileRead(fd, (char*)am, len)) != len) { - write_irels(); - return; - } - - ird->rd_am = am; - - /* next read the relation tuple form */ - if ((nread = FileRead(fd, (char*)&len, sizeof(int))) != sizeof(int)) { - write_irels(); - return; - } - - relform = (Form_pg_class) palloc(len); - if ((nread = FileRead(fd, (char*)relform, len)) != len) { - write_irels(); - return; - } - - ird->rd_rel = relform; - - /* initialize attribute tuple forms */ - ird->rd_att = CreateTemplateTupleDesc(relform->relnatts); - - /* next read all the attribute tuple form data entries */ - len = ATTRIBUTE_TUPLE_SIZE; - for (i = 0; i < relform->relnatts; i++) { - if ((nread = FileRead(fd, (char*)&len, sizeof(int))) != sizeof(int)) { - write_irels(); - return; - } - - ird->rd_att->attrs[i] = (AttributeTupleForm) palloc(len); - - if ((nread = FileRead(fd, (char*)ird->rd_att->attrs[i], len)) != len) { + Size len; + int nread; + File fd; + Relation irel[Num_indices_bootstrap]; + Relation ird; + Form_pg_am am; + Form_pg_class relform; + IndexStrategy strat; + RegProcedure *support; + int i; + int relno; + + if ((fd = FileNameOpenFile(INIT_FILENAME, O_RDONLY, 0600)) < 0) + { write_irels(); return; - } - } - - /* next, read the index strategy map */ - if ((nread = FileRead(fd, (char*)&len, sizeof(int))) != sizeof(int)) { - write_irels(); - return; - } - - strat = (IndexStrategy) palloc(len); - if ((nread = FileRead(fd, (char*)strat, len)) != len) { - write_irels(); - return; } - - /* oh, for god's sake... */ + + FileSeek(fd, 0L, SEEK_SET); + + for (relno = 0; relno < Num_indices_bootstrap; relno++) + { + /* first read the relation descriptor length */ + if ((nread = FileRead(fd, (char *) &len, sizeof(int))) != sizeof(int)) + { + write_irels(); + return; + } + + ird = irel[relno] = (Relation) palloc(len); + memset(ird, 0, len); + + /* then, read the Relation structure */ + if ((nread = FileRead(fd, (char *) ird, len)) != len) + { + write_irels(); + return; + } + + /* the file descriptor is not yet opened */ + ird->rd_fd = -1; + + /* lock info is not initialized */ + ird->lockInfo = (char *) NULL; + + /* next, read the access method tuple form */ + if ((nread = FileRead(fd, (char *) &len, sizeof(int))) != sizeof(int)) + { + write_irels(); + return; + } + + am = (Form_pg_am) palloc(len); + if ((nread = FileRead(fd, (char *) am, len)) != len) + { + write_irels(); + return; + } + + ird->rd_am = am; + + /* next read the relation tuple form */ + if ((nread = FileRead(fd, (char *) &len, sizeof(int))) != sizeof(int)) + { + write_irels(); + return; + } + + relform = (Form_pg_class) palloc(len); + if ((nread = FileRead(fd, (char *) relform, len)) != len) + { + write_irels(); + return; + } + + ird->rd_rel = relform; + + /* initialize attribute tuple forms */ + ird->rd_att = CreateTemplateTupleDesc(relform->relnatts); + + /* next read all the attribute tuple form data entries */ + len = ATTRIBUTE_TUPLE_SIZE; + for (i = 0; i < relform->relnatts; i++) + { + if ((nread = FileRead(fd, (char *) &len, sizeof(int))) != sizeof(int)) + { + write_irels(); + return; + } + + ird->rd_att->attrs[i] = (AttributeTupleForm) palloc(len); + + if ((nread = FileRead(fd, (char *) ird->rd_att->attrs[i], len)) != len) + { + write_irels(); + return; + } + } + + /* next, read the index strategy map */ + if ((nread = FileRead(fd, (char *) &len, sizeof(int))) != sizeof(int)) + { + write_irels(); + return; + } + + strat = (IndexStrategy) palloc(len); + if ((nread = FileRead(fd, (char *) strat, len)) != len) + { + write_irels(); + return; + } + + /* oh, for god's sake... */ #define SMD(i) strat[0].strategyMapData[i].entry[0] - - /* have to reinit the function pointers in the strategy maps */ - for (i = 0; i < am->amstrategies; i++) - fmgr_info(SMD(i).sk_procedure, - &(SMD(i).sk_func), &(SMD(i).sk_nargs)); - - - /* use a real field called rd_istrat instead of the - bogosity of hanging invisible fields off the end of a structure - - jolly */ - ird->rd_istrat = strat; - - /* finally, read the vector of support procedures */ - if ((nread = FileRead(fd, (char*)&len, sizeof(int))) != sizeof(int)) { - write_irels(); - return; - } - - support = (RegProcedure *) palloc(len); - if ((nread = FileRead(fd, (char*)support, len)) != len) { - write_irels(); - return; - } - - /* - p += sizeof(IndexStrategy); - *((RegProcedure **) p) = support; - */ - ird->rd_support = support; - - RelationCacheInsert(ird); - } + /* have to reinit the function pointers in the strategy maps */ + for (i = 0; i < am->amstrategies; i++) + fmgr_info(SMD(i).sk_procedure, + &(SMD(i).sk_func), &(SMD(i).sk_nargs)); + + + /* + * use a real field called rd_istrat instead of the bogosity of + * hanging invisible fields off the end of a structure - jolly + */ + ird->rd_istrat = strat; + + /* finally, read the vector of support procedures */ + if ((nread = FileRead(fd, (char *) &len, sizeof(int))) != sizeof(int)) + { + write_irels(); + return; + } + + support = (RegProcedure *) palloc(len); + if ((nread = FileRead(fd, (char *) support, len)) != len) + { + write_irels(); + return; + } + + /* + * p += sizeof(IndexStrategy); ((RegProcedure **) p) = support; + */ + + ird->rd_support = support; + + RelationCacheInsert(ird); + } } static void write_irels(void) { - int len; - int nwritten; - File fd; - Relation irel[Num_indices_bootstrap]; - Relation ird; - Form_pg_am am; - Form_pg_class relform; - IndexStrategy strat; - RegProcedure *support; - ProcessingMode oldmode; - int i; - int relno; - RelationBuildDescInfo bi; - - fd = FileNameOpenFile(INIT_FILENAME, O_WRONLY|O_CREAT|O_TRUNC, 0600); - if (fd < 0) - elog(FATAL, "cannot create init file %s", INIT_FILENAME); - - FileSeek(fd, 0L, SEEK_SET); - - /* - * Build a relation descriptor for pg_attnumind without resort to the - * descriptor cache. In order to do this, we set ProcessingMode - * to Bootstrap. The effect of this is to disable indexed relation - * searches -- a necessary step, since we're trying to instantiate - * the index relation descriptors here. - */ - - oldmode = GetProcessingMode(); - SetProcessingMode(BootstrapProcessing); - - bi.infotype = INFO_RELNAME; - bi.i.info_name = AttributeNumIndex; - irel[0] = RelationBuildDesc(bi); - irel[0]->rd_isnailed = true; - - bi.i.info_name = ClassNameIndex; - irel[1] = RelationBuildDesc(bi); - irel[1]->rd_isnailed = true; - - bi.i.info_name = ClassOidIndex; - irel[2] = RelationBuildDesc(bi); - irel[2]->rd_isnailed = true; - - SetProcessingMode(oldmode); - - /* nail the descriptor in the cache */ - for (relno = 0; relno < Num_indices_bootstrap; relno++) { - ird = irel[relno]; - - /* save the volatile fields in the relation descriptor */ - am = ird->rd_am; - ird->rd_am = (Form_pg_am) NULL; - relform = ird->rd_rel; - ird->rd_rel = (Form_pg_class) NULL; - strat = ird->rd_istrat; - support = ird->rd_support; - - /* first write the relation descriptor , excluding strategy and support */ - len = sizeof(RelationData); - - /* first, write the relation descriptor length */ - if ((nwritten = FileWrite(fd, (char*) &len, sizeof(int))) - != sizeof(int)) - elog(FATAL, "cannot write init file -- descriptor length"); - - /* next, write out the Relation structure */ - if ((nwritten = FileWrite(fd, (char*) ird, len)) != len) - elog(FATAL, "cannot write init file -- reldesc"); - - /* next, write the access method tuple form */ - len = sizeof(FormData_pg_am); - if ((nwritten = FileWrite(fd, (char*) &len, sizeof(int))) - != sizeof(int)) - elog(FATAL, "cannot write init file -- am tuple form length"); - - if ((nwritten = FileWrite(fd, (char*) am, len)) != len) - elog(FATAL, "cannot write init file -- am tuple form"); - - /* next write the relation tuple form */ - len = sizeof(FormData_pg_class); - if ((nwritten = FileWrite(fd, (char*) &len, sizeof(int))) - != sizeof(int)) - elog(FATAL, "cannot write init file -- relation tuple form length"); - - if ((nwritten = FileWrite(fd, (char*) relform, len)) != len) - elog(FATAL, "cannot write init file -- relation tuple form"); - - /* next, do all the attribute tuple form data entries */ - len = ATTRIBUTE_TUPLE_SIZE; - for (i = 0; i < relform->relnatts; i++) { - if ((nwritten = FileWrite(fd, (char*) &len, sizeof(int))) - != sizeof(int)) - elog(FATAL, "cannot write init file -- length of attdesc %d", i); - if ((nwritten = FileWrite(fd, (char*) ird->rd_att->attrs[i], len)) - != len) - elog(FATAL, "cannot write init file -- attdesc %d", i); + int len; + int nwritten; + File fd; + Relation irel[Num_indices_bootstrap]; + Relation ird; + Form_pg_am am; + Form_pg_class relform; + IndexStrategy strat; + RegProcedure *support; + ProcessingMode oldmode; + int i; + int relno; + RelationBuildDescInfo bi; + + fd = FileNameOpenFile(INIT_FILENAME, O_WRONLY | O_CREAT | O_TRUNC, 0600); + if (fd < 0) + elog(FATAL, "cannot create init file %s", INIT_FILENAME); + + FileSeek(fd, 0L, SEEK_SET); + + /* + * Build a relation descriptor for pg_attnumind without resort to the + * descriptor cache. In order to do this, we set ProcessingMode to + * Bootstrap. The effect of this is to disable indexed relation + * searches -- a necessary step, since we're trying to instantiate the + * index relation descriptors here. + */ + + oldmode = GetProcessingMode(); + SetProcessingMode(BootstrapProcessing); + + bi.infotype = INFO_RELNAME; + bi.i.info_name = AttributeNumIndex; + irel[0] = RelationBuildDesc(bi); + irel[0]->rd_isnailed = true; + + bi.i.info_name = ClassNameIndex; + irel[1] = RelationBuildDesc(bi); + irel[1]->rd_isnailed = true; + + bi.i.info_name = ClassOidIndex; + irel[2] = RelationBuildDesc(bi); + irel[2]->rd_isnailed = true; + + SetProcessingMode(oldmode); + + /* nail the descriptor in the cache */ + for (relno = 0; relno < Num_indices_bootstrap; relno++) + { + ird = irel[relno]; + + /* save the volatile fields in the relation descriptor */ + am = ird->rd_am; + ird->rd_am = (Form_pg_am) NULL; + relform = ird->rd_rel; + ird->rd_rel = (Form_pg_class) NULL; + strat = ird->rd_istrat; + support = ird->rd_support; + + /* + * first write the relation descriptor , excluding strategy and + * support + */ + len = sizeof(RelationData); + + /* first, write the relation descriptor length */ + if ((nwritten = FileWrite(fd, (char *) &len, sizeof(int))) + != sizeof(int)) + elog(FATAL, "cannot write init file -- descriptor length"); + + /* next, write out the Relation structure */ + if ((nwritten = FileWrite(fd, (char *) ird, len)) != len) + elog(FATAL, "cannot write init file -- reldesc"); + + /* next, write the access method tuple form */ + len = sizeof(FormData_pg_am); + if ((nwritten = FileWrite(fd, (char *) &len, sizeof(int))) + != sizeof(int)) + elog(FATAL, "cannot write init file -- am tuple form length"); + + if ((nwritten = FileWrite(fd, (char *) am, len)) != len) + elog(FATAL, "cannot write init file -- am tuple form"); + + /* next write the relation tuple form */ + len = sizeof(FormData_pg_class); + if ((nwritten = FileWrite(fd, (char *) &len, sizeof(int))) + != sizeof(int)) + elog(FATAL, "cannot write init file -- relation tuple form length"); + + if ((nwritten = FileWrite(fd, (char *) relform, len)) != len) + elog(FATAL, "cannot write init file -- relation tuple form"); + + /* next, do all the attribute tuple form data entries */ + len = ATTRIBUTE_TUPLE_SIZE; + for (i = 0; i < relform->relnatts; i++) + { + if ((nwritten = FileWrite(fd, (char *) &len, sizeof(int))) + != sizeof(int)) + elog(FATAL, "cannot write init file -- length of attdesc %d", i); + if ((nwritten = FileWrite(fd, (char *) ird->rd_att->attrs[i], len)) + != len) + elog(FATAL, "cannot write init file -- attdesc %d", i); + } + + /* next, write the index strategy map */ + len = AttributeNumberGetIndexStrategySize(relform->relnatts, + am->amstrategies); + if ((nwritten = FileWrite(fd, (char *) &len, sizeof(int))) + != sizeof(int)) + elog(FATAL, "cannot write init file -- strategy map length"); + + if ((nwritten = FileWrite(fd, (char *) strat, len)) != len) + elog(FATAL, "cannot write init file -- strategy map"); + + /* finally, write the vector of support procedures */ + len = relform->relnatts * (am->amsupport * sizeof(RegProcedure)); + if ((nwritten = FileWrite(fd, (char *) &len, sizeof(int))) + != sizeof(int)) + elog(FATAL, "cannot write init file -- support vector length"); + + if ((nwritten = FileWrite(fd, (char *) support, len)) != len) + elog(FATAL, "cannot write init file -- support vector"); + + /* restore volatile fields */ + ird->rd_am = am; + ird->rd_rel = relform; } - - /* next, write the index strategy map */ - len = AttributeNumberGetIndexStrategySize(relform->relnatts, - am->amstrategies); - if ((nwritten = FileWrite(fd, (char*) &len, sizeof(int))) - != sizeof(int)) - elog(FATAL, "cannot write init file -- strategy map length"); - - if ((nwritten = FileWrite(fd, (char*) strat, len)) != len) - elog(FATAL, "cannot write init file -- strategy map"); - - /* finally, write the vector of support procedures */ - len = relform->relnatts * (am->amsupport * sizeof(RegProcedure)); - if ((nwritten = FileWrite(fd, (char*) &len, sizeof(int))) - != sizeof(int)) - elog(FATAL, "cannot write init file -- support vector length"); - - if ((nwritten = FileWrite(fd, (char*) support, len)) != len) - elog(FATAL, "cannot write init file -- support vector"); - - /* restore volatile fields */ - ird->rd_am = am; - ird->rd_rel = relform; - } - - FileClose(fd); + + FileClose(fd); } |