head 1.64; access; symbols Version_2_1:1.37 Version_2:1.19 C_Demo_1:1.14; locks; strict; comment @ * @; 1.64 date 92.08.25.22.24.00; author mao; state Exp; branches; next 1.63; 1.63 date 92.08.21.16.27.19; author mao; state Exp; branches; next 1.62; 1.62 date 92.07.30.20.48.30; author mao; state Exp; branches; next 1.61; 1.61 date 92.07.13.03.37.20; author hong; state Exp; branches; next 1.60; 1.60 date 92.07.09.23.18.21; author mao; state Exp; branches; next 1.59; 1.59 date 92.07.09.22.59.42; author mao; state Exp; branches; next 1.58; 1.58 date 92.06.27.18.47.14; author mao; state Exp; branches; next 1.57; 1.57 date 92.06.11.19.40.51; author mao; state Exp; branches; next 1.56; 1.56 date 92.03.11.02.18.36; author mer; state Exp; branches; next 1.55; 1.55 date 92.03.04.22.13.52; author mer; state Exp; branches; next 1.54; 1.54 date 92.03.02.21.18.26; author mer; state Exp; branches; next 1.53; 1.53 date 92.02.25.21.40.22; author mer; state Exp; branches; next 1.52; 1.52 date 91.11.25.21.32.42; author postgres; state Exp; branches; next 1.51; 1.51 date 91.11.21.18.22.11; author mer; state Exp; branches; next 1.50; 1.50 date 91.11.12.20.20.29; author mer; state Exp; branches; next 1.49; 1.49 date 91.11.11.16.01.18; author mer; state Exp; branches; next 1.48; 1.48 date 91.10.08.01.16.03; author hong; state Exp; branches; next 1.47; 1.47 date 91.09.27.07.44.39; author hong; state Exp; branches; next 1.46; 1.46 date 91.09.16.17.42.36; author mer; state Exp; branches; next 1.45; 1.45 date 91.09.09.23.04.57; author mao; state Exp; branches; next 1.44; 1.44 date 91.09.06.12.28.34; author hong; state Exp; branches; next 1.43; 1.43 date 91.08.15.18.08.12; author caetta; state Exp; branches; next 1.42; 1.42 date 91.08.01.11.05.39; author mer; state Exp; branches; next 1.41; 1.41 date 91.07.30.00.09.03; author mao; state Exp; branches; next 1.40; 1.40 date 91.07.22.05.54.24; author mao; state Exp; branches; next 1.39; 1.39 date 91.04.19.05.38.55; author kemnitz; state Exp; branches; next 1.38; 1.38 date 91.03.16.17.29.47; author sp; state Exp; branches; next 1.37; 1.37 date 91.03.06.11.22.52; author hong; state Exp; branches; next 1.36; 1.36 date 91.02.27.12.49.48; author mao; state Exp; branches; next 1.35; 1.35 date 91.02.19.13.58.32; author mao; state Exp; branches; next 1.34; 1.34 date 91.02.06.18.18.18; author cimarron; state Exp; branches; next 1.33; 1.33 date 91.01.31.23.46.36; author hong; state Exp; branches; next 1.32; 1.32 date 90.12.29.13.30.34; author mao; state Exp; branches; next 1.31; 1.31 date 90.11.14.08.28.18; author kemnitz; state Exp; branches; next 1.30; 1.30 date 90.10.05.17.45.35; author cimarron; state Exp; branches; next 1.29; 1.29 date 90.09.29.16.32.43; author hong; state Exp; branches; next 1.28; 1.28 date 90.09.21.11.21.57; author goh; state Exp; branches; next 1.27; 1.27 date 90.09.18.22.38.02; author hong; state Exp; branches; next 1.26; 1.26 date 90.08.22.15.18.18; author choi; state Exp; branches; next 1.25; 1.25 date 90.08.18.00.42.23; author cimarron; state Exp; branches; next 1.24; 1.24 date 90.08.15.08.35.45; author cimarron; state Exp; branches; next 1.23; 1.23 date 90.08.13.19.42.50; author sp; state Exp; branches; next 1.22; 1.22 date 90.08.10.15.19.10; author cimarron; state Exp; branches; next 1.21; 1.21 date 90.08.08.08.36.51; author cimarron; state Exp; branches; next 1.20; 1.20 date 90.08.01.14.56.24; author sp; state Exp; branches; next 1.19; 1.19 date 90.07.19.15.30.34; author mao; state Version_2; branches; next 1.18; 1.18 date 90.06.09.18.46.17; author kemnitz; state Exp; branches; next 1.17; 1.17 date 90.04.02.11.33.10; author hong; state Exp; branches; next 1.16; 1.16 date 89.11.02.18.06.24; author cimarron; state Exp; branches; next 1.15; 1.15 date 89.09.28.17.50.39; author hirohama; state Exp; branches; next 1.14; 1.14 date 89.09.05.17.27.10; author mao; state C_Demo_1; branches; next 1.13; 1.13 date 89.08.09.18.11.10; author cimarron; state Exp; branches; next 1.12; 1.12 date 89.06.17.01.53.05; author hirohama; state Exp; branches; next 1.11; 1.11 date 89.06.13.17.48.02; author dillon; state Exp; branches; next 1.10; 1.10 date 89.06.13.17.46.26; author dillon; state Exp; branches; next 1.9; 1.9 date 89.06.13.17.41.34; author dillon; state Exp; branches; next 1.8; 1.8 date 89.06.13.17.10.54; author cimarron; state Exp; branches; next 1.7; 1.7 date 89.06.13.16.53.42; author cimarron; state Exp; branches; next 1.6; 1.6 date 89.06.13.16.41.35; author cimarron; state Exp; branches; next 1.5; 1.5 date 89.05.07.16.23.13; author hirohama; state Exp; branches; next 1.4; 1.4 date 89.03.08.15.29.10; author goh; state Stab; branches; next 1.3; 1.3 date 89.03.06.16.29.40; author hirohama; state Exp; branches; next 1.2; 1.2 date 89.03.02.17.27.22; author muir; state Exp; branches; next 1.1; 1.1 date 89.01.17.05.58.49; author cimarron; state Exp; branches; next ; desc @@ 1.64 log @for 4.0.1, turn off invalidation of index reldescs in the event of pg_amop, pg_am update. nobody but me should be doing this anyway, and this code was never tested and doesn't work. @ text @/* ---------------------------------------------------------------- * FILE * relcache.c * * DESCRIPTION * POSTGRES relation descriptor cache code * * 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 * * NOTES * 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.... * * IDENTIFICATION * $Header: /private/mao/postgres/src/utils/cache/RCS/relcache.c,v 1.63 1992/08/21 16:27:19 mao Exp $ * ---------------------------------------------------------------- */ #include #include #include /* XXX check above includes */ #include "tmp/postgres.h" RcsId("$Header: /private/mao/postgres/src/utils/cache/RCS/relcache.c,v 1.63 1992/08/21 16:27:19 mao Exp $"); #include "access/att.h" #include "access/attnum.h" #include "access/genam.h" #include "access/heapam.h" #include "access/htup.h" #include "access/istrat.h" #include "access/itup.h" #include "access/skey.h" #include "access/tqual.h" /* for NowTimeQual */ #include "access/tupdesc.h" #include "rules/rlock.h" #include "storage/buf.h" #include "storage/lmgr.h" #include "tmp/hasht.h" #include "utils/memutils.h" #include "utils/log.h" #include "utils/mcxt.h" #include "utils/rel.h" #include "utils/hsearch.h" #include "catalog/catname.h" #include "catalog/syscache.h" #include "catalog/pg_attribute.h" #include "catalog/pg_aggregate.h" #include "catalog/pg_index.h" #include "catalog/pg_proc.h" #include "catalog/pg_relation.h" #include "catalog/pg_type.h" #include "catalog/pg_variable.h" #include "catalog/pg_log.h" #include "catalog/pg_time.h" #include "utils/relcache.h" #ifdef sprite #include "sprite_file.h" #else #include "storage/fd.h" #endif /* sprite */ /* ---------------- * defines * ---------------- */ #define private static /* ---------------- * externs * ---------------- */ extern bool AMI_OVERRIDE; /* XXX style */ /* ---------------- * hardcoded tuple descriptors. see lib/H/catalog/pg_attribute.h * ---------------- */ SCHEMA_DEF(pg_relation); SCHEMA_DEF(pg_attribute); SCHEMA_DEF(pg_proc); SCHEMA_DEF(pg_type); SCHEMA_DEF(pg_variable); SCHEMA_DEF(pg_log); SCHEMA_DEF(pg_time); /* ---------------- * global variables * * Relations are cached two ways, by name and by id, * thus there are two hash tables for referencing them. * ---------------- */ HTAB *RelationNameCache; HTAB *RelationIdCache; /* ---------------- * RelationBuildDescInfo exists so code can be shared * between RelationIdGetRelation() and RelationNameGetRelation() * ---------------- */ typedef struct RelationBuildDescInfo { int infotype; /* lookup by id or by name */ #define INFO_RELID 1 #define INFO_RELNAME 2 union { ObjectId info_id; /* relation object id */ Name info_name; /* relation name */ } i; } RelationBuildDescInfo; typedef struct relidcacheent { ObjectId reloid; Relation reldesc; } RelIdCacheEnt; typedef struct relnamecacheent { NameData relname; Relation reldesc; } RelNameCacheEnt; char *BuildDescInfoError ARGS((RelationBuildDescInfo buildinfo )); HeapTuple ScanPgRelation ARGS((RelationBuildDescInfo buildinfo )); void RelationBuildTupleDesc ARGS(( RelationBuildDescInfo buildinfo, Relation relation, AttributeTupleForm attp, u_int natts )); Relation RelationBuildDesc ARGS((RelationBuildDescInfo buildinfo )); private void formrdesc ARGS(( char *relationName, u_int natts, AttributeTupleFormData att [] )); private void RelationFlushIndexes ARGS(( Relation relation, ObjectId accessMethodId )); /* ----------------- * macros to manipulate name cache and id cache * ----------------- */ #define RelationCacheInsert(RELATION) \ { RelIdCacheEnt *idhentry; RelNameCacheEnt *namehentry; \ Name relname; ObjectId reloid; Boolean found; \ relname = &(RELATION->rd_rel->relname); \ namehentry = (RelNameCacheEnt*)hash_search(RelationNameCache, \ &relname->data[0], \ 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; Boolean 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; Boolean 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; \ Name relname; ObjectId reloid; Boolean found; \ relname = &(RELATION->rd_rel->relname); \ namehentry = (RelNameCacheEnt*)hash_search(RelationNameCache, \ &relname->data[0], \ 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."); \ } \ } /* ---------------------------------------------------------------- * RelationIdGetRelation() and RelationNameGetRelation() * support functions * ---------------------------------------------------------------- */ /* -------------------------------- * BuildDescInfoError returns a string appropriate to * the buildinfo passed to it * -------------------------------- */ char * BuildDescInfoError(buildinfo) RelationBuildDescInfo buildinfo; { static char errBuf[64]; bzero(errBuf, 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; } /* -------------------------------- * ScanPgRelation * * this is used by RelationBuildDesc to find a pg_relation * tuple matching either a relation name or a relation id * as specified in buildinfo. * * ADD INDEXING HERE * -------------------------------- */ HeapTuple ScanPgRelation(buildinfo) RelationBuildDescInfo buildinfo; { HeapTuple pg_relation_tuple; HeapTuple return_tuple; Relation pg_relation_desc; HeapScanDesc pg_relation_scan; ScanKeyData key; Buffer buf; /* ---------------- * form a scan key * ---------------- */ switch (buildinfo.infotype) { case INFO_RELID: ScanKeyEntryInitialize(&key.data[0], 0, ObjectIdAttributeNumber, ObjectIdEqualRegProcedure, ObjectIdGetDatum(buildinfo.i.info_id)); break; case INFO_RELNAME: ScanKeyEntryInitialize(&key.data[0], 0, RelationNameAttributeNumber, Character16EqualRegProcedure, NameGetDatum(buildinfo.i.info_name)); break; default: elog(WARN, "ScanPgRelation: bad buildinfo"); return NULL; break; } /* ---------------- * open pg_relation and fetch a tuple * ---------------- */ pg_relation_desc = heap_openr(RelationRelationName); RelationSetLockForRead(pg_relation_desc); pg_relation_scan = heap_beginscan(pg_relation_desc, 0, NowTimeQual, 1, &key); pg_relation_tuple = heap_getnext(pg_relation_scan, 0, &buf); /* ---------------- * get set to return tuple * ---------------- */ if (! HeapTupleIsValid(pg_relation_tuple)) { return_tuple = pg_relation_tuple; } else { /* ------------------ * a satanic bug used to live here: pg_relation_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(pg_relation_tuple->t_len); bcopy(pg_relation_tuple, return_tuple, pg_relation_tuple->t_len); ReleaseBuffer(buf); } /* all done */ heap_endscan(pg_relation_scan); RelationUnsetLockForRead(pg_relation_desc); heap_close(pg_relation_desc); return return_tuple; } /* ---------------- * AllocateRelationDesc * * This is used to allocate memory for a new relation descriptor * and initialize the rd_rel field. * ---------------- */ Relation AllocateRelationDesc(natts, relp) u_int natts; RelationTupleForm relp; { Relation relation; int len; RelationTupleForm relationTupleForm; /* ---------------- * allocate space for the relation tuple form * ---------------- */ relationTupleForm = (RelationTupleForm) palloc(sizeof (RuleLock) + sizeof *relation->rd_rel); bcopy((char *)relp, (char *)relationTupleForm, sizeof *relp); /* ---------------- * allocate space for new relation descriptor, including * the tuple descriptor and the index strategy and support pointers * ---------------- */ len = sizeof(RelationData) + ((int)natts - 1) * sizeof(relation->rd_att) + /* var len struct */ sizeof(IndexStrategy) + sizeof(RegProcedure *) + 10; /* + 10 is voodoo XXX mao */ relation = (Relation) palloc(len); /* ---------------- * clear new reldesc and initialize relation tuple form * ---------------- */ bzero((char *)relation, len); relation->rd_rel = relationTupleForm; return relation; } /* -------------------------------- * RelationBuildTupleDesc * * Form the relation's tuple descriptor from information in * the pg_attribute system catalog. * * ADD INDEXING HERE * -------------------------------- */ void RelationBuildTupleDesc(buildinfo, relation, attp, natts) RelationBuildDescInfo buildinfo; Relation relation; AttributeTupleForm attp; u_int natts; { HeapTuple pg_attribute_tuple; Relation pg_attribute_desc; HeapScanDesc pg_attribute_scan; ScanKeyData key; int i; int need; /* ---------------- * form a scan key * ---------------- */ ScanKeyEntryInitialize(&key.data[0], 0, AttributeRelationIdAttributeNumber, 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) HeapTupleGetForm(pg_attribute_tuple); if (attp->attnum > 0) { relation->rd_att.data[attp->attnum - 1] = (Attribute) palloc(sizeof (RuleLock) + sizeof *relation->rd_att.data[0]); bcopy((char *) attp, (char *) relation->rd_att.data[attp->attnum - 1], sizeof *relation->rd_att.data[0]); need--; } 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", natts - need, ((natts - need) == 1 ? "" : "s"), relation->rd_id); /* ---------------- * end the scan and close the attribute relation * ---------------- */ heap_endscan(pg_attribute_scan); heap_close(pg_attribute_desc); } /* -------------------------------- * 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 * AccessMethodTupleForm rd_am; AM tuple * RelationTupleForm rd_rel; RELATION tuple * ObjectId rd_id; relations's object id * Pointer lockInfo; ptr. to misc. info. * TupleDescriptorData 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 * -------------------------------- */ Relation RelationBuildDesc(buildinfo) RelationBuildDescInfo buildinfo; { File fd; Relation relation; u_int natts; ObjectId relid; ObjectId relam; RelationTupleForm relp; AttributeTupleForm attp = NULL; ObjectId attrioid; /* attribute relation index relation oid */ extern GlobalMemory CacheCxt; MemoryContext oldcxt; HeapTuple pg_relation_tuple; oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); /* ---------------- * find the tuple in pg_relation corresponding to the given relation id * ---------------- */ pg_relation_tuple = ScanPgRelation(buildinfo); /* ---------------- * if no such tuple exists, return NULL * ---------------- */ if (! HeapTupleIsValid(pg_relation_tuple)) { MemoryContextSwitchTo(oldcxt); return NULL; } /* ---------------- * get information from the pg_relation_tuple * ---------------- */ relid = pg_relation_tuple->t_oid; relp = (RelationTupleForm) GETSTRUCT(pg_relation_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 (ObjectIdIsValid(relam)) { relation->rd_am = (AccessMethodTupleForm) 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, attp, natts); /* ---------------- * initialize index strategy and support information for this relation * ---------------- */ if (ObjectIdIsValid(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_relation_tuple * ------------------- */ pfree(pg_relation_tuple); MemoryContextSwitchTo(oldcxt); return relation; } IndexedAccessMethodInitialize(relation) Relation relation; { IndexStrategy strategy; RegProcedure *support; int natts; int stratSize; int 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.data[0]->attrelid, relation->rd_rel->relam, relamstrategies, relamsupport, natts); RelationSetIndexSupport(relation, strategy, support); } /* -------------------------------- * 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 * bootstraping. * -------------------------------- */ private void formrdesc(relationName, natts, att) char *relationName; u_int natts; AttributeTupleFormData att[]; { Relation relation; int fd; int len; int i; char *relpath(); Relation publicCopy; /* ---------------- * allocate new relation desc * ---------------- */ len = sizeof *relation + ((int)natts - 1) * sizeof relation->rd_att; relation = (Relation) palloc(len); bzero((char *)relation, 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 = (RelationTupleForm) palloc(sizeof (RuleLock) + sizeof *relation->rd_rel); bzero(relation->rd_rel, sizeof(struct RelationTupleFormD)); strncpy(&relation->rd_rel->relname, relationName, sizeof(NameData)); /* * 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 (issystem(relationName)) { relation->rd_rel->relowner = 6; /* XXX use sym const */ relation->rd_rel->relisshared = NameIsSharedSystemRelationName((Name)relationName); } else { relation->rd_rel->relowner = InvalidObjectId; /* XXX incorrect*/ relation->rd_rel->relisshared = false; } relation->rd_rel->relpages = 1; /* XXX */ relation->rd_rel->reltuples = 1; /* XXX */ relation->rd_rel->relkind = 'r'; 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.data[i] = (Attribute) palloc(sizeof (RuleLock) + sizeof *relation->rd_att.data[0]); bzero((char *)relation->rd_att.data[i], sizeof (RuleLock) + sizeof *relation->rd_att.data[0]); bcopy((char *)&att[i], (char *)relation->rd_att.data[i], sizeof *relation->rd_att.data[0]); } /* ---------------- * initialize relation id * ---------------- */ relation->rd_id = relation->rd_att.data[0]->attrelid; /* ---------------- * add new reldesc to relcache * ---------------- */ RelationCacheInsert(relation); /* * Determining this requires a scan on pg_relation, but to do the * scan the rdesc for pg_relation 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 * ---------------------------------------------------------------- */ /* -------------------------------- * 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. * -------------------------------- */ Relation RelationIdCacheGetRelation(relationId) ObjectId 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); } RelationIncrementReferenceCount(rd); RelationSetLockForDescriptorOpen(rd); } return(rd); } /* -------------------------------- * RelationNameCacheGetRelation * -------------------------------- */ Relation RelationNameCacheGetRelation(relationName) Name relationName; { Relation rd; NameData name; /* make sure that the name key used for hash lookup is properly null-padded */ bzero(&name, sizeof(NameData)); strncpy(&name, relationName, sizeof(NameData)); RelationNameCacheLookup(&name, 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); } return(rd); } /* -------------------------------- * RelationIdGetRelation * * return a relation descriptor based on its id. * return a cached value if possible * -------------------------------- */ Relation RelationIdGetRelation(relationId) ObjectId 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; } /* -------------------------------- * RelationNameGetRelation * * return a relation descriptor based on its name. * return a cached value if possible * -------------------------------- */ Relation RelationNameGetRelation(relationName) Name 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)) 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. * ---------------- */ Relation getreldesc(relationName) Name relationName; { /* ---------------- * increment access statistics * ---------------- */ IncrHeapAccessStat(local_getreldesc); IncrHeapAccessStat(global_getreldesc); return (Relation) RelationNameGetRelation(relationName); } /* ---------------------------------------------------------------- * cache invalidation support routines * ---------------------------------------------------------------- */ /* -------------------------------- * RelationClose - close an open relation * -------------------------------- */ void RelationClose(relation) Relation relation; { /* Note: no locking manipulations needed */ RelationDecrementReferenceCount(relation); } /* -------------------------------- * RelationFlushRelation * -------------------------------- */ /**** xxref: * RelationIdInvalidateRelationCacheByRelationId * RelationFlushIndexes ****/ void RelationFlushRelation(relation, onlyFlushReferenceCountZero) Relation relation; bool onlyFlushReferenceCountZero; { int i; Attribute *p; MemoryContext oldcxt; if (relation->rd_isnailed) { /* this is a nailed special relation for bootstraping */ return; } if (!onlyFlushReferenceCountZero || RelationHasReferenceCountZero(relation)) { oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); RelationCacheDelete(relation); FileInvalidate(RelationGetSystemPort(relation)); i = relation->rd_rel->relnatts - 1; p = &relation->rd_att.data[i]; while ((i -= 1) >= 0) { pfree((char *)*p--); } pfree((char *)RelationGetLockInfo(relation)); pfree((char *)RelationGetRelationTupleForm(relation)); pfree((char *)relation); MemoryContextSwitchTo(oldcxt); } } /* -------------------------------- * RelationIdInvalidateRelationCacheByRelationId * -------------------------------- */ /**** xxref: * CacheIdInvalidate ****/ void RelationIdInvalidateRelationCacheByRelationId(relationId) ObjectId relationId; { Relation relation; RelationIdCacheLookup(relationId, relation); if (PointerIsValid(relation)) { /* Assert(RelationIsValid(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. */ RelationFlushRelation(relation, CurrentXactInProgress()); } } /* -------------------------------- * RelationIdInvalidateRelationCacheByAccessMethodId * * RelationFlushIndexes is needed for use with HashTableWalk.. * -------------------------------- */ private void RelationFlushIndexes(r, accessMethodId) Relation *r; ObjectId accessMethodId; { Relation relation = *r; if (!RelationIsValid(relation)) { elog(NOTICE, "inval call to RFI"); return; } if (relation->rd_rel->relkind == 'i' && /* XXX style */ (!ObjectIdIsValid(accessMethodId) || relation->rd_rel->relam == accessMethodId)) { RelationFlushRelation(relation, false); } } /**** xxref: * CacheIdInvalidate ****/ void RelationIdInvalidateRelationCacheByAccessMethodId(accessMethodId) ObjectId 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, RelationFlushIndexes, accessMethodId); # else return; # endif } /* -------------------------------- * RelationCacheInvalidate * -------------------------------- */ /**** xxref: * ResetSystemCaches ****/ void RelationCacheInvalidate(onlyFlushReferenceCountZero) bool onlyFlushReferenceCountZero; { HashTableWalk(RelationNameCache, RelationFlushRelation, onlyFlushReferenceCountZero); } /* -------------------------------- * RelationRegisterRelation * -------------------------------- */ /**** xxref: * RelationRegisterTempRel ****/ void RelationRegisterRelation(relation) Relation relation; { extern GlobalMemory CacheCxt; MemoryContext oldcxt; oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); if (oldcxt != (MemoryContext)CacheCxt) elog(NOIND,"RelationRegisterRelation: WARNING: Context != CacheCxt"); RelationCacheInsert(relation); RelationInitLockInfo(relation); MemoryContextSwitchTo(oldcxt); } /* ----------------------------------- * RelationRegisterTempRel * * Register a temporary relation created by another backend * only called in parallel mode. * ---------------------------------- */ /**** xxref: * ****/ void RelationRegisterTempRel(temprel) Relation temprel; { extern GlobalMemory CacheCxt; MemoryContext oldcxt; Relation rd; /* ---------------------------------------- * see if the temprel is created by the current backend * and therefore is already in the hast table * ---------------------------------------- */ RelationIdCacheLookup(temprel->rd_id, rd); if (RelationIsValid(rd)) return; /* ---------------------------------------- * the temprel is created by another backend, insert it into the * hash table * ---------------------------------------- */ oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); RelationRegisterRelation(temprel); MemoryContextSwitchTo(oldcxt); } /* -------------------------------- * RelationInitialize * * This initializes the relation descriptor cache. * -------------------------------- */ #define INITRELCACHESIZE 400 void RelationInitialize() { extern GlobalMemory CacheCxt; MemoryContext oldcxt; HASHCTL ctl; /* ---------------- * switch to cache memory context * ---------------- */ if (!CacheCxt) CacheCxt = CreateGlobalMemory("Cache"); oldcxt = MemoryContextSwitchTo((MemoryContext)CacheCxt); /* ---------------- * create global caches * ---------------- */ bzero(&ctl, sizeof(ctl)); ctl.keysize = sizeof(NameData); ctl.datasize = sizeof(Relation); RelationNameCache = hash_create(INITRELCACHESIZE, &ctl, HASH_ELEM); ctl.keysize = sizeof(ObjectId); 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. * ---------------- */ #define INIT_RELDESC(x) \ formrdesc(SCHEMA_NAME(x), \ SCHEMA_NATTS(x), \ SCHEMA_DESC(x)) INIT_RELDESC(pg_relation); INIT_RELDESC(pg_attribute); INIT_RELDESC(pg_proc); INIT_RELDESC(pg_type); INIT_RELDESC(pg_variable); INIT_RELDESC(pg_log); INIT_RELDESC(pg_time); MemoryContextSwitchTo(oldcxt); } @ 1.63 log @when building a tuple descriptor, don't scan all of pg_attribute -- stop as early as possible. @ text @d25 1 a25 1 * $Header: /home/postgres/mao/postgres/src/utils/cache/RCS/relcache.c,v 1.62 1992/07/30 20:48:30 mao Exp $ d36 1 a36 1 RcsId("$Header: /home/postgres/mao/postgres/src/utils/cache/RCS/relcache.c,v 1.62 1992/07/30 20:48:30 mao Exp $"); d1054 2 a1055 2 RelationFlushIndexes(relation, accessMethodId) Relation relation; d1058 7 d1080 10 d1092 3 @ 1.62 log @on cache invalidation, also have to invalidate fd cache @ text @d25 1 a25 1 * $Header: /home/postgres/mao/postgres/src/utils/cache/RCS/relcache.c,v 1.61 1992/07/13 03:37:20 hong Exp mao $ d36 1 a36 1 RcsId("$Header: /home/postgres/mao/postgres/src/utils/cache/RCS/relcache.c,v 1.61 1992/07/13 03:37:20 hong Exp mao $"); d428 1 d434 1 a434 1 ScanKeyEntryInitialize(&key.data[0], 0, d440 1 a440 1 * open pg_relation and begin a scan d448 1 a448 1 * for each tuple scanned, add attribute data to relation->rd_att d451 4 a454 4 while (pg_attribute_tuple = heap_getnext(pg_attribute_scan, 0, (Buffer *) NULL), HeapTupleIsValid(pg_attribute_tuple)) { d457 3 a459 10 if (!AttributeNumberIsValid(attp->attnum)) elog(WARN, "RelationBuildTupleDesc: %s bad attribute number %d", BuildDescInfoError(buildinfo), attp->attnum); if (AttributeNumberIsForUserDefinedAttribute(attp->attnum)) { if (AttributeIsValid(relation->rd_att.data[attp->attnum - 1])) elog(WARN, "RelationBuildTupleDesc: %s bad attribute %d", BuildDescInfoError(buildinfo), attp->attnum - 1); d462 1 a462 1 d466 2 d469 2 d472 6 a477 1 a483 13 /* ---------------- * check that all attributes are valid because it's possible that * some tuples in the pg_attribute relation are missing so rd_att.data * might have zeros in it someplace. * ---------------- */ for(i = --natts; i>=0; i--) { if (! AttributeIsValid(relation->rd_att.data[i])) elog(WARN, "RelationBuildTupleDesc: %s attribute %d invalid", RelationGetRelationName(relation), i); } @ 1.61 log @prototyping @ text @d25 1 a25 1 * $Header: RCS/relcache.c,v 1.60 92/07/09 23:18:21 mao Exp Locker: hong $ d36 1 a36 1 RcsId("$Header: RCS/relcache.c,v 1.60 92/07/09 23:18:21 mao Exp Locker: hong $"); d1014 1 a1014 1 FileClose(RelationGetSystemPort(relation)); @ 1.60 log @do read locking in ScanPgRelation, too. @ text @d25 1 a25 1 * $Header: /private/mao/postgres/src/utils/cache/RCS/relcache.c,v 1.59 1992/07/09 22:59:42 mao Exp mao $ d36 1 a36 1 RcsId("$Header: /private/mao/postgres/src/utils/cache/RCS/relcache.c,v 1.59 1992/07/09 22:59:42 mao Exp mao $"); d751 1 a751 1 NameIsSharedSystemRelationName(relationName); @ 1.59 log @be more careful about buffer management in ScanPgRelation @ text @d25 1 a25 1 * $Header: /private/mao/postgres/src/utils/cache/RCS/relcache.c,v 1.58 1992/06/27 18:47:14 mao Exp $ d36 1 a36 1 RcsId("$Header: /private/mao/postgres/src/utils/cache/RCS/relcache.c,v 1.58 1992/06/27 18:47:14 mao Exp $"); d328 1 d354 1 @ 1.58 log @don't bother to elog(NOTICE, ...) if reln not found -- error will be reported later, and there are cases where we don't want to bother the user with this stuff. @ text @d25 1 a25 1 * $Header: /private/mao/postgres/src/utils/cache/RCS/relcache.c,v 1.57 1992/06/11 19:40:51 mao Exp mao $ d36 1 a36 1 RcsId("$Header: /private/mao/postgres/src/utils/cache/RCS/relcache.c,v 1.57 1992/06/11 19:40:51 mao Exp mao $"); d296 1 d330 1 a330 1 pg_relation_tuple = heap_getnext(pg_relation_scan, 0, (Buffer *)NULL); d333 1 a333 1 * close the relation d336 16 a353 17 /* ---------------- * return tuple * ---------------- */ if (! HeapTupleIsValid(pg_relation_tuple)) return NULL; /* ------------------ * a satanic bug used to live here: pg_relation_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(pg_relation_tuple->t_len); bcopy(pg_relation_tuple, return_tuple, pg_relation_tuple->t_len); @ 1.57 log @correctly initialize relisshared in formrdesc(). @ text @d25 1 a25 1 * $Header: /private/mao/postgres/src/utils/cache/RCS/relcache.c,v 1.56 1992/03/11 02:18:36 mer Exp $ d36 1 a36 1 RcsId("$Header: /private/mao/postgres/src/utils/cache/RCS/relcache.c,v 1.56 1992/03/11 02:18:36 mer Exp $"); d544 1 a544 1 * if no such tuple exists, report an error and return NULL a547 2 elog(NOTICE, "RelationBuildDesc: %s nonexistent", BuildDescInfoError(buildinfo)); @ 1.56 log @free lock info when reldesc get flushed from the cache @ text @d25 1 a25 1 * $Header: /users/mer/pg/src/utils/cache/RCS/relcache.c,v 1.55 1992/03/04 22:13:52 mer Exp mer $ d36 1 a36 1 RcsId("$Header: /users/mer/pg/src/utils/cache/RCS/relcache.c,v 1.55 1992/03/04 22:13:52 mer Exp mer $"); d740 17 a756 1 relation->rd_rel->relowner = InvalidObjectId; /* XXX incorrect */ @ 1.55 log @pass number of attributes as an arg to IndexSupportInitialize @ text @d25 1 a25 1 * $Header: /users/mer/pg_opt.new/src/utils/cache/RCS/relcache.c,v 1.54 1992/03/02 21:18:26 mer Exp mer $ d36 1 a36 1 RcsId("$Header: /users/mer/pg_opt.new/src/utils/cache/RCS/relcache.c,v 1.54 1992/03/02 21:18:26 mer Exp mer $"); d1006 1 @ 1.54 log @set the rd_rel->relhasindex field dynamically during initialization. If this is not done we'll never know as the reldescs are always nailed in the cache. @ text @d25 1 a25 1 * $Header: /users/mer/pg/src/utils/cache/RCS/relcache.c,v 1.53 1992/02/25 21:40:22 mer Exp mer $ d36 1 a36 1 RcsId("$Header: /users/mer/pg/src/utils/cache/RCS/relcache.c,v 1.53 1992/02/25 21:40:22 mer Exp mer $"); d682 1 a682 1 relamstrategies, relamsupport); @ 1.53 log @don't always free reldesc from relcache, only after commit @ text @d25 1 a25 1 * $Header: /users/mer/pg/src/utils/cache/RCS/relcache.c,v 1.52 1991/11/25 21:32:42 postgres Exp mer $ d36 1 a36 1 RcsId("$Header: /users/mer/pg/src/utils/cache/RCS/relcache.c,v 1.52 1991/11/25 21:32:42 postgres Exp mer $"); a742 1 relation->rd_rel->relhasindex = '\0'; d747 1 a747 1 d773 7 @ 1.52 log @Initialize those relation descriptors properly! This fixes an initialization bug that only shows up on Sparc... @ text @d25 1 a25 1 * $Header: RCS/relcache.c,v 1.51 91/11/21 18:22:11 mer Exp $ d36 1 a36 1 RcsId("$Header: RCS/relcache.c,v 1.51 91/11/21 18:22:11 mer Exp $"); d527 1 a527 1 AttributeTupleForm attp; d825 1 d1024 7 a1030 1 RelationFlushRelation(relation, false); @ 1.51 log @temporary hack to test fix for sun3 architecture @ text @d25 1 a25 1 * $Header: RCS/relcache.c,v 1.50 91/11/12 20:20:29 mer Exp $ d36 1 a36 1 RcsId("$Header: RCS/relcache.c,v 1.50 91/11/12 20:20:29 mer Exp $"); d736 3 a738 1 @ 1.50 log @prototyping changes @ text @d25 1 a25 1 * $Header: /users/mer/postgres/src/utils/cache/RCS/relcache.c,v 1.49 1991/11/11 16:01:18 mer Exp mer $ d36 1 a36 1 RcsId("$Header: /users/mer/postgres/src/utils/cache/RCS/relcache.c,v 1.49 1991/11/11 16:01:18 mer Exp mer $"); d391 1 a391 1 + sizeof(RegProcedure *); @ 1.49 log @prototying changes @ text @d25 1 a25 1 * $Header: /users/mer/postgres/src/utils/cache/RCS/relcache.c,v 1.48 1991/10/08 01:16:03 hong Exp mer $ d36 1 a36 1 RcsId("$Header: /users/mer/postgres/src/utils/cache/RCS/relcache.c,v 1.48 1991/10/08 01:16:03 hong Exp mer $"); a116 2 extern int tag_hash(); d169 2 a170 1 relname, HASH_ENTER, \ d181 3 a183 1 &reloid, HASH_ENTER, &found); \ d195 1 a195 1 NAME, HASH_FIND, &found); \ d209 1 a209 1 &(ID), HASH_FIND, &found); \ d225 2 a226 1 relname, HASH_REMOVE, \ d236 2 a237 1 &reloid, HASH_REMOVE, &found); \ @ 1.48 log @bug fix to avoid coredump when a relation does not exist @ text @d25 1 a25 1 * $Header: utils/cache/RCS/relcache.c,v 1.47 91/09/27 07:44:39 hong Exp Locker: hong $ d36 1 a36 1 RcsId("$Header: utils/cache/RCS/relcache.c,v 1.47 91/09/27 07:44:39 hong Exp Locker: hong $"); d94 1 a94 1 d119 15 d142 19 a248 15 /* ---------------- * RelationBuildDescInfo exists so code can be shared * between RelationIdGetRelation() and RelationNameGetRelation() * ---------------- */ typedef struct RelationBuildDescInfo { int infotype; /* lookup by id or by name */ #define INFO_RELID 1 #define INFO_RELNAME 2 union { ObjectId info_id; /* relation object id */ Name info_name; /* relation name */ } i; } RelationBuildDescInfo; d254 1 d532 1 a532 1 oldcxt = MemoryContextSwitchTo(CacheCxt); d982 1 a982 1 oldcxt = MemoryContextSwitchTo(CacheCxt); d1081 1 a1081 1 oldcxt = MemoryContextSwitchTo(CacheCxt); d1126 1 a1126 1 oldcxt = MemoryContextSwitchTo(CacheCxt); d1156 1 a1156 1 oldcxt = MemoryContextSwitchTo(CacheCxt); @ 1.47 log @fixed a satanic bug in ScanPgRelation() that returns pg_relation tuples from buffer page without pinning. @ text @d25 1 a25 1 * $Header: RCS/relcache.c,v 1.46 91/09/16 17:42:36 mer Exp Locker: hong $ d36 1 a36 1 RcsId("$Header: RCS/relcache.c,v 1.46 91/09/16 17:42:36 mer Exp Locker: hong $"); a307 10 /* ------------------ * a satanic bug used to live here: pg_relation_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(pg_relation_tuple->t_len); bcopy(pg_relation_tuple, return_tuple, pg_relation_tuple->t_len); d316 1 a316 1 * return tuple or NULL d321 10 @ 1.46 log @don't elog a NOTICE to user when overwriting a reln in the cache. @ text @d25 1 a25 1 * $Header: RCS/relcache.c,v 1.45 91/09/09 23:04:57 mao Exp Locker: mer $ d36 1 a36 1 RcsId("$Header: RCS/relcache.c,v 1.45 91/09/09 23:04:57 mao Exp Locker: mer $"); d269 1 d308 10 d332 1 a332 1 return pg_relation_tuple; d620 6 @ 1.45 log @don't complain about reldescs already in the cache during bootstrap; this is guaranteed to happen. @ text @d25 1 a25 1 * $Header: /local/mao/postgres/src/utils/cache/RCS/relcache.c,v 1.44 1991/09/06 12:28:34 hong Exp mao $ d36 1 a36 1 RcsId("$Header: /local/mao/postgres/src/utils/cache/RCS/relcache.c,v 1.44 1991/09/06 12:28:34 hong Exp mao $"); d143 1 a143 1 elog(NOTICE, "trying to insert a reldesc that already exists."); \ d153 1 a153 1 elog(NOTICE, "trying to insert a reldesc that already exists."); \ @ 1.44 log @ditched old hashing code, now uses dynahash for descriptor caches got rid of private cache, now only maintains one global cache bootstraping reldescs are carefully nailed into the cache @ text @d25 1 a25 1 * $Header: RCS/relcache.c,v 1.43 91/08/15 18:08:12 caetta Exp Locker: hong $ d36 1 a36 1 RcsId("$Header: RCS/relcache.c,v 1.43 91/08/15 18:08:12 caetta Exp Locker: hong $"); d142 1 a142 1 if (found) { \ d152 1 a152 1 if (found) { \ @ 1.43 log @for declaring aggregates @ text @d25 1 a25 1 * $Header: utils/cache/RCS/relcache.c,v 1.42 91/08/01 11:05:39 mer Exp Locker: caetta $ d36 1 a36 1 RcsId("$Header: utils/cache/RCS/relcache.c,v 1.42 91/08/01 11:05:39 mer Exp Locker: caetta $"); a52 2 #include "tmp/miscadmin.h" #include "tmp/hashlib.h" d59 1 d114 13 a126 6 HashTable RelationCacheHashByName; HashTable GlobalNameCache; HashTable RelationCacheHashById; HashTable GlobalIdCache; HashTable PrivateRelationCacheHashByName; HashTable PrivateRelationCacheHashById; d128 81 a499 2 HashTable NameCacheSave; HashTable IdCacheSave; a500 9 /* ---------------- * hold onto our caches * ---------------- */ NameCacheSave = RelationCacheHashByName; IdCacheSave = RelationCacheHashById; RelationCacheHashByName = PrivateRelationCacheHashByName; RelationCacheHashById = PrivateRelationCacheHashById; a516 2 RelationCacheHashByName = NameCacheSave; RelationCacheHashById = IdCacheSave; d551 6 a606 2 RelationCacheHashByName = NameCacheSave; RelationCacheHashById = IdCacheSave; d608 2 a609 3 HashTableInsert(RelationCacheHashByName, relation); HashTableInsert(RelationCacheHashById, relation); d652 3 a654 1 * relcache. d658 2 a659 3 formrdesc(relationName, reloid, natts, att, initialReferenceCount) char relationName[]; OID reloid; /* XXX unused */ a661 1 int initialReferenceCount; d697 1 a697 1 strncpy(&relation->rd_rel->relname, relationName, 16); d705 1 d722 1 a722 1 * initialize relation id (??? should use reloid parameter instead ???) d728 1 a728 1 * add new reldesc to the private relcache d731 1 a731 17 HashTableInsert(PrivateRelationCacheHashByName, relation); HashTableInsert(PrivateRelationCacheHashById, relation); /* ---------------- * add new reldesc to the public relcache * ---------------- */ if (initialReferenceCount != 0) { publicCopy = (Relation)palloc(len); bcopy(relation, publicCopy, len); RelationSetReferenceCount(publicCopy, initialReferenceCount); HashTableInsert(RelationCacheHashByName, publicCopy); HashTableInsert(RelationCacheHashById, publicCopy); RelationInitLockInfo(relation); /* XXX unuseful here ??? */ } d754 1 a754 2 rd = (Relation) KeyHashTableLookup(RelationCacheHashById, relationId); a755 3 if (!RelationIsValid(rd)) rd = (Relation) KeyHashTableLookup(GlobalIdCache, relationId); d779 1 d781 4 a784 2 rd = (Relation) KeyHashTableLookup(RelationCacheHashByName, relationName); a785 3 if (!RelationIsValid(rd)) rd = (Relation) KeyHashTableLookup(GlobalNameCache, relationName); d937 2 a938 2 if (relation->rd_refcnt > 0x1000) { /* XXX */ /* this is a non-regeneratable special relation */ d942 2 a943 2 if (onlyFlushReferenceCountZero == false || RelationHasReferenceCountZero(relation)) { d947 1 a947 2 HashTableDelete(RelationCacheHashByName,relation); HashTableDelete(RelationCacheHashById,relation); d977 1 a977 2 relation = (Relation) KeyHashTableLookup(RelationCacheHashById, relationId); d1011 1 a1011 1 HashTableWalk(RelationCacheHashByName, RelationFlushIndexes, d1026 1 a1026 1 HashTableWalk(RelationCacheHashByName, RelationFlushRelation, d1049 1 a1049 2 HashTableInsert(RelationCacheHashByName,relation); HashTableInsert(RelationCacheHashById,relation); d1079 1 a1079 1 rd = (Relation) KeyHashTableLookup(RelationCacheHashById,temprel->rd_id); a1080 3 if (!RelationIsValid(rd)) rd = (Relation) KeyHashTableLookup(GlobalIdCache, temprel->rd_id); d1096 1 a1096 91 /* ---------------------------------------------------------------- * catalog cache initialization support functions * ---------------------------------------------------------------- */ /* -------------------------------- * CompareNameInArgumentWithRelationNameInRelation() * CompareIdInArgumentWithIdInRelation() * * these are needed for use with CreateHashTable() in * RelationInitialize() below. * -------------------------------- */ private int CompareNameInArgumentWithRelationNameInRelation(relation, relationName) Relation relation; String relationName; { return strncmp(relationName, &relation->rd_rel->relname, 16); } private int CompareIdInArgumentWithIdInRelation(relation, relationId) Relation relation; ObjectId relationId; { return relation->rd_id - relationId; } /* -------------------------------- * RelationInitialize hash function support * -------------------------------- */ /* ---------------- * HashByNameAsArgument * ---------------- */ private Index HashByNameAsArgument(collisions, hashTableSize, relationName) uint16 collisions; Size hashTableSize; Name relationName; { return NameHashFunction(collisions, hashTableSize, relationName); } /* ---------------- * HashByNameInRelation * ---------------- */ private Index HashByNameInRelation(collisions, hashTableSize, relation) uint16 collisions; Size hashTableSize; Relation relation; { return NameHashFunction(collisions, hashTableSize, &relation->rd_rel->relname); } /* ---------------- * HashByIdAsArgument * ---------------- */ private Index HashByIdAsArgument(collisions, hashTableSize, relationId) uint16 collisions; Size hashTableSize; uint32 relationId; { return IntegerHashFunction(collisions, hashTableSize, relationId); } /* ---------------- * HashByIdInRelation * ---------------- */ private Index HashByIdInRelation(collisions, hashTableSize, relation) uint16 collisions; Size hashTableSize; Relation relation; { return IntegerHashFunction(collisions, hashTableSize, relation->rd_id); } /* -------------------------------- d1102 3 d1110 1 a1110 1 int initialReferences; d1125 4 a1128 6 RelationCacheHashByName = CreateHashTable(HashByNameAsArgument, HashByNameInRelation, CompareNameInArgumentWithRelationNameInRelation, NULL, 300); d1130 4 a1133 1 GlobalNameCache = RelationCacheHashByName; a1134 9 RelationCacheHashById = CreateHashTable(HashByIdAsArgument, HashByIdInRelation, CompareIdInArgumentWithIdInRelation, NULL, 300); GlobalIdCache = RelationCacheHashById; a1135 38 * create private caches * * these should use a hash function that is perfect on them * and the hash table code should have a way of telling it not * to bother trying to resize 'cauase they all fit and there * arn't any collisions. Also, the hash table code could have * a HashTableDisableModification call. * * ??? What are the private caches used for? my guess is that * system catalog relations use them but I'm not sure * -cim 2/5/91 * ---------------- */ PrivateRelationCacheHashByName = CreateHashTable(HashByNameAsArgument, HashByNameInRelation, CompareNameInArgumentWithRelationNameInRelation, NULL, 30); PrivateRelationCacheHashById = CreateHashTable(HashByIdAsArgument, HashByIdInRelation, CompareIdInArgumentWithIdInRelation, NULL, 30); /* ---------------- * using a large positive initial reference count is a hack * to prevent generation of the special descriptors * ---------------- */ initialReferences = 0; if (AMI_OVERRIDE) { initialReferences = 0x2000; } /* ---------------- a1142 1 SCHEMA_DESC(x)[0].attrelid, \ d1144 1 a1144 2 SCHEMA_DESC(x), \ initialReferences); a1149 3 initialReferences = 0x2000; @ 1.42 log @cleanup lmgr.h include @ text @d25 1 a25 1 * $Header: utils/cache/RCS/relcache.c,v 1.41 91/07/30 00:09:03 mao Exp Locker: mer $ d36 1 a36 1 RcsId("$Header: utils/cache/RCS/relcache.c,v 1.41 91/07/30 00:09:03 mao Exp Locker: mer $"); d66 1 @ 1.41 log @use smgropen() instead of relopen(); relopen() is gone. @ text @d25 1 a25 1 * $Header: /users/mao/postgres/src/utils/cache/RCS/relcache.c,v 1.40 1991/07/22 05:54:24 mao Exp mao $ d36 1 a36 1 RcsId("$Header: /users/mao/postgres/src/utils/cache/RCS/relcache.c,v 1.40 1991/07/22 05:54:24 mao Exp mao $"); d51 1 a57 1 #include "utils/lmgr.h" @ 1.40 log @get rid of a spelling mistake that has bothered me for two years. @ text @d25 1 a25 1 * $Header: /users/mao/postgres/src/utils/cache/RCS/relcache.c,v 1.39 1991/04/19 05:38:55 kemnitz Exp mao $ d36 1 a36 1 RcsId("$Header: /users/mao/postgres/src/utils/cache/RCS/relcache.c,v 1.39 1991/04/19 05:38:55 kemnitz Exp mao $"); a142 36 * relopen - physically open a relation * * Note that this function should be replaced by a fd manager * which interacts with the reldesc manager. (Thus, this function * may be eventually have different functionality/have a different name. * * Perhaps relpath() code should be placed in-line here eventually. * -------------------------------- */ /**** xxref: * BuildRelation * formrdesc ****/ File relopen(relationName, flags, mode) char relationName[]; int flags; int mode; { File file; int oumask; extern char *relpath(); oumask = (int) umask(0077); file = FileNameOpenFile(relpath(relationName), flags, mode); if (file == -1) elog(NOTICE, "cannot open %s (%d)", relpath(relationName), errno); umask(oumask); return file; } /* -------------------------------- a467 15 /* ---------------- * open the file named in the pg_relation_tuple and * assign the file descriptor to rd_fd and record the * number of blocks in the relation * ---------------- */ fd = relopen(&relp->relname, O_RDWR, 0666); Assert (fd >= -1); if (fd == -1) elog(NOTICE, "RelationIdBuildRelation: relopen(%s): %m", &relp->relname); relation->rd_fd = fd; d508 14 a589 1 File relopen(); d699 1 a699 2 rd->rd_fd = relopen(&rd->rd_rel-> relname, O_RDWR | O_CREAT, 0666); d729 1 a729 2 rd->rd_fd = relopen(&rd->rd_rel->relname, O_RDWR | O_CREAT, 0666); @ 1.39 log @uses new scankey stuff @ text @d25 1 a25 1 * $Header: RCS/relcache.c,v 1.38 91/03/16 17:29:47 sp Exp Locker: kemnitz $ d36 1 a36 1 RcsId("$Header: RCS/relcache.c,v 1.38 91/03/16 17:29:47 sp Exp Locker: kemnitz $"); d170 1 a170 1 elog(NOTICE, "Unable too open %s (%d)", relpath(relationName), errno); @ 1.38 log @minor bug fix, an elog WARN had wrong # of arguments.... @ text @d25 1 a25 1 * $Header: RCS/relcache.c,v 1.37 91/03/06 11:22:52 hong Exp Locker: sp $ d36 1 a36 1 RcsId("$Header: RCS/relcache.c,v 1.37 91/03/06 11:22:52 hong Exp Locker: sp $"); d227 4 a230 4 key.data[0].flags = 0; key.data[0].attributeNumber = ObjectIdAttributeNumber; key.data[0].procedure = ObjectIdEqualRegProcedure; key.data[0].argument = ObjectIdGetDatum(buildinfo.i.info_id); d234 4 a237 4 key.data[0].flags = 0; key.data[0].attributeNumber = RelationNameAttributeNumber; key.data[0].procedure = Character16EqualRegProcedure; key.data[0].argument = NameGetDatum(buildinfo.i.info_name); d345 4 a348 4 key.data[0].flags = 0; key.data[0].attributeNumber = AttributeRelationIdAttributeNumber; key.data[0].procedure = ObjectIdEqualRegProcedure; key.data[0].argument = ObjectIdGetDatum(relation->rd_id); @ 1.37 log @remove unnecessary seeks @ text @d25 1 a25 1 * $Header: RCS/relcache.c,v 1.36 91/02/27 12:49:48 mao Exp Locker: hong $ d36 1 a36 1 RcsId("$Header: RCS/relcache.c,v 1.36 91/02/27 12:49:48 mao Exp Locker: hong $"); d403 2 a404 1 "RelationBuildTupleDesc: %s attribute %d invalid", i); @ 1.36 log @init relamsupport before we look at it. @ text @d25 1 a25 1 * $Header: RCS/relcache.c,v 1.35 91/02/19 13:58:32 mao Exp Locker: mao $ d36 1 a36 1 RcsId("$Header: RCS/relcache.c,v 1.35 91/02/19 13:58:32 mao Exp Locker: mao $"); d416 1 a517 1 relation->rd_nblocks = FileGetNumberOfBlocks(fd); a743 1 rd->rd_nblocks = FileGetNumberOfBlocks(rd->rd_fd); a774 1 rd->rd_nblocks = FileGetNumberOfBlocks(rd->rd_fd); @ 1.35 log @new rtree code installed @ text @d25 1 a25 1 * $Header: RCS/relcache.c,v 1.34 91/02/06 18:18:18 cimarron Exp Locker: mao $ d36 1 a36 1 RcsId("$Header: RCS/relcache.c,v 1.34 91/02/06 18:18:18 cimarron Exp Locker: mao $"); d588 1 a590 1 relamsupport = relation->rd_am->amsupport; @ 1.34 log @preliminary checkin for access method and system cache changes @ text @d25 1 a25 1 * $Header$ d36 1 a36 1 RcsId("$Header: RCS/relcache.c,v 1.32 90/12/29 13:30:34 mao Exp Locker: cimarron $"); d299 1 a299 1 * the tuple descriptor and the index strategy d304 2 a305 1 sizeof(IndexStrategy); d544 1 a544 3 * initialize index strategy information for this relation * remember, the index strategy lives in the memory right after * the tuple descriptor. d548 1 a548 18 IndexStrategy strategy; int stratSize; uint16 relamstrategies; relamstrategies = relation->rd_am->amstrategies; stratSize = AttributeNumberGetIndexStrategySize(natts, relamstrategies); strategy = (IndexStrategy) palloc(stratSize); IndexStrategyInitialize(strategy, relation->rd_att.data[0]->attrelid, relam, AMStrategies(relamstrategies)); RelationSetIndexStrategy(relation, strategy); d571 32 @ 1.33 log @added routine RelationIdCacheGetRelation() @ text @d2 5 a6 2 * relcache.c -- * POSTGRES relation descriptor cache code. d8 8 a15 2 * NOTE: This file is in the process of being cleaned up * before I add system attribute indexing. -cim 10/2/90 d17 3 a19 6 * OLD NOTES: * This code will leak relation descriptor sctructures. XXXX. * It will happen whenever *GetRelation() is called without a corrosponding * FreeRelation(). This will happen at a minimum when a transaction * aborts. To fix this, each transaction could keep a list of relation/ * reference count pairs. a20 13 * It is not clear who is responcible for incrementing and decrementing * the reference count and when RelationFree() should be called. I would * propose that there be calls: RelationAddUsage and RelationSubtractUsage * where AddUsage is called instead of incrementing the reference count * and SubtractUsage instead of decrementing it. SubtractUsage would * be responcible for calling RelationFree which would become a private * routine. The following files (there could be more) paly with * the refernece count: * access/{genam,logaccess}.c * spam/{spam-controll,var-access}.c * util/{access,create}.c * * Note: d23 3 d64 1 d69 6 a74 3 extern bool AMI_OVERRIDE; /* XXX style */ d76 1 a82 109 extern HeapTuple GetHeapTuple(); /* XXX use include file */ /* #define DEBUG_RELCACHE /* debug relcache... */ #ifdef DEBUG_RELCACHE # define DO_DB(A) A # define DO_NOTDB(A) /* A */ # define private /* static */ #else # define DO_DB(A) /* A */ # define DO_NOTDB(A) A # define private static #endif #define NO_DO_DB(A) /* A */ #define IN() DO_DB(ElogDebugIndentLevel++) #define OUT() DO_DB(ElogDebugIndentLevel--) /* XXX using the values in h/anum.h might be better */ #define REL_NATTS (14) #define ATT_NATTS (12) #define PRO_NATTS (10) #define TYP_NATTS (14) /* these next 3 are bogus for now... */ #define VAR_NATTS (2) #define LOG_NATTS (2) #define TIM_NATTS (2) /* * Relations are cached two ways, by name and by id, thus there are two * hash tables for referencing them. */ HashTable RelationCacheHashByName; HashTable GlobalNameCache; HashTable RelationCacheHashById; HashTable GlobalIdCache; HashTable PrivateRelationCacheHashByName; HashTable PrivateRelationCacheHashById; /* * XXX the atttyparg field is always set to 0l in the tables. * This may or may not be correct. (Depends on array semantics.) */ private AttributeTupleFormData relatt[REL_NATTS] = { { 83l, "relname", 19l, 83l, 0l, 0l, 16, 1, 0, '\0', '\001', 0l }, { 83l, "relowner", 26l, 83l, 0l, 0l, 4, 2, 0, '\001', '\001', 0l }, { 83l, "relam", 26l, 83l, 0l, 0l, 4, 3, 0, '\001', '\001', 0l }, { 83l, "relpages", 23, 83l, 0l, 0l, 4, 4, 0, '\001', '\001', 0l }, { 83l, "reltuples", 23, 83l, 0l, 0l, 4, 5, 0, '\001', '\001', 0l }, { 83l, "relexpires", 20, 83l, 0l, 0l, 4, 6, 0, '\001', '\001', 0l }, { 83l, "relpreserved", 20, 83l, 0l, 0l, 4, 7, 0, '\001', '\001', 0l }, { 83l, "relhasindex", 16, 83l, 0l, 0l, 1, 8, 0, '\001', '\001', 0l }, { 83l, "relisshared", 16, 83l, 0l, 0l, 1, 9, 0, '\001', '\001', 0l }, { 83l, "relkind", 18, 83l, 0l, 0l, 1, 10, 0, '\001', '\001', 0l }, { 83l, "relarch", 18, 83l, 0l, 0l, 1, 11, 0, '\001', '\001', 0l }, { 83l, "relnatts", 21, 83l, 0l, 0l, 2, 12, 0, '\001', '\001', 0l }, { 83l, "relkey", 22, 83l, 0l, 0l, 16, 13, 0, '\0', '\001', 0l }, /* * { 83l, "relkeyop", 30, 83l, 0l, 0l, 32, 14, 0, '\0', '\001', 0l }, * { 83l, "rellock", 591, 0l, 0l, 0l, 8, 15, 0, '\0', '\001', 0l } */ { 83l, "relkeyop", 30, 83l, 0l, 0l, 32, 14, 0, '\0', '\001', 0l } }; private AttributeTupleFormData attatt[ATT_NATTS] = { { 75l, "attrelid", 26l, 75l, 0l, 0l, 4, 1, 0, '\001', '\001', 0l }, { 75l, "attname", 19l, 75l, 0l, 0l, 16, 2, 0, '\0', '\001', 0l }, { 75l, "atttypid", 26l, 75l, 0l, 0l, 4, 3, 0, '\001', '\001', 0l }, { 75l, "attdefrel", 26l, 75l, 0l, 0l, 4, 4, 0, '\001', '\001', 0l }, { 75l, "attnvals", 23l, 75l, 0l, 0l, 4, 5, 0, '\001', '\001', 0l }, { 75l, "atttyparg", 26l, 75l, 0l, 0l, 4, 6, 0, '\001', '\001', 0l }, { 75l, "attlen", 21l, 75l, 0l, 0l, 2, 7, 0, '\001', '\001', 0l }, { 75l, "attnum", 21l, 75l, 0l, 0l, 2, 8, 0, '\001', '\001', 0l }, { 75l, "attbound", 21l, 75l, 0l, 0l, 2, 9, 0, '\001', '\001', 0l }, { 75l, "attbyval", 16l, 75l, 0l, 0l, 1, 10, 0, '\001', '\001', 0l }, { 75l, "attcanindex", 16l, 75l, 0l, 0l, 1, 11, 0, '\001', '\001', 0l }, { 75l, "attproc", 26l, 75l, 0l, 0l, 4, 12, 0, '\001', '\001', 0l } }; private AttributeTupleFormData proatt[PRO_NATTS] = { { 81l, "proname", 19l, 81l, 0l, 0l, 16, 1, 0, '\0', '\001', 0l }, { 81l, "proowner", 26l, 81l, 0l, 0l, 4, 2, 0, '\001', '\001', 0l }, { 81l, "prolang", 26l, 81l, 0l, 0l, 4, 3, 0, '\001', '\001', 0l }, { 81l, "proisinh", 16l, 81l, 0l, 0l, 1, 4, 0, '\001', '\001', 0l }, { 81l, "proistrusted", 16l, 81l, 0l, 0l, 1, 5, 0, '\001', '\001', 0l }, { 81l, "proiscachable", 16l, 81l, 0l, 0l, 1, 6, 0, '\001', '\001', 0l }, { 81l, "pronargs", 21l, 81l, 0l, 0l, 2, 7, 0, '\001', '\001', 0l }, { 81l, "prorettype", 26l, 81l, 0l, 0l, 4, 8, 0, '\001', '\001', 0l }, { 81l, "prosrc", 25l, 81l, 0l, 0l, -1, 9, 0, '\0', '\001', 0l }, { 81l, "probin", 17l, 81l, 0l, 0l, -1, 10, 0, '\0', '\001', 0l } }; private AttributeTupleFormData typatt[TYP_NATTS] = { { 71l, "typname", 19l, 71l, 0l, 0l, 16, 1, 0, '\0', '\001', 0l }, { 71l, "typowner", 26l, 71l, 0l, 0l, 4, 2, 0, '\001', '\001', 0l }, { 71l, "typlen", 21l, 71l, 0l, 0l, 2, 3, 0, '\001', '\001', 0l }, { 71l, "typprtlen", 21l, 71l, 0l, 0l, 2, 4, 0, '\001', '\001', 0l }, { 71l, "typbyval", 16l, 71l, 0l, 0l, 1, 5, 0, '\001', '\001', 0l }, { 71l, "typisproc", 16l, 71l, 0l, 0l, 1, 6, 0, '\001', '\001', 0l }, { 71l, "typisdefined", 16l, 71l, 0l, 0l, 1, 7, 0, '\001', '\001', 0l }, { 71l, "typprocid", 26l, 71l, 0l, 0l, 4, 8, 0, '\001', '\001', 0l }, { 71l, "typelem", 26l, 71l, 0l, 0l, 4, 9, 0, '\001', '\001', 0l }, { 71l, "typinput", 24l, 71l, 0l, 0l, 4, 10, 0, '\001', '\001', 0l }, { 71l, "typoutput", 24l, 71l, 0l, 0l, 4, 11, 0, '\001', '\001', 0l }, { 71l, "typreceive", 24l, 71l, 0l, 0l, 4, 12, 0, '\001', '\001', 0l }, { 71l, "typsend", 24l, 71l, 0l, 0l, 4, 13, 0, '\001', '\001', 0l }, { 71l, "typdefault", 25l, 71l, 0l, 0l, -1, 14, 0, '\0', '\001', 0l } }; d84 1 a84 3 * XXX * these are bogus, the values come from the bogus entries * in the local.ami script d87 1 a87 34 private AttributeTupleFormData varatt[VAR_NATTS] = { { 90l, "varname", 19l, 90l, 0l, 0l, 16, 1, 0, 0, '\001', 0l }, { 90l, "varvalue", 17l, 90l, 0l, 0l, -1, 2, 0, 0, '\001', 0l }, }; private AttributeTupleFormData logatt[LOG_NATTS] = { { 91l, "varname", 19l, 91l, 0l, 0l, 16, 1, 0, 0, '\001', 0l }, { 91l, "varvalue", 17l, 91l, 0l, 0l, -1, 2, 0, 0, '\001', 0l }, }; private AttributeTupleFormData timatt[VAR_NATTS] = { { 92l, "varname", 19l, 92l, 0l, 0l, 16, 1, 0, 0, '\001', 0l }, { 92l, "varvalue", 17l, 92l, 0l, 0l, -1, 2, 0, 0, '\001', 0l }, }; /* ---------------------------------------------------------------- * hash function support * * XXX where are these used??? * ---------------------------------------------------------------- */ /* -------------------------------- * HashByNameAsArgument * -------------------------------- */ private Index HashByNameAsArgument(collisions, hashTableSize, relationName) uint16 collisions; Size hashTableSize; Name relationName; { return NameHashFunction(collisions, hashTableSize, relationName); } d89 3 a91 3 /* -------------------------------- * HashByNameInRelation * -------------------------------- d93 1 a93 9 private Index HashByNameInRelation(collisions, hashTableSize, relation) uint16 collisions; Size hashTableSize; Relation relation; { return NameHashFunction(collisions, hashTableSize, &relation->rd_rel->relname); } d95 3 a97 3 /* -------------------------------- * HashByIdAsArgument * -------------------------------- d99 7 a105 9 private Index HashByIdAsArgument(collisions, hashTableSize, relationId) uint16 collisions; Size hashTableSize; uint32 relationId; { return IntegerHashFunction(collisions, hashTableSize, relationId); } d107 6 a112 3 /* -------------------------------- * HashByIdInRelation * -------------------------------- d114 6 a119 9 private Index HashByIdInRelation(collisions, hashTableSize, relation) uint16 collisions; Size hashTableSize; Relation relation; { return IntegerHashFunction(collisions, hashTableSize, relation->rd_id); } d122 1 a122 1 * RelationIdGetRelation() and getreldesc() d127 16 a142 1 /* -------------------------------- a165 2 IN(); d174 2 a175 3 OUT(); return (file); d177 24 d203 1 a203 3 * GetAttributeRelationIndexRelationId -- * * find relation id of the index of relation id's on the attribute relation d205 5 a209 2 * attempt to return the object id of an index relation of * RelationId on the AttributeRelation. d212 3 a214 12 #define UNTRIED 0 #define FOUND 1 #define FAILED 2 #define TRYING 3 #define TRIED 4 /**** xxref: * BuildRelation ****/ private ObjectId GetAttributeRelationIndexRelationId () d216 4 a219 2 HeapTuple tuple; ObjectId objectId; d221 3 a223 14 static int state = UNTRIED; /* * XXX The next line is incorrect. It should be removed if the * performance penalty is not too great or if indexes are added * and dropped frequently. A more clever hack which will produce * correct behavior in a *single-user* situation is to keep a * global variable which is incremented each time DEFINE INDEX * is called. Then if the state is FAILED and a index has been * created since the last call to this function, then treat the * state as UNTRIED. But, this hack works incorrectly in a * multiuser environment. The correct thing to do is to have the * system cache keep information about failed search and to have * this information invalidated when a tuple is appended. -hirohama d225 19 a243 4 IN(); if (state == FAILED) { OUT(); return InvalidObjectId; d246 3 a248 4 /* * We don't want any infinately recusive calls to this * routine because SearchSysCacheTuple does some relation * descriptor lookups. d250 37 a286 1 state = FAILED; d288 3 a290 4 /* * The syscache must be searched again in the case of FOUND state * since the result may have been invalidated since the last call * to this function. d292 2 a293 9 tuple = SearchSysCacheTuple(INDRELIDKEY, AttributeRelationId, AttributeRelationIdAttributeNumber); if (!HeapTupleIsValid(tuple)) { OUT(); state = FAILED; return InvalidObjectId; } d295 1 a295 1 objectId = ((IndexTupleForm) HeapTupleGetForm(tuple))-> indexrelid; d297 19 a315 4 state = FOUND; OUT(); return objectId; d317 1 a317 1 d319 6 a324 1 * BuildRelationAttributes d327 6 a332 7 /**** xxref: * BuildRelation ****/ private inline void BuildRelationAttributes(attp, relation, errorName) AttributeTupleForm attp; Relation relation; d334 14 a347 4 IN(); if (!AttributeNumberIsValid(attp->attnum)) elog(WARN, "getreldesc: found zero attnum %s", errorName); d349 27 a375 1 if (AttributeNumberIsForUserDefinedAttribute(attp->attnum)) { d377 2 a378 4 if (AttributeIsValid(relation->rd_att.data[attp->attnum - 1])) elog(WARN, "getreldesc: corrupted ATTRIBUTE %s",errorName); relation->rd_att.data[attp->attnum - 1] = (Attribute) palloc(sizeof (RuleLock) + sizeof *relation->rd_att.data[0]); d380 4 a383 2 bcopy((char *)attp, (char *)relation->rd_att.data[attp->attnum - 1], sizeof *relation->rd_att.data[0]); d386 18 a403 1 OUT(); d405 1 a405 1 d407 19 a425 1 * BuildRelation d428 3 a430 13 /**** xxref: * RelationIdGetRelation * getreldesc ****/ private Relation BuildRelation(rd, sd, errorName, oldcxt, tuple, NameCacheSave, IdCacheSave) Relation rd; HeapScanDesc sd; String errorName; MemoryContext oldcxt; HeapTuple tuple; HashTable NameCacheSave; HashTable IdCacheSave; a431 1 static bool avoidIndex = false; d434 1 a434 2 int len; u_int numatts, natts; d436 1 a438 1 ScanKeyData key; d440 3 d444 3 a446 1 RelationTupleForm relationTupleForm; d448 8 a455 1 extern pfree(); d457 16 a472 4 if (!HeapTupleIsValid(tuple)) { elog(NOTICE, "BuildRelation: %s relation nonexistent", errorName); amendscan(sd); amclose(rd); d477 1 a477 1 return (NULL); d479 8 d488 7 a494 2 fd = relopen(&((RelationTupleForm) GETSTRUCT(tuple))->relname, O_RDWR, 0666); a495 10 Assert (fd >= -1); if (fd == -1) { elog(NOTICE, "BuildRelation: relopen(%s): %m", &((RelationTupleForm)GETSTRUCT(tuple))->relname); } relid = tuple->t_oid; relp = (RelationTupleForm) HeapTupleGetForm(tuple); numatts = natts = relp->relnatts; d497 1 a497 2 * allocate space for the relation descriptor, including * the index strategy (this is a hack) d500 1 a500 3 len = sizeof(RelationData) + ((int)natts - 1) * sizeof(relation->rd_att) + /* var len struct */ sizeof(IndexStrategy); a501 68 relationTupleForm = (RelationTupleForm) palloc(sizeof (RuleLock) + sizeof *relation->rd_rel); /* should use relp->relam to create this */ bcopy((char *)relp, (char *)relationTupleForm, sizeof *relp); amendscan(sd); amclose(rd); if (!ObjectIdIsValid(relationTupleForm->relam)) { relation = (Relation)palloc(len); bzero((char *)relation, len); relation->rd_rel = relationTupleForm; } else { AccessMethodTupleForm accessMethodTupleForm; /* ---------------- * ADD INDEXING HERE * ---------------- */ rd = amopenr(AccessMethodRelationName); key.data[0].flags = 0; key.data[0].attributeNumber = ObjectIdAttributeNumber; key.data[0].procedure = ObjectIdEqualRegProcedure; key.data[0].argument = ObjectIdGetDatum(relationTupleForm->relam); sd = ambeginscan(rd, 0, NowTimeQual, 1, &key); tuple = amgetnext(sd, 0, (Buffer *)NULL); if (!HeapTupleIsValid(tuple)) { elog(NOTICE, "BuildRelation: %s: unknown AM %d", errorName, relationTupleForm->relam); /* amendscan(sd); amclose(rd); return (NULL); */ RelationCacheHashByName = NameCacheSave; RelationCacheHashById = IdCacheSave; } accessMethodTupleForm = (AccessMethodTupleForm) palloc(sizeof *relation->rd_am); bcopy((char *)HeapTupleGetForm(tuple), accessMethodTupleForm, sizeof *accessMethodTupleForm); amendscan(sd); amclose(rd); /* * this was removed because the index strategy is now * a pointer and it alrwady has it's space allocated above.. * * len += AttributeNumberGetIndexStrategySize( * relationTupleForm->relnatts, * AMStrategies(accessMethodTupleForm->amstrategies)); */ relation = (Relation)palloc(len); bzero((char *)relation, len); relation->rd_rel = relationTupleForm; relation->rd_am = accessMethodTupleForm; } d503 3 a505 1 * ADD INDEXING HERE (correctly) d508 1 a508 4 key.data[0].flags = 0; key.data[0].attributeNumber = AttributeRelationIdAttributeNumber; key.data[0].procedure = ObjectIdEqualRegProcedure; key.data[0].argument = ObjectIdGetDatum(relid); d510 4 a513 1 attrioid = GetAttributeRelationIndexRelationId(); a514 74 if (ObjectIdIsValid(attrioid) && !avoidIndex) { /* * indexed scan of Attribute Relation */ IndexScanDesc scan; GeneralRetrieveIndexResult result; Relation attrd; Relation attrird; Buffer buffer; /* * avoidIndex prevents a recursive call to this code. I think * it would recurse indefinately. It is okay to have to * do this one scan the long way because the result will * be cached. */ attrd = RelationIdGetRelation(AttributeRelationId); avoidIndex = true; attrird = RelationIdGetRelation(attrioid); avoidIndex = false; scan = RelationGetIndexScan(attrird, 0, 1, &key); for(;;) { /* Get rid of loop? Just use first index? */ IndexTuple indexTuple; result = IndexScanGetGeneralRetrieveIndexResult(scan, 1); if (! GeneralRetrieveIndexResultIsValid(result)) break; /* * XXX * * the buffer should be freed.... * * however, the buffer won't be retured and thus * wont't be freed. (bug) */ tuple = GetHeapTuple(result, attrd, &buffer); if (!HeapTupleIsValid(tuple)) break; attp = (AttributeTupleForm) HeapTupleGetForm(tuple); BuildRelationAttributes(attp, relation, errorName); } IndexScanEnd(scan); RelationFree(attrd); RelationFree(attrird); } else { /* * sequential scan of Attribute Relation */ rd = amopenr(AttributeRelationName); sd = ambeginscan(rd, 0, NowTimeQual, 1, &key); while (tuple = amgetnext(sd, 0, (Buffer *) NULL), HeapTupleIsValid(tuple)) { attp = (AttributeTupleForm) HeapTupleGetForm(tuple); BuildRelationAttributes(attp, relation, errorName); } amendscan(sd); amclose(rd); } while ((int)--natts >= 0) { if (!AttributeIsValid(relation->rd_att.data[natts])) elog(NOTICE, "getreldesc: ATTRIBUTE relation corrupted %s", errorName); } d517 5 a521 1 d524 30 a553 3 if (ObjectIdIsValid(relation->rd_rel->relam)) { IndexStrategy strategy; int stratSize; d556 1 a556 2 AttributeNumberGetIndexStrategySize(numatts, relation->rd_am->amstrategies); d562 3 a564 4 RelationGetTupleDescriptor(relation)->data[0]->attrelid, RelationGetRelationTupleForm(relation)->relam, AMStrategies( RelationGetAccessMethodTupleForm(relation)->amstrategies)); d566 1 a566 1 RelationSetIndexStrategy(relation,strategy); d568 6 d575 5 a579 2 relation->rd_id = relid; a585 2 RelationInitLockInfo(relation); a587 2 RelationInitLockInfo(relation); d590 103 d694 7 a700 1 /* -------------------------------- d704 2 a705 2 * do not go to the disk * this is for BlockPrepareFile() d710 1 a710 1 ObjectId relationId; d712 1 a712 1 Relation rd; d721 2 a722 2 if (rd -> rd_fd == -1) { rd -> rd_fd = relopen (&rd -> rd_rel -> relname, d724 1 a724 1 Assert (rd -> rd_fd != -1); d726 1 d728 1 d730 1 a730 1 RelationSetLockForDescriptorOpen(rd); d737 1 a737 1 * RelationIdGetRelation a739 3 /**** xxref: * BuildRelation ****/ d741 2 a742 2 RelationIdGetRelation(relationId) ObjectId relationId; d744 2 a745 16 Relation rd; HeapScanDesc sd; ScanKeyData key; char errorName[50]; extern GlobalMemory CacheCxt; MemoryContext oldcxt; HeapTuple tuple; HashTable NameCacheSave; HashTable IdCacheSave; IN(); /* if not in the current cache, check the global cache */ d747 1 a747 1 KeyHashTableLookup(RelationCacheHashById, relationId); d750 2 a751 2 rd = (Relation) KeyHashTableLookup(GlobalIdCache, relationId); d753 4 a756 4 if (rd -> rd_fd == -1) { rd -> rd_fd = relopen (&rd -> rd_rel -> relname, O_RDWR | O_CREAT, 0666); Assert (rd -> rd_fd != -1); d758 1 a759 1 d762 1 a762 1 return rd; d765 16 a780 4 NameCacheSave = RelationCacheHashByName; IdCacheSave = RelationCacheHashById; RelationCacheHashByName = PrivateRelationCacheHashByName; RelationCacheHashById = PrivateRelationCacheHashById; d782 14 a795 1 oldcxt = MemoryContextSwitchTo(CacheCxt); d797 7 a803 1 rd = amopenr(RelationRelationName); d805 3 a807 21 key.data[0].flags = 0; key.data[0].attributeNumber = ObjectIdAttributeNumber; key.data[0].procedure = ObjectIdEqualRegProcedure; key.data[0].argument = ObjectIdGetDatum(relationId); sd = ambeginscan(rd, 0, NowTimeQual, 1, &key); tuple = amgetnext(sd, 0, (Buffer *)NULL); if (!HeapTupleIsValid(tuple)) { sprintf(errorName, "RelationId=%d", relationId); } else { sprintf(errorName, "%s (id: %d)", &((RelationTupleForm)GETSTRUCT(tuple))->relname, relationId); } rd = BuildRelation(rd, sd, errorName, oldcxt, tuple, NameCacheSave, IdCacheSave); return rd; d809 1 a809 1 d811 1 a811 1 * getreldesc / RelationNameGetRelation a816 1 d818 1 a818 1 getreldesc(relationName) d821 2 a822 3 Relation rd; HeapScanDesc sd; ScanKeyData key; d824 14 a837 2 extern GlobalMemory CacheCxt; MemoryContext oldcxt; d839 7 a845 3 HeapTuple tuple; HashTable NameCacheSave; HashTable IdCacheSave; d847 13 a859 34 IN(); /* if not in the current cache, check the global cache */ rd = (Relation) KeyHashTableLookup(RelationCacheHashByName,relationName); if (! RelationIsValid(rd)) rd = (Relation) KeyHashTableLookup(GlobalNameCache, relationName); if (RelationIsValid(rd)) { if (rd -> rd_fd == -1) { rd -> rd_fd = relopen (&rd->rd_rel->relname, O_RDWR | O_CREAT, 0666); Assert (rd->rd_fd != -1); } RelationIncrementReferenceCount(rd); OUT(); RelationSetLockForDescriptorOpen(rd); rd->rd_nblocks = FileGetNumberOfBlocks(rd->rd_fd); return rd; } NameCacheSave = RelationCacheHashByName; IdCacheSave = RelationCacheHashById; RelationCacheHashByName = PrivateRelationCacheHashByName; RelationCacheHashById = PrivateRelationCacheHashById; oldcxt = MemoryContextSwitchTo(CacheCxt); d861 1 a861 1 * ADD INDEXING HERE d864 2 a865 1 rd = amopenr(RelationRelationName); d867 2 a868 15 key.data[0].flags = 0; key.data[0].attributeNumber = RelationNameAttributeNumber; key.data[0].procedure = Character16EqualRegProcedure; key.data[0].argument = NameGetDatum(relationName); sd = ambeginscan(rd, 0, NowTimeQual, 1, &key); tuple = amgetnext(sd, 0, (Buffer *)NULL); rd = BuildRelation(rd, sd, relationName, oldcxt, tuple, NameCacheSave, IdCacheSave); OUT(); return rd; d870 1 a870 1 d877 12 a904 2 IN(); a930 2 OUT(); a980 1 IN(); a982 1 OUT(); a995 1 IN(); a997 1 OUT(); a1000 13 * RelationFree * -------------------------------- */ /**** xxref: * BuildRelation ****/ void RelationFree(relation) Relation relation; { } /* -------------------------------- a1075 72 * formrdesc * * this is used to create relation descriptors for * RelationInitialize() below. * -------------------------------- */ /**** xxref: * RelationInitialize ****/ private void formrdesc(relationName, reloid, natts, att, initialReferenceCount) char relationName[]; OID reloid; /* XXX unused */ u_int natts; AttributeTupleFormData att[]; int initialReferenceCount; { Relation relation; int fd; int len; int i; char *relpath(); File relopen(); Relation publicCopy; len = sizeof *relation + ((int)natts - 1) * sizeof relation->rd_att; relation = (Relation) palloc(len); bzero((char *)relation, len); relation->rd_fd = -1; RelationSetReferenceCount(relation, 1); relation->rd_rel = (RelationTupleForm) palloc(sizeof (RuleLock) + sizeof *relation->rd_rel); strncpy(&relation->rd_rel->relname, relationName, 16); relation->rd_rel->relowner = InvalidObjectId; /* XXX incorrect */ relation->rd_rel->relpages = 1; /* XXX */ relation->rd_rel->reltuples = 1; /* XXX */ relation->rd_rel->relhasindex = '\0'; relation->rd_rel->relkind = 'r'; relation->rd_rel->relarch = 'n'; relation->rd_rel->relnatts = (uint16)natts; for (i = 0; i < natts; i++) { relation->rd_att.data[i] = (Attribute) palloc(sizeof (RuleLock) + sizeof *relation->rd_att.data[0]); bzero((char *)relation->rd_att.data[i], sizeof (RuleLock) + sizeof *relation->rd_att.data[0]); bcopy((char *)&att[i], (char *)relation->rd_att.data[i], sizeof *relation->rd_att.data[0]); } relation->rd_id = relation->rd_att.data[0]->attrelid; HashTableInsert(PrivateRelationCacheHashByName, relation); HashTableInsert(PrivateRelationCacheHashById, relation); if (initialReferenceCount != 0) { publicCopy = (Relation)palloc(len); bcopy(relation, publicCopy, len); RelationSetReferenceCount(publicCopy, initialReferenceCount); HashTableInsert(RelationCacheHashByName, publicCopy); HashTableInsert(RelationCacheHashById, publicCopy); RelationInitLockInfo(relation); /* XXX unuseful here ??? */ } } /* -------------------------------- d1101 60 d1162 2 d1172 5 a1176 3 IN(); d1181 5 a1185 1 d1204 13 a1216 6 /* * these should use a hash function that is perfect on them * and the hash table code should have a way of telling it not * to bother trying to resize 'cauase they all fit and there * arn't any collisions. Also, the hash table code could have * a HashTableDisableModification call. d1232 5 a1237 1 a1238 1 /* a hack to prevent generation of the special descriptors */ a1241 12 formrdesc(RelationRelationName, relatt[0].attrelid, REL_NATTS, relatt, initialReferences); formrdesc(AttributeRelationName, attatt[0].attrelid, ATT_NATTS, attatt, initialReferences); formrdesc(ProcedureRelationName, proatt[0].attrelid, PRO_NATTS, proatt, initialReferences); formrdesc(TypeRelationName, typatt[0].attrelid, TYP_NATTS, typatt, initialReferences); d1243 3 a1245 2 * the var, log, and time relations * are also cached... d1248 6 a1253 2 formrdesc(VariableRelationName, varatt[0].attrelid, VAR_NATTS, varatt, 0x1fff); d1255 4 a1258 2 formrdesc(LogRelationName, logatt[0].attrelid, LOG_NATTS, logatt, 0x1fff); d1260 1 a1260 2 formrdesc(TimeRelationName, timatt[0].attrelid, TIM_NATTS, timatt, 0x1fff); d1262 4 a1266 2 OUT(); @ 1.32 log @save index strategy in reldesc after constructing it @ text @d40 1 a40 1 RcsId("$Header: RCS/relcache.c,v 1.31 90/11/14 08:28:18 kemnitz Exp Locker: mao $"); d687 34 @ 1.31 log @Got rid of declaration of umask() so as to be compatible with OS's that declare it in include files as something other than int. @ text @d40 1 a40 1 RcsId("$Header: ./utils/cache/RCS/relcache.c,v 1.30 90/10/05 17:45:35 cimarron Exp Locker: kemnitz $"); d666 2 @ 1.30 log @cleaned up things so that index scans may be used with system caches. @ text @d40 1 a40 1 RcsId("$Header: RCS/relcache.c,v 1.29 90/09/29 16:32:43 hong Exp Locker: cimarron $"); a301 1 int umask(); d306 1 a306 1 oumask = umask(0077); @ 1.29 log @added a routine that registers reldescs of temp relations created by other backends. @ text @d1 1 a1 1 /* d5 4 a8 1 * Note: d30 1 a31 1 d35 1 d37 1 a37 1 d40 2 a41 2 RcsId("$Header: RCS/relcache.c,v 1.28 90/09/21 11:21:57 goh Exp Locker: hong $"); d52 1 a52 1 d55 1 d59 1 d65 1 a65 1 d72 1 a72 1 d74 1 a74 1 a75 1 d81 1 a81 1 d83 1 a83 1 a84 1 d94 1 a95 1 d98 1 a98 1 d104 1 a104 1 d109 1 a109 1 a113 1 a117 1 d120 1 a120 1 a124 1 d126 13 a138 13 { 83l, "relname", 19l, 83l, 0l, 0l, 16, 1, 0, '\0', '\001', 0l }, { 83l, "relowner", 26l, 83l, 0l, 0l, 4, 2, 0, '\001', '\001', 0l }, { 83l, "relam", 26l, 83l, 0l, 0l, 4, 3, 0, '\001', '\001', 0l }, { 83l, "relpages", 23, 83l, 0l, 0l, 4, 4, 0, '\001', '\001', 0l }, { 83l, "reltuples", 23, 83l, 0l, 0l, 4, 5, 0, '\001', '\001', 0l }, { 83l, "relexpires", 20, 83l, 0l, 0l, 4, 6, 0, '\001', '\001', 0l }, { 83l, "relpreserved", 20, 83l, 0l, 0l, 4, 7, 0, '\001', '\001', 0l }, { 83l, "relhasindex", 16, 83l, 0l, 0l, 1, 8, 0, '\001', '\001', 0l }, { 83l, "relisshared", 16, 83l, 0l, 0l, 1, 9, 0, '\001', '\001', 0l }, { 83l, "relkind", 18, 83l, 0l, 0l, 1, 10, 0, '\001', '\001', 0l }, { 83l, "relarch", 18, 83l, 0l, 0l, 1, 11, 0, '\001', '\001', 0l }, { 83l, "relnatts", 21, 83l, 0l, 0l, 2, 12, 0, '\001', '\001', 0l }, { 83l, "relkey", 22, 83l, 0l, 0l, 16, 13, 0, '\0', '\001', 0l }, d140 4 a143 4 { 83l, "relkeyop", 30, 83l, 0l, 0l, 32, 14, 0, '\0', '\001', 0l }, { 83l, "rellock", 591, 0l, 0l, 0l, 8, 15, 0, '\0', '\001', 0l } */ { 83l, "relkeyop", 30, 83l, 0l, 0l, 32, 14, 0, '\0', '\001', 0l } d145 1 d147 12 a158 12 { 75l, "attrelid", 26l, 75l, 0l, 0l, 4, 1, 0, '\001', '\001', 0l }, { 75l, "attname", 19l, 75l, 0l, 0l, 16, 2, 0, '\0', '\001', 0l }, { 75l, "atttypid", 26l, 75l, 0l, 0l, 4, 3, 0, '\001', '\001', 0l }, { 75l, "attdefrel", 26l, 75l, 0l, 0l, 4, 4, 0, '\001', '\001', 0l }, { 75l, "attnvals", 23l, 75l, 0l, 0l, 4, 5, 0, '\001', '\001', 0l }, { 75l, "atttyparg", 26l, 75l, 0l, 0l, 4, 6, 0, '\001', '\001', 0l }, { 75l, "attlen", 21l, 75l, 0l, 0l, 2, 7, 0, '\001', '\001', 0l }, { 75l, "attnum", 21l, 75l, 0l, 0l, 2, 8, 0, '\001', '\001', 0l }, { 75l, "attbound", 21l, 75l, 0l, 0l, 2, 9, 0, '\001', '\001', 0l }, { 75l, "attbyval", 16l, 75l, 0l, 0l, 1, 10, 0, '\001', '\001', 0l }, { 75l, "attcanindex", 16l, 75l, 0l, 0l, 1, 11, 0, '\001', '\001', 0l }, { 75l, "attproc", 26l, 75l, 0l, 0l, 4, 12, 0, '\001', '\001', 0l } d160 1 d162 10 a171 10 { 81l, "proname", 19l, 81l, 0l, 0l, 16, 1, 0, '\0', '\001', 0l }, { 81l, "proowner", 26l, 81l, 0l, 0l, 4, 2, 0, '\001', '\001', 0l }, { 81l, "prolang", 26l, 81l, 0l, 0l, 4, 3, 0, '\001', '\001', 0l }, { 81l, "proisinh", 16l, 81l, 0l, 0l, 1, 4, 0, '\001', '\001', 0l }, { 81l, "proistrusted", 16l, 81l, 0l, 0l, 1, 5, 0, '\001', '\001', 0l }, { 81l, "proiscachable", 16l, 81l, 0l, 0l, 1, 6, 0, '\001', '\001', 0l }, { 81l, "pronargs", 21l, 81l, 0l, 0l, 2, 7, 0, '\001', '\001', 0l }, { 81l, "prorettype", 26l, 81l, 0l, 0l, 4, 8, 0, '\001', '\001', 0l }, { 81l, "prosrc", 25l, 81l, 0l, 0l, -1, 9, 0, '\0', '\001', 0l }, { 81l, "probin", 17l, 81l, 0l, 0l, -1, 10, 0, '\0', '\001', 0l } d173 1 d175 14 a188 14 { 71l, "typname", 19l, 71l, 0l, 0l, 16, 1, 0, '\0', '\001', 0l }, { 71l, "typowner", 26l, 71l, 0l, 0l, 4, 2, 0, '\001', '\001', 0l }, { 71l, "typlen", 21l, 71l, 0l, 0l, 2, 3, 0, '\001', '\001', 0l }, { 71l, "typprtlen", 21l, 71l, 0l, 0l, 2, 4, 0, '\001', '\001', 0l }, { 71l, "typbyval", 16l, 71l, 0l, 0l, 1, 5, 0, '\001', '\001', 0l }, { 71l, "typisproc", 16l, 71l, 0l, 0l, 1, 6, 0, '\001', '\001', 0l }, { 71l, "typisdefined", 16l, 71l, 0l, 0l, 1, 7, 0, '\001', '\001', 0l }, { 71l, "typprocid", 26l, 71l, 0l, 0l, 4, 8, 0, '\001', '\001', 0l }, { 71l, "typelem", 26l, 71l, 0l, 0l, 4, 9, 0, '\001', '\001', 0l }, { 71l, "typinput", 24l, 71l, 0l, 0l, 4, 10, 0, '\001', '\001', 0l }, { 71l, "typoutput", 24l, 71l, 0l, 0l, 4, 11, 0, '\001', '\001', 0l }, { 71l, "typreceive", 24l, 71l, 0l, 0l, 4, 12, 0, '\001', '\001', 0l }, { 71l, "typsend", 24l, 71l, 0l, 0l, 4, 13, 0, '\001', '\001', 0l }, { 71l, "typdefault", 25l, 71l, 0l, 0l, -1, 14, 0, '\0', '\001', 0l } d190 1 a190 1 a196 1 d201 1 a201 1 d206 1 a206 1 d211 6 a216 3 /* * Private Routines d218 3 a220 14 private Relation BuildRelation ARGS(( Relation rd, HeapScanDesc sd, String errorName, struct context *oldcx HashTable NameCacheSave; HashTable IdCacheSave; )); /* * RelationFlushIndexes -- d222 9 a230 5 private void RelationFlushIndexes ARGS(( ObjectId accessMethodId )); d232 3 a234 2 /* * find relation id of the index of relation id's on the attribute relation d236 5 a240 18 private ObjectId GetAttributeRelationIndexRelationId ARGS(()); private inline void BuildRelationAttributes ARGS(( AttributeTupleForm attp, Relation relation, Name errorName )); Relation RelationIdGetRelation(relationId) ObjectId relationId; d242 2 a243 60 Relation rd; HeapScanDesc sd; ScanKeyData key; char errorName[50]; extern GlobalMemory CacheCxt; MemoryContext oldcxt; HeapTuple tuple; HashTable NameCacheSave; HashTable IdCacheSave; IN(); /* if not in the current cache, check the global cache */ rd = (Relation)KeyHashTableLookup(RelationCacheHashById,relationId); if (!RelationIsValid(rd)) rd = (Relation) KeyHashTableLookup(GlobalIdCache, relationId); if (RelationIsValid(rd)) { if (rd -> rd_fd == -1) { rd -> rd_fd = relopen (&rd -> rd_rel -> relname, O_RDWR | O_CREAT, 0666); Assert (rd -> rd_fd != -1); } RelationIncrementReferenceCount(rd); RelationSetLockForDescriptorOpen(rd); return rd; } NameCacheSave = RelationCacheHashByName; IdCacheSave = RelationCacheHashById; RelationCacheHashByName = PrivateRelationCacheHashByName; RelationCacheHashById = PrivateRelationCacheHashById; oldcxt = MemoryContextSwitchTo(CacheCxt); rd = amopenr(RelationRelationName); key.data[0].flags = 0; key.data[0].attributeNumber = ObjectIdAttributeNumber; key.data[0].procedure = ObjectIdEqualRegProcedure; key.data[0].argument = ObjectIdGetDatum(relationId); sd = ambeginscan(rd, 0, NowTimeQual, 1, &key); tuple = amgetnext(sd, 0, (Buffer *)NULL); if (!HeapTupleIsValid(tuple)) { sprintf(errorName, "RelationId=%d", relationId); } else { sprintf(errorName, "%s (id: %d)", &((RelationTupleForm)GETSTRUCT(tuple))->relname, relationId); } rd = BuildRelation(rd, sd, errorName, oldcxt, tuple, NameCacheSave, IdCacheSave); return rd; d245 4 a248 7 /* * Relation Name Get Relation -- (getreldesc for the time being) * * return a relation descriptor based on its name. * * return a cached value if possible d250 5 a254 4 Relation getreldesc(relationName) Name relationName; d256 16 a271 62 Relation rd; HeapScanDesc sd; ScanKeyData key; extern GlobalMemory CacheCxt; MemoryContext oldcxt; HeapTuple tuple; HashTable NameCacheSave; HashTable IdCacheSave; IN(); NO_DO_DB(elog(NOIND,"getreldesc: %s", relationName)); /* if not in the current cache, check the global cache */ rd = (Relation)KeyHashTableLookup(RelationCacheHashByName,relationName); if (!RelationIsValid(rd)) rd = (Relation) KeyHashTableLookup(GlobalNameCache, relationName); NO_DO_DB(if (rd != NULL) { elog(NOIND,"rd = (%x) %s",rd,&rd->rd_rel->relname); } else elog(NOIND,"rd = %x",rd);) if (RelationIsValid(rd)) { if (rd -> rd_fd == -1) { rd -> rd_fd = relopen (&rd -> rd_rel -> relname, O_RDWR | O_CREAT, 0666); Assert (rd -> rd_fd != -1); } RelationIncrementReferenceCount(rd); DO_DB(elog(NOIND,"getreldesc: found %s hashed", relationName)); OUT(); RelationSetLockForDescriptorOpen(rd); rd->rd_nblocks = FileGetNumberOfBlocks(rd->rd_fd); return rd; } DO_DB(elog(NOIND,"getreldesc: building %s", relationName)); NameCacheSave = RelationCacheHashByName; IdCacheSave = RelationCacheHashById; RelationCacheHashByName = PrivateRelationCacheHashByName; RelationCacheHashById = PrivateRelationCacheHashById; oldcxt = MemoryContextSwitchTo(CacheCxt); rd = amopenr(RelationRelationName); key.data[0].flags = 0; key.data[0].attributeNumber = RelationNameAttributeNumber; key.data[0].procedure = Character16EqualRegProcedure; key.data[0].argument = NameGetDatum(relationName); sd = ambeginscan(rd, 0, NowTimeQual, 1, &key); tuple = amgetnext(sd, 0, (Buffer *)NULL); rd = BuildRelation(rd, sd, relationName,oldcxt, tuple, NameCacheSave, IdCacheSave); OUT(); return rd; d273 26 a298 12 private Relation BuildRelation(rd, sd, errorName, oldcxt, tuple, NameCacheSave, IdCacheSave) Relation rd; HeapScanDesc sd; String errorName; MemoryContext oldcxt; HeapTuple tuple; HashTable NameCacheSave; HashTable IdCacheSave; d300 18 a317 260 static bool avoidIndex = false; File fd; Relation relation; int len; u_int numatts, natts; ObjectId relid; RelationTupleForm relp; AttributeTupleForm attp; ScanKeyData key; ObjectId attrioid; /* attribute relation index relation object id */ RelationTupleForm relationTupleForm; extern pfree(); DO_DB(elog(NOIND,"now at %d in %s", __LINE__, "relcache.c");) if (!HeapTupleIsValid(tuple)) { elog(NOTICE, "BuildRelation: %s relation nonexistent", errorName); NO_DO_DB(puts("I'm here...")); amendscan(sd); amclose(rd); RelationCacheHashByName = NameCacheSave; RelationCacheHashById = IdCacheSave; MemoryContextSwitchTo(oldcxt); return (NULL); } DO_DB(elog(NOIND,"now at %d in %s", __LINE__, "relcache.c");) fd = relopen(&((RelationTupleForm)GETSTRUCT(tuple))->relname, O_RDWR, 0666); Assert (fd >= -1); if (fd == -1) { elog(NOTICE, "BuildRelation: relopen(%s): %m", &((RelationTupleForm)GETSTRUCT(tuple))->relname); } relid = tuple->t_oid; relp = (RelationTupleForm)HeapTupleGetForm(tuple); numatts = natts = relp->relnatts; /* ---------------- * allocate space for the relation descriptor, including * the index strategy (this is a hack) * ---------------- */ DO_DB(elog(NOIND,"now at %d in %s", __LINE__, "relcache.c");) len = sizeof(RelationData) + ((int)natts - 1) * sizeof(relation->rd_att) + /* var len struct */ sizeof(IndexStrategy); relationTupleForm = (RelationTupleForm)palloc(sizeof (RuleLock) + sizeof *relation->rd_rel); /* should use relp->relam to create this */ bcopy((char *)relp, (char *)relationTupleForm, sizeof *relp); NO_DO_DB(puts("but now I'm here")); amendscan(sd); amclose(rd); DO_DB(elog(NOIND,"now at %d in %s", __LINE__, "relcache.c");) if (!ObjectIdIsValid(relationTupleForm->relam)) { relation = (Relation)palloc(len); bzero((char *)relation, len); relation->rd_rel = relationTupleForm; } else { AccessMethodTupleForm accessMethodTupleForm; rd = amopenr(AccessMethodRelationName); key.data[0].flags = 0; key.data[0].attributeNumber = ObjectIdAttributeNumber; key.data[0].procedure = ObjectIdEqualRegProcedure; key.data[0].argument = ObjectIdGetDatum(relationTupleForm->relam); sd = ambeginscan(rd, 0, NowTimeQual, 1, &key); DO_DB(elog(NOIND,"now at %d in %s", __LINE__, "relcache.c");) tuple = amgetnext(sd, 0, (Buffer *)NULL); if (!HeapTupleIsValid(tuple)) { elog(NOTICE, "BuildRelation: %s: unknown AM %d", errorName, relationTupleForm->relam); /* amendscan(sd); amclose(rd); return (NULL); */ RelationCacheHashByName = NameCacheSave; RelationCacheHashById = IdCacheSave; } accessMethodTupleForm = (AccessMethodTupleForm)palloc(sizeof *relation->rd_am); bcopy((char *)HeapTupleGetForm(tuple), accessMethodTupleForm, sizeof *accessMethodTupleForm); NO_DO_DB(puts("and not, I'm here")); amendscan(sd); amclose(rd); DO_DB(elog(NOIND,"now at %d in %s", __LINE__, "relcache.c");) /* this was removed because the index strategy is now a pointer and it alrwady has it's space allocated above.. len += AttributeNumberGetIndexStrategySize( relationTupleForm->relnatts, AMStrategies(accessMethodTupleForm->amstrategies)); */ relation = (Relation)palloc(len); bzero((char *)relation, len); relation->rd_rel = relationTupleForm; relation->rd_am = accessMethodTupleForm; } DO_DB(elog(NOIND,"now at %d in %s", __LINE__, "relcache.c");) key.data[0].flags = 0; key.data[0].attributeNumber = AttributeRelationIdAttributeNumber; key.data[0].procedure = ObjectIdEqualRegProcedure; key.data[0].argument = ObjectIdGetDatum(relid); DO_DB(elog(NOIND,"now at %d in %s", __LINE__, "relcache.c");) attrioid = GetAttributeRelationIndexRelationId(); DO_DB(elog(NOIND,"now at %d in %s", __LINE__, "relcache.c");) if (ObjectIdIsValid(attrioid) && !avoidIndex) { /* * indexed scan of Attribute Relation */ IndexScanDesc scan; GeneralRetrieveIndexResult result; Relation attrd; Relation attrird; Buffer buffer; DO_DB(elog(NOIND,"Indexed build of %d", attrioid);) /* * avoidIndex prevents a recursive call to this code. I think * it would recurse indefinately. It is okay to have to * do this one scan the long way because the result will * be cached. */ attrd = RelationIdGetRelation(AttributeRelationId); avoidIndex = true; attrird = RelationIdGetRelation(attrioid); avoidIndex = false; scan = RelationGetIndexScan(attrird, 0, 1, &key); for(;;) { /* Get rid of loop? Just use first index? */ IndexTuple indexTuple; result = IndexScanGetGeneralRetrieveIndexResult(scan, 1); if (!GeneralRetrieveIndexResultIsValid(result)) break; /* * XXX * * the buffer should be freed.... * * however, the buffer won't be retured and thus * wont't be freed. (bug) */ tuple = GetHeapTuple(result, attrd, &buffer); if (!HeapTupleIsValid(tuple)) break; attp = (AttributeTupleForm)HeapTupleGetForm(tuple); BuildRelationAttributes(attp, relation, errorName); } IndexScanEnd(scan); RelationFree(attrd); RelationFree(attrird); DO_DB(elog(NOIND,"Done with Indexed build");) } else { /* * sequential scan of Attribute Relation */ DO_DB(elog(NOIND,"sequential build of %16s", errorName);) rd = amopenr(AttributeRelationName); sd = ambeginscan(rd, 0, NowTimeQual, 1, &key); while (HeapTupleIsValid( tuple = amgetnext(sd, 0, (Buffer *)NULL))) { attp = (AttributeTupleForm)HeapTupleGetForm(tuple); BuildRelationAttributes(attp, relation, errorName); } amendscan(sd); amclose(rd); DO_DB(elog(NOIND,"Done with sequential build %16s", errorName);) } DO_DB(elog(NOIND,"now at %d in %s", __LINE__, "relcache.c");) NO_DO_DB(puts("but now, I'm here again")); while ((int)--natts >= 0) { DO_DB(elog(NOIND,"now at %d in %s", __LINE__, "relcache.c");) if (!AttributeIsValid(relation->rd_att.data[natts])) { elog(NOTICE, "getreldesc: ATTRIBUTE relation corrupted %s", errorName); } } DO_DB(elog(NOIND,"now at %d in %s", __LINE__, "relcache.c");) relation->rd_fd = fd; relation->rd_nblocks = FileGetNumberOfBlocks(fd); DO_DB(elog(NOIND,"now at %d in %s", __LINE__, "relcache.c");) RelationSetReferenceCount(relation, 1); DO_DB(elog(NOIND,"now at %d in %s", __LINE__, "relcache.c");) if (ObjectIdIsValid(relation->rd_rel->relam)) { IndexStrategy strategy; int stratSize; DO_DB(elog(NOIND,"now at %d in %s", __LINE__, "relcache.c");) stratSize = AttributeNumberGetIndexStrategySize(numatts, relation->rd_am->amstrategies); DO_DB(elog(NOIND,"now at %d in %s", __LINE__, "relcache.c");) strategy = LintCast(IndexStrategy, palloc(stratSize)); DO_DB(elog(NOIND,"now at %d in %s", __LINE__, "relcache.c");) IndexStrategyInitialize(strategy, RelationGetTupleDescriptor(relation)->data[0]->attrelid, RelationGetRelationTupleForm(relation)->relam, AMStrategies(RelationGetAccessMethodTupleForm( relation)->amstrategies)); DO_DB(elog(NOIND,"now at %d in %s", __LINE__, "relcache.c");) RelationSetIndexStrategy(relation, strategy); } DO_DB(elog(NOIND,"now at %d in %s", __LINE__, "relcache.c");) relation->rd_id = relid; DO_DB(elog(NOIND,"now at %d in %s", __LINE__, "relcache.c");) RelationCacheHashByName = NameCacheSave; DO_DB(elog(NOIND,"now at %d in %s", __LINE__, "relcache.c");) RelationCacheHashById = IdCacheSave; DO_DB(elog(NOIND,"now at %d in %s", __LINE__, "relcache.c");) HashTableInsert(RelationCacheHashByName,relation); DO_DB(elog(NOIND,"now at %d in %s", __LINE__, "relcache.c");) HashTableInsert(RelationCacheHashById,relation); DO_DB(elog(NOIND,"now at %d in %s", __LINE__, "relcache.c");) RelationInitLockInfo(relation); DO_DB(elog(NOIND,"now at %d in %s", __LINE__, "relcache.c");) MemoryContextSwitchTo(oldcxt); DO_DB(elog(NOIND,"now at %d in %s", __LINE__, "relcache.c");) RelationInitLockInfo(relation); DO_DB(elog(NOIND,"now at %d in %s", __LINE__, "relcache.c");) return relation; d319 2 a320 3 /* d323 2 d327 1 a327 1 * d329 1 a329 1 d336 3 d342 172 a513 17 HeapTuple tuple; ObjectId objectId; static int state = UNTRIED; /* * XXX The next line is incorrect. It should be removed if the * performance penalty is not too great or if indexes are added * and dropped frequently. A more clever hack which will produce * correct behavior in a *single-user* situation is to keep a * global variable which is incremented each time DEFINE INDEX * is called. Then if the state is FAILED and a index has been * created since the last call to this function, then treat the * state as UNTRIED. But, this hack works incorrectly in a * multiuser environment. The correct thing to do is to have the * system cache keep information about failed search and to have * this information invalidated when a tuple is appended. -hirohama d515 21 a535 5 IN(); DO_DB(elog(NOIND,"GetAttrRelIndRelnId %d\n",state);) if (state == FAILED) { OUT(); return InvalidObjectId; d537 9 a545 1 d547 6 a552 3 * We don't want any infinately recusive calls to this * routine because SearchSysCacheTuple does some relation * descriptor lookups. d554 19 a572 2 state = FAILED; d574 1 a574 3 * The syscache must be searched again in the case of FOUND state * since the result may have been invalidated since the last call * to this function. d576 41 a616 9 DO_DB(elog(NOIND,"now at %d in %s", __LINE__, "relcache.c");) tuple = SearchSysCacheTuple(INDRELIDKEY, AttributeRelationId, AttributeRelationIdAttributeNumber); DO_DB(elog(NOIND,"now at %d in %s", __LINE__, "relcache.c");) if (!HeapTupleIsValid(tuple)) { OUT(); state = FAILED; return InvalidObjectId; d618 66 a683 7 objectId = LintCast(IndexTupleForm, HeapTupleGetForm(tuple)) -> indexrelid;; state = FOUND; OUT(); return objectId; d685 11 a695 7 private inline void BuildRelationAttributes(attp, relation, errorName) AttributeTupleForm attp; Relation relation; d697 27 a723 18 IN(); DO_DB(elog(NOIND,"BuildRelationAttr %x %x %s",attp, relation, errorName);) if (!AttributeNumberIsValid(attp->attnum)) elog(WARN, "getreldesc: found zero attnum %s", errorName); if (AttributeNumberIsForUserDefinedAttribute(attp->attnum)) { if (AttributeIsValid(relation->rd_att.data[ attp->attnum - 1])) { elog(WARN, "getreldesc: corrupted ATTRIBUTE %s" ,errorName); } relation->rd_att.data[attp->attnum - 1] = (Attribute)palloc(sizeof (RuleLock) + sizeof *relation->rd_att.data[0]); bcopy((char *)attp, (char *)relation->rd_att.data[ attp->attnum - 1], sizeof *relation->rd_att.data[0]); d725 81 d807 35 d843 14 a856 1 d859 2 a860 2 Relation relation; bool onlyFlushReferenceCountZero; d862 13 a874 3 int i; Attribute *p; MemoryContext oldcxt; d876 11 a886 11 IN(); DO_DB(elog(NOIND, "RelationFlush: %s[%d] called", RelationGetRelationName(relation), relation->rd_refcnt)); if (relation->rd_refcnt > 0x1000) { /* XXX */ /* this is a non-regeneratable special relation */ DO_DB(elog(NOTICE, "RelationFlush: cannot flush")); return; d888 8 a895 26 if (onlyFlushReferenceCountZero == false || RelationHasReferenceCountZero(relation)) { oldcxt = MemoryContextSwitchTo(CacheCxt); DO_DB(elog(NOIND,"RelationFlush: %s",&relation->rd_rel->relname)); HashTableDelete(RelationCacheHashByName,relation); HashTableDelete(RelationCacheHashById,relation); FileClose(RelationGetSystemPort(relation)); i = relation->rd_rel->relnatts - 1; p = &relation->rd_att.data[i]; while ((i -= 1) >= 0) { pfree((char *)*p--); } pfree((char *)RelationGetRelationTupleForm(relation)); pfree((char *)relation); MemoryContextSwitchTo(oldcxt); } OUT(); d897 8 a904 1 d907 1 a907 1 ObjectId relationId; d909 27 a935 13 Relation relation; relation = (Relation)KeyHashTableLookup(RelationCacheHashById, relationId); if (PointerIsValid(relation)) { /* Assert(RelationIsValid(relation)); */ DO_DB(elog(DEBUG, "RelationIdInvalidateRelationCacheByRelationId(%d)")); RelationFlushRelation(relation, false); d939 3 d944 1 a944 1 ObjectId accessMethodId; d946 4 a949 11 IN(); DO_DB(elog(NOIND, "RelationIdInvalidateRelationCacheByAccessMethodId (%d) BEGIN", accessMethodId)); HashTableWalk(RelationCacheHashByName, RelationFlushIndexes, accessMethodId); DO_DB(elog(NOIND, "RelationIdInvalidateRelationCacheByAccessMethodId END")); OUT(); d951 8 a958 1 d961 1 a961 1 bool onlyFlushReferenceCountZero; d963 4 a966 6 IN(); DO_DB(elog(NOIND,"RelationCacheInvalidate (%d) BEGIN",onlyFlushReferenceCountZero)); HashTableWalk(RelationCacheHashByName, RelationFlushRelation, onlyFlushReferenceCountZero); DO_DB(elog(NOIND,"RelationCacheInvalidate END")); OUT(); d968 8 a975 1 d978 1 a978 1 Relation relation; a979 1 DO_DB(elog(NOIND,"RelationFree: %s",&relation->rd_rel->relname)); d981 8 a988 1 d991 1 a991 1 Relation relation; d993 14 a1006 15 extern GlobalMemory CacheCxt; MemoryContext oldcxt; oldcxt = MemoryContextSwitchTo(CacheCxt); if (oldcxt != (MemoryContext)CacheCxt) elog(NOIND,"RelationRegisterRelation: WARNING: Context != CacheCxt"); HashTableInsert(RelationCacheHashByName,relation); HashTableInsert(RelationCacheHashById,relation); RelationInitLockInfo(relation); MemoryContextSwitchTo(oldcxt); d1008 1 a1008 1 d1011 1 d1016 3 d1021 1 a1021 1 Relation temprel; d1023 4 a1026 5 extern GlobalMemory CacheCxt; MemoryContext oldcxt; Relation rd; d1032 2 a1033 1 rd = (Relation)KeyHashTableLookup(RelationCacheHashById,temprel->rd_id); d1036 1 d1039 1 a1039 1 d1046 1 d1048 1 a1049 1 return; d1051 8 a1058 3 /* * relopen - physically open a relation d1060 3 a1062 5 * Note that this function should be replaced by a fd manager * which interacts with the reldesc manager. (Thus, this function * may be eventually have different functionality/have a different name. * * Perhaps relpath() code should be placed in-line here eventually. d1064 3 a1066 24 File relopen(relationName, flags, mode) char relationName[]; int flags; int mode; { File file; int oumask; int umask(); extern char *relpath(); IN(); DO_DB(elog(NOIND,"relopen: %s (%s)",relationName,relpath(relationName))); oumask = umask(0077); file = FileNameOpenFile(relpath(relationName), flags, mode); if (file == -1) elog(NOTICE, "Unable too open %s (%d)", relpath(relationName), errno); umask(oumask); OUT(); return (file); } d1069 5 a1073 5 char relationName[]; OID reloid; /* XXX unused */ u_int natts; AttributeTupleFormData att[]; int initialReferenceCount; d1075 31 a1105 4 Relation relation; int fd; int len; int i; d1107 13 a1119 1 /* struct attribute *attp; */ d1121 3 a1123 9 char *relpath(); File relopen(); Relation publicCopy; DO_DB(elog(NOIND,"formrdesc: %s",relationName)); len = sizeof *relation + ((int)natts - 1) * sizeof relation->rd_att; relation = (Relation)palloc(len); bzero((char *)relation, len); d1125 2 a1126 42 relation->rd_fd = -1; RelationSetReferenceCount(relation, 1); relation->rd_rel = (RelationTupleForm)palloc(sizeof (RuleLock) + sizeof *relation->rd_rel); /* rdesc->rd_am.xxx */ strncpy(&relation->rd_rel->relname, relationName, 16); relation->rd_rel->relowner = InvalidObjectId; /* XXX incorrect */ relation->rd_rel->relpages = 1; /* XXX */ relation->rd_rel->reltuples = 1; /* XXX */ relation->rd_rel->relhasindex = '\0'; relation->rd_rel->relkind = 'r'; relation->rd_rel->relarch = 'n'; relation->rd_rel->relnatts = (uint16)natts; for (i = 0; i < natts; i++) { relation->rd_att.data[i] = (Attribute) palloc(sizeof (RuleLock) + sizeof *relation->rd_att.data[0]); bzero((char *)relation->rd_att.data[i], sizeof (RuleLock) + sizeof *relation->rd_att.data[0]); bcopy((char *)&att[i], (char *)relation->rd_att.data[i], sizeof *relation->rd_att.data[0]); } relation->rd_id = relation->rd_att.data[0]->attrelid; HashTableInsert(PrivateRelationCacheHashByName, relation); HashTableInsert(PrivateRelationCacheHashById, relation); if (initialReferenceCount != 0) { publicCopy = (Relation)palloc(len); bcopy(relation, publicCopy, len); RelationSetReferenceCount(publicCopy, initialReferenceCount); HashTableInsert(RelationCacheHashByName, publicCopy); HashTableInsert(RelationCacheHashById, publicCopy); RelationInitLockInfo(relation); /* XXX unuseful here ??? */ } d1128 9 a1136 21 private Index HashByNameAsArgument(collisions,hashTableSize,relationName) uint16 collisions; Size hashTableSize; Name relationName; { return NameHashFunction(collisions,hashTableSize,relationName); } private Index HashByNameInRelation(collisions,hashTableSize,relation) uint16 collisions; Size hashTableSize; Relation relation; { NO_DO_DB(elog(NOIND,"HashByNameInRelation: %s",&relation->rd_rel->relname)); return NameHashFunction(collisions,hashTableSize, &relation->rd_rel->relname); } d1138 3 a1140 3 CompareNameInArgumentWithRelationNameInRelation(relation,relationName) Relation relation; String relationName; d1142 2 a1143 2 NO_DO_DB(elog(NOIND,"CompareNameInArg..: %s =%d= %s",relationName, strncmp(relationName, &relation->rd_rel->relname, 16), &relation->rd_rel->relname)); return strncmp(relationName, &relation->rd_rel->relname, 16); a1144 19 private Index HashByIdAsArgument(collisions,hashTableSize,relationId) uint16 collisions; Size hashTableSize; uint32 relationId; { return IntegerHashFunction(collisions,hashTableSize,relationId); } private Index HashByIdInRelation(collisions,hashTableSize,relation) uint16 collisions; Size hashTableSize; Relation relation; { return IntegerHashFunction(collisions,hashTableSize,relation->rd_id); } d1147 2 a1148 2 Relation relation; ObjectId relationId; d1150 2 a1151 1 return relation->rd_id - relationId; d1153 5 a1157 2 d1161 13 a1173 13 extern GlobalMemory CacheCxt; MemoryContext oldcxt; int initialReferences; IN(); DO_DB(elog(NOIND,"RelationInitialize")); if (!CacheCxt) CacheCxt = CreateGlobalMemory("Cache"); oldcxt = MemoryContextSwitchTo(CacheCxt); RelationCacheHashByName = CreateHashTable( HashByNameAsArgument, d1176 7 a1182 5 NULL, 300); GlobalNameCache = RelationCacheHashByName; RelationCacheHashById = CreateHashTable( HashByIdAsArgument, d1184 15 a1198 12 CompareIdInArgumentWithIdInRelation, NULL, 300); GlobalIdCache = RelationCacheHashById; /* * these should use a hash function that is perfect on them * and the hash table code should have a way of telling it not * to bother trying to resize 'cauase they all fit and there * arn't any collisions. Also, the hash table code could have * a HashTableDisableModification call. */ PrivateRelationCacheHashByName = CreateHashTable( HashByNameAsArgument, d1201 5 a1205 3 NULL, 30); PrivateRelationCacheHashById = CreateHashTable( HashByIdAsArgument, d1207 40 a1246 38 CompareIdInArgumentWithIdInRelation, NULL, 30); initialReferences = 0; if (AMI_OVERRIDE) { /* a hack to prevent generation of the special descriptors */ initialReferences = 0x2000; } formrdesc(RelationRelationName, relatt[0].attrelid, REL_NATTS, relatt, initialReferences); formrdesc(AttributeRelationName, attatt[0].attrelid, ATT_NATTS, attatt, initialReferences); formrdesc(ProcedureRelationName, proatt[0].attrelid, PRO_NATTS, proatt, initialReferences); formrdesc(TypeRelationName, typatt[0].attrelid, TYP_NATTS, typatt, initialReferences); /* ---------------- * the var, log, and time relations * are also cached... * ---------------- */ formrdesc(VariableRelationName, varatt[0].attrelid, VAR_NATTS, varatt, 0x1fff); formrdesc(LogRelationName, logatt[0].attrelid, LOG_NATTS, logatt, 0x1fff); formrdesc(TimeRelationName, timatt[0].attrelid, TIM_NATTS, timatt, 0x1fff); MemoryContextSwitchTo(oldcxt); OUT(); a1247 16 private void RelationFlushIndexes(relation, accessMethodId) Relation relation; ObjectId accessMethodId; { if (relation->rd_rel->relkind == 'i' && /* XXX style */ (!ObjectIdIsValid(accessMethodId) || relation->rd_rel->relam == accessMethodId)) { RelationFlushRelation(relation, false); } } @ 1.28 log @bugfix : elog(WARN ... ) used to leave routine in incorrect memory xact state @ text @d36 1 a36 1 RcsId("$Header: RCS/relcache.c,v 1.27 90/09/18 22:38:02 hong Exp Locker: goh $"); d894 37 @ 1.27 log @cleaned up striping code @ text @d36 1 a36 1 RcsId("$Header: RCS/relcache.c,v 1.26 90/08/22 15:18:18 choi Exp Locker: hong $"); d429 1 @ 1.26 log @lines added for Sprite OS port. @ text @d36 1 a36 1 RcsId("$Header: RCS/relcache.c,v 1.25 90/08/18 00:42:23 cimarron Exp Locker: choi $"); a273 3 #ifdef _xprs_ if (rd -> rd_fd.fd[0] == -1) { #else /* _xprs_ */ a274 1 #endif /* _xprs_ */ a276 3 #ifdef _xprs_ Assert (rd -> rd_fd.fd[0] != -1); #else /* _xprs_ */ a277 1 #endif /* _xprs_ */ a351 3 #ifdef _xprs_ if (rd -> rd_fd.fd[0] == -1) { #else /* _xprs_ */ a352 1 #endif /* _xprs_ */ a354 3 #ifdef _xprs_ Assert (rd -> rd_fd.fd[0] != -1); #else /* _xprs_ */ a355 1 #endif /* _xprs_ */ d363 1 a435 4 #ifdef _xprs_ Assert (fd.fd[0] >= -1); if (fd.fd[0] == -1) { #else /* _xprs_ */ a437 1 #endif /* _xprs_ */ d610 1 a799 10 #ifdef _xprs_ { File fd; fd = RelationGetSystemPort(relation); if (fd.is_sys) FileClose(fd.fd[0]); else for (i=0; ird_fd.fd[0] = -1; #else /* _xprs_ */ a953 1 #endif /* _xprs_ */ @ 1.25 log @eliminated less significant .h files @ text @d36 1 a36 1 RcsId("$Header: RCS/relcache.c,v 1.24 90/08/15 08:35:45 cimarron Exp Locker: cimarron $"); a50 1 #include "storage/fd.h" d70 6 @ 1.24 log @added pathnames to include statements @ text @d36 1 a36 1 RcsId("$Header: RCS/relcache.c,v 1.23 90/08/13 19:42:50 sp Exp Locker: cimarron $"); a37 3 #include "tmp/os.h" #include "tmp/clib.h" d52 1 d55 1 @ 1.23 log @'pg_relation.relstub' went to the great System Attribute Room in the sky. @ text @d34 1 a34 1 #include "postgres.h" d36 1 a36 1 RcsId("$Header: RCS/relcache.c,v 1.22 90/08/10 15:19:10 cimarron Exp $"); d38 2 a39 2 #include "os.h" #include "clib.h" d41 10 a50 21 #include "att.h" #include "attnum.h" #include "buf.h" #include "catname.h" #include "mcxt.h" #include "fd.h" #include "genam.h" #include "hashlib.h" #include "hasht.h" #include "heapam.h" #include "htup.h" #include "itup.h" #include "istrat.h" #include "lmgr.h" #include "log.h" #include "rel.h" #include "rlock.h" #include "skey.h" #include "syscache.h" #include "tqual.h" /* for NowTimeQual */ #include "tupdesc.h" d52 12 d71 1 a71 1 #include "relcache.h" @ 1.22 log @changed scan from (0) NoMovement to (1) Forward @ text @d36 1 a36 1 RcsId("$Header: RCS/relcache.c,v 1.21 90/08/08 08:36:51 cimarron Exp $"); d91 1 a91 1 #define REL_NATTS (15) d137 1 a137 2 { 83l, "relkeyop", 30, 83l, 0l, 0l, 32, 14, 0, '\0', '\001', 0l }, { 83l, "relstub", 33, 83l, 0l, 0l, -1, 15, 0, '\0', '\001', 0l } @ 1.21 log @reorganized some header files @ text @d36 1 a36 1 RcsId("$Header: RCS/relcache.c,v 1.20 90/08/01 14:56:24 sp Exp Locker: cimarron $"); d574 2 a575 1 result = IndexScanGetGeneralRetrieveIndexResult(scan,0); @ 1.20 log @Changed the private `relatt' table because pg_relation has now a new attribute `relstub' @ text @a28 4 #include "c.h" RcsId("$Header: RCS/relcache.c,v 1.19 90/07/19 15:30:34 mao Version_2 $"); d34 4 a40 1 #include "anum.h" a43 1 #include "cat.h" a55 1 #include "oid.h" a57 1 #include "rproc.h" d62 6 a67 1 /* #include "var-access.h" /* XXX for AMI_OVERRIDE */ d970 1 a970 1 formrdesc(relationName, oid, natts, att, initialReferenceCount) d972 1 a972 1 OID oid; d981 1 d983 1 d993 1 d999 1 d1001 1 d1004 1 d1006 1 d1009 2 a1010 2 relation->rd_rel->relpages = 1; /* XXX */ relation->rd_rel->reltuples = 1; /* XXX */ d1016 4 a1019 1 relation->rd_att.data[i] = (Attribute)palloc(sizeof (RuleLock) + d1021 1 a1021 1 bzero((char *)relation->rd_att.data[i], sizeof (RuleLock) + a1022 2 bcopy((char *)&att[i], (char *)relation->rd_att.data[i], sizeof *relation->rd_att.data[0]); d1024 1 d1026 2 a1027 2 HashTableInsert(PrivateRelationCacheHashByName,relation); HashTableInsert(PrivateRelationCacheHashById,relation); @ 1.19 log @fix for wei's bug #1 -- we sometimes looked in the wrong cache for a reldesc. @ text @d31 1 a31 1 RcsId("$Header: RCS/relcache.c,v 1.18 90/06/09 18:46:17 kemnitz Exp Locker: goh $"); d90 1 a90 2 /* #define REL_NATTS (15) */ #define REL_NATTS (14) d136 2 a137 1 { 83l, "relkeyop", 30, 83l, 0l, 0l, 32, 14, 0, '\0', '\001', 0l } @ 1.18 log @Got rid of datum indirection. @ text @d31 1 a31 1 RcsId("$Header: RCS/relcache.c,v 1.17 90/04/02 11:33:10 hong Exp Locker: hong $"); d107 1 d109 1 d264 1 d266 2 d346 1 d348 2 d1107 2 d1113 1 @ 1.17 log @changes for striping relations, but should not affect others at all @ text @d31 1 a31 1 RcsId("$Header: RCS/relcache.c,v 1.16 89/11/02 18:06:24 cimarron Exp Locker: hong $"); d296 1 a296 1 key.data[0].argument.objectId.value = relationId; d383 1 a383 1 key.data[0].argument.name.value = relationName; d487 1 a487 1 key.data[0].argument.objectId.value = relationTupleForm->relam; d534 1 a534 1 key.data[0].argument.objectId.value = relid; @ 1.16 log @added support for Merge Joins in the executor @ text @d31 1 a31 1 RcsId("$Header: RCS/relcache.c,v 1.15 89/09/28 17:50:39 hirohama Exp $"); d264 13 a276 5 if (rd->rd_fd == -1) { rd->rd_fd = relopen(&rd->rd_rel->relname, O_RDWR|O_CREAT, 0666); Assert(rd->rd_fd != -1); } d347 13 a359 5 if (rd->rd_fd == -1) { rd->rd_fd = relopen(&rd->rd_rel->relname, O_RDWR|O_CREAT, 0666); Assert(rd->rd_fd != -1); } d438 7 a444 2 Assert(fd >= -1); if (fd == -1) { d805 10 d816 1 d936 15 d952 3 a955 2 if (file == -1) elog(NOTICE, "Unable too open %s (%d)", relpath(relationName), errno); d974 1 a974 1 int relopen(); d982 3 d986 1 @ 1.15 log @TimeRange -> TimeQual @ text @d31 1 a31 1 RcsId("$Header: RCS/relcache.c,v 1.14 89/09/05 17:27:10 mao C_Demo_1 Locker: hirohama $"); d408 8 a415 7 elog(WARN, "getreldesc: %s relation nonexistent", errorName); NO_DO_DB(puts("I'm here...")); amendscan(sd); amclose(rd); RelationCacheHashByName = NameCacheSave; RelationCacheHashById = IdCacheSave; return (NULL); d421 2 a422 1 Assert(fd >= -1) d424 2 a425 2 elog(WARN, "getreldesc: relopen(%s): %m", &((RelationTupleForm)GETSTRUCT(tuple))->relname); d473 3 a475 2 elog(WARN, "getreldesc: %s: unknown AM %d", errorName, relationTupleForm->relam); d477 3 a479 3 amendscan(sd); amclose(rd); return (NULL); d481 2 a482 2 RelationCacheHashByName = NameCacheSave; RelationCacheHashById = IdCacheSave; d587 5 a591 5 DO_DB(elog(NOIND,"now at %d in %s", __LINE__, "relcache.c");) if (!AttributeIsValid(relation->rd_att.data[natts])) { elog(WARN, "getreldesc: ATTRIBUTE relation corrupted %s" ,errorName); } @ 1.14 log @Working version of C-only demo @ text @d31 1 a31 1 RcsId("$Header: /usr6/postgres/mao/postgres/src/utils/cache/RCS/relcache.c,v 1.13 89/08/09 18:11:10 cimarron Exp $"); d64 1 a64 1 #include "trange.h" d290 1 a290 1 sd = ambeginscan(rd, 0, DefaultTimeRange, 1, &key); d369 1 a369 1 sd = ambeginscan(rd, 0, DefaultTimeRange, 1, &key); d466 1 a466 1 sd = ambeginscan(rd, 0, DefaultTimeRange, 1, &key); d570 1 a570 1 sd = ambeginscan(rd, 0, DefaultTimeRange, 1, &key); @ 1.13 log @"retrieve(x=1)" @ text @d31 1 a31 1 RcsId("$Header: /usr6/postgres/cimarron/postgres3/src/utils/cache/RCS/relcache.c,v 1.12 89/06/17 01:53:05 hirohama Exp $"); @ 1.12 log @*** empty log message *** @ text @d31 1 a31 1 RcsId("$Header: /usr6/postgres/hirohama/postgres/src/utils/cache/RCS/relcache.c,v 1.11 89/06/13 17:48:02 dillon Exp $"); d210 1 a210 1 HeapScan sd, d249 1 a249 1 HeapScan sd; d320 1 a320 1 HeapScan sd; d382 1 a382 1 HeapScan sd; d519 1 a519 1 IndexScan scan; @ 1.11 log @*** empty log message *** @ text @d31 1 a31 1 RcsId("$Header: /usr6/postgres/dillon/tree/src/utils/cache/RCS/relcache.c,v 1.10 89/06/13 17:46:26 dillon Exp $"); a35 1 #include "context.h" a46 1 #include "context.h" @ 1.10 log @*** empty log message *** @ text @d31 1 a31 1 RcsId("$Header: /usr6/postgres/dillon/tree/src/utils/cache/RCS/relcache.c,v 1.9 89/06/13 17:41:34 dillon Exp $"); d866 1 a866 1 if (oldcxt != CacheCxt) @ 1.9 log @*** empty log message *** @ text @d31 1 a31 1 RcsId("$Header: /usr6/postgres/dillon/tree/src/utils/cache/RCS/relcache.c,v 1.8 89/06/13 17:10:54 cimarron Exp $"); d796 1 @ 1.8 log @made a few changes @ text @d31 1 a31 1 RcsId("$Header: /n/postgres/a/postgres/cimarron/postgres/src/utils/cache/RCS/relcache.c,v 1.5 89/05/07 16:23:13 hirohama Exp $"); d49 1 @ 1.7 log @*** empty log message *** @ text @d31 1 a31 1 RcsId("$Header: relcache.c,v 1.6 89/06/13 16:41:35 cimarron Exp $"); d253 4 a256 2 extern struct context *CacheCxt; struct context *oldcxt; d282 1 a282 1 oldcxt = switchcontext(CacheCxt); d302 1 a302 1 rd = BuildRelation(rd, sd, errorName,oldcxt, tuple, d323 4 a326 2 extern struct context *CacheCxt; struct context *oldcxt; d361 1 a361 1 oldcxt = switchcontext(CacheCxt); d381 1 a381 1 BuildRelation(rd, sd, errorName,oldcxt, tuple, NameCacheSave, IdCacheSave) d385 4 a388 2 struct context *oldcxt; HeapTuple tuple; a637 1 (void)switchcontext(oldcxt); d639 2 d859 4 a862 1 struct context *oldcxt; a863 2 oldcxt = switchcontext(CacheCxt); d872 2 a873 1 (void)switchcontext(oldcxt); @ 1.6 log @changed to new memory manager interface -cim @ text @d31 1 a31 1 RcsId("$Header: /n/postgres/a/postgres/cimarron/postgres/src/utils/cache/RCS/relcache.c,v 1.5 89/05/07 16:23:13 hirohama Exp $"); @ 1.5 log @hash.h -> hasht.h @ text @d31 1 a31 1 RcsId("$Header: relcache.c,v 1.4 89/03/08 15:29:10 hirohama Locked $"); d751 2 a752 2 struct context *oldcxt; d769 1 a769 1 oldcxt = switchcontext(CacheCxt); d786 2 a788 2 (void)switchcontext(oldcxt); } d1019 2 a1020 2 extern struct context *CacheCxt; struct context *oldcxt; d1025 5 a1029 8 if (!CacheCxt) { /* init the cache system */ oldcxt = newcontext(); CacheCxt = Curcxt; CacheCxt->ct_status |= CT_PRESERVE; } else { oldcxt = switchcontext(CacheCxt); } d1090 2 a1091 1 switchcontext(oldcxt); @ 1.4 log @minor fix, sequent port @ text @d29 4 d37 1 a38 1 #include "c.h" a50 1 #include "hash.h" d52 1 a70 2 RcsId("$Header: relcache.c,v 1.3 89/03/06 16:29:40 hirohama Exp $"); @ 1.3 log @now compiles quietly @ text @d29 1 d68 1 a68 1 RcsId("$Header: relcache.c,v 1.2 89/03/02 17:27:22 hirohama Locked $"); @ 1.2 log @ Mostly added relcache speedup: use an index on pg_attribute @ text @d67 3 a69 1 RcsId("$Header: /usr6/postgres/muir/postgres/src/utils/cache/RCS/relcache.c,v 1.1 89/01/17 05:58:49 cimarron Exp $"); @ 1.1 log @Initial revision @ text @a0 1 a1 26 * * POSTGRES Data Base Management System * * Copyright (c) 1988 Regents of the University of California * * Permission to use, copy, modify, and distribute this software and its * documentation for educational, research, and non-profit purposes and * without fee is hereby granted, provided that the above copyright * notice appear in all copies and that both that copyright notice and * this permission notice appear in supporting documentation, and that * the name of the University of California not be used in advertising * or publicity pertaining to distribution of the software without * specific, written prior permission. Permission to incorporate this * software into commercial products can be obtained from the Campus * Software Office, 295 Evans Hall, University of California, Berkeley, * Ca., 94720 provided only that the the requestor give the University * of California a free licence to any derived software for educational * and research purposes. The University of California makes no * representations about the suitability of this software for any * purpose. It is provided "as is" without express or implied warranty. * */ /* d45 1 d50 1 d59 1 d67 1 a67 1 RcsId("$Header: relcache.c,v 1.1 88/11/11 16:42:22 postgres Exp $"); d74 1 a74 1 # define static /* static */ /* WARNING WARNING WARNING */ d78 1 d113 1 a113 1 static AttributeTupleFormData relatt[REL_NATTS] = { d133 1 a133 1 static AttributeTupleFormData attatt[ATT_NATTS] = { d147 1 a147 1 static AttributeTupleFormData proatt[PRO_NATTS] = { d159 1 a159 1 static AttributeTupleFormData typatt[TYP_NATTS] = { d183 1 a183 1 static AttributeTupleFormData varatt[VAR_NATTS] = { d188 1 a188 1 static AttributeTupleFormData logatt[LOG_NATTS] = { d193 1 a193 1 static AttributeTupleFormData timatt[VAR_NATTS] = { d202 2 a203 1 static Relation d216 1 a216 1 static d222 18 d371 1 a371 1 static Relation d381 1 d390 1 d396 1 d407 1 d426 1 d441 1 d458 1 d479 1 d496 1 a496 2 rd = amopenr(AttributeRelationName); d502 12 a513 1 sd = ambeginscan(rd, 0, DefaultTimeRange, 1, &key); d515 12 a526 1 while (HeapTupleIsValid(tuple = amgetnext(sd, 0, (Buffer *)NULL))) { d528 21 a548 16 attp = (AttributeTupleForm)HeapTupleGetForm(tuple); if (!AttributeNumberIsValid(attp->attnum)) elog(WARN, "getreldesc: found zero attnum %s", errorName); if (AttributeNumberIsForUserDefinedAttribute(attp->attnum)) { if (AttributeIsValid(relation->rd_att.data[ attp->attnum - 1])) { elog(WARN, "getreldesc: corrupted ATTRIBUTE %s" ,errorName); } relation->rd_att.data[attp->attnum - 1] = (Attribute)palloc(sizeof (RuleLock) + sizeof *relation->rd_att.data[0]); bcopy((char *)attp, (char *)relation->rd_att.data[ attp->attnum - 1], sizeof *relation->rd_att.data[0]); d550 20 d571 1 a572 2 amendscan(sd); amclose(rd); d574 1 d580 1 d583 1 d586 1 d591 1 d595 1 d598 1 d605 1 d610 1 d613 1 d615 1 d618 1 d620 1 d623 1 d626 1 d629 1 d632 1 d636 76 d713 27 d889 2 d895 1 a895 1 static void d955 1 a955 1 static Index d964 1 a964 1 static Index d975 1 a975 1 static int d984 1 a984 1 static Index d993 1 a993 1 static Index d1002 1 a1002 1 static int d1092 1 a1092 1 static d1105 2 @