diff options
author | Tom Lane <tgl@sss.pgh.pa.us> | 2005-04-14 20:03:27 +0000 |
---|---|---|
committer | Tom Lane <tgl@sss.pgh.pa.us> | 2005-04-14 20:03:27 +0000 |
commit | 162bd08b3f2e6783d1d75ae79f86fc444d34a28d (patch) | |
tree | 0220cd8a906557db64763a1a57dd339de313d221 /src/backend/utils/cache | |
parent | 9dc2e6deaf66f97ff9157478a517d0f48a1e5060 (diff) | |
download | postgresql-162bd08b3f2e6783d1d75ae79f86fc444d34a28d.tar.gz postgresql-162bd08b3f2e6783d1d75ae79f86fc444d34a28d.zip |
Completion of project to use fixed OIDs for all system catalogs and
indexes. Replace all heap_openr and index_openr calls by heap_open
and index_open. Remove runtime lookups of catalog OID numbers in
various places. Remove relcache's support for looking up system
catalogs by name. Bulky but mostly very boring patch ...
Diffstat (limited to 'src/backend/utils/cache')
-rw-r--r-- | src/backend/utils/cache/catcache.c | 55 | ||||
-rw-r--r-- | src/backend/utils/cache/lsyscache.c | 21 | ||||
-rw-r--r-- | src/backend/utils/cache/relcache.c | 315 | ||||
-rw-r--r-- | src/backend/utils/cache/syscache.c | 168 | ||||
-rw-r--r-- | src/backend/utils/cache/typcache.c | 7 |
5 files changed, 187 insertions, 379 deletions
diff --git a/src/backend/utils/cache/catcache.c b/src/backend/utils/cache/catcache.c index 44ef1de6eee..13711b22416 100644 --- a/src/backend/utils/cache/catcache.c +++ b/src/backend/utils/cache/catcache.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/cache/catcache.c,v 1.119 2005/03/25 18:30:27 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/cache/catcache.c,v 1.120 2005/04/14 20:03:26 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -21,7 +21,6 @@ #include "catalog/pg_opclass.h" #include "catalog/pg_operator.h" #include "catalog/pg_type.h" -#include "catalog/catname.h" #include "catalog/indexing.h" #include "miscadmin.h" #ifdef CATCACHE_STATS @@ -35,7 +34,7 @@ #include "utils/syscache.h" - /* #define CACHEDEBUG */ /* turns DEBUG elogs on */ +/* #define CACHEDEBUG */ /* turns DEBUG elogs on */ /* * Constants related to size of the catcache. @@ -297,9 +296,9 @@ CatCachePrintStats(void) { if (cache->cc_ntup == 0 && cache->cc_searches == 0) continue; /* don't print unused caches */ - elog(DEBUG2, "catcache %s/%s: %d tup, %ld srch, %ld+%ld=%ld hits, %ld+%ld=%ld loads, %ld invals, %ld discards, %ld lsrch, %ld lhits", + elog(DEBUG2, "catcache %s/%u: %d tup, %ld srch, %ld+%ld=%ld hits, %ld+%ld=%ld loads, %ld invals, %ld discards, %ld lsrch, %ld lhits", cache->cc_relname, - cache->cc_indname, + cache->cc_indexoid, cache->cc_ntup, cache->cc_searches, cache->cc_hits, @@ -763,8 +762,9 @@ CatalogCacheFlushRelation(Oid relId) #ifdef CACHEDEBUG #define InitCatCache_DEBUG2 \ do { \ - elog(DEBUG2, "InitCatCache: rel=%s id=%d nkeys=%d size=%d", \ - cp->cc_relname, cp->id, cp->cc_nkeys, cp->cc_nbuckets); \ + elog(DEBUG2, "InitCatCache: rel=%u ind=%u id=%d nkeys=%d size=%d", \ + cp->cc_reloid, cp->cc_indexoid, cp->id, \ + cp->cc_nkeys, cp->cc_nbuckets); \ } while(0) #else @@ -773,8 +773,8 @@ do { \ CatCache * InitCatCache(int id, - const char *relname, - const char *indname, + Oid reloid, + Oid indexoid, int reloidattr, int nkeys, const int *key) @@ -821,9 +821,9 @@ InitCatCache(int id, * other internal fields. But don't open the relation yet. */ cp->id = id; - cp->cc_relname = relname; - cp->cc_indname = indname; - cp->cc_reloid = InvalidOid; /* temporary */ + cp->cc_relname = "(not known yet)"; + cp->cc_reloid = reloid; + cp->cc_indexoid = indexoid; cp->cc_relisshared = false; /* temporary */ cp->cc_tupdesc = (TupleDesc) NULL; cp->cc_reloidattr = reloidattr; @@ -861,9 +861,9 @@ InitCatCache(int id, * that the relcache entry can be opened at this point! */ #ifdef CACHEDEBUG -#define CatalogCacheInitializeCache_DEBUG2 \ - elog(DEBUG2, "CatalogCacheInitializeCache: cache @%p %s", cache, \ - cache->cc_relname) +#define CatalogCacheInitializeCache_DEBUG1 \ + elog(DEBUG2, "CatalogCacheInitializeCache: cache @%p rel=%u", cache, \ + cache->cc_reloid) #define CatalogCacheInitializeCache_DEBUG2 \ do { \ @@ -878,7 +878,7 @@ do { \ } while(0) #else -#define CatalogCacheInitializeCache_DEBUG2 +#define CatalogCacheInitializeCache_DEBUG1 #define CatalogCacheInitializeCache_DEBUG2 #endif @@ -890,13 +890,13 @@ CatalogCacheInitializeCache(CatCache *cache) TupleDesc tupdesc; int i; - CatalogCacheInitializeCache_DEBUG2; + CatalogCacheInitializeCache_DEBUG1; /* * Open the relation without locking --- we only need the tupdesc, * which we assume will never change ... */ - relation = heap_openr(cache->cc_relname, NoLock); + relation = heap_open(cache->cc_reloid, NoLock); Assert(RelationIsValid(relation)); /* @@ -913,9 +913,10 @@ CatalogCacheInitializeCache(CatCache *cache) tupdesc = CreateTupleDescCopyConstr(RelationGetDescr(relation)); /* - * get the relation's OID and relisshared flag, too + * save the relation's name and relisshared flag, too (cc_relname + * is used only for debugging purposes) */ - cache->cc_reloid = RelationGetRelid(relation); + cache->cc_relname = pstrdup(RelationGetRelationName(relation)); cache->cc_relisshared = RelationGetForm(relation)->relisshared; /* @@ -999,7 +1000,7 @@ InitCatCachePhase2(CatCache *cache) { Relation idesc; - idesc = index_openr(cache->cc_indname); + idesc = index_open(cache->cc_indexoid); index_close(idesc); } } @@ -1202,7 +1203,7 @@ SearchCatCache(CatCache *cache, relation = heap_open(cache->cc_reloid, AccessShareLock); scandesc = systable_beginscan(relation, - cache->cc_indname, + cache->cc_indexoid, IndexScanOK(cache, cur_skey), SnapshotNow, cache->cc_nkeys, @@ -1230,9 +1231,17 @@ SearchCatCache(CatCache *cache, * If tuple was not found, we need to build a negative cache entry * containing a fake tuple. The fake tuple has the correct key * columns, but nulls everywhere else. + * + * In bootstrap mode, we don't build negative entries, because the + * cache invalidation mechanism isn't alive and can't clear them + * if the tuple gets created later. (Bootstrap doesn't do UPDATEs, + * so it doesn't need cache inval for that.) */ if (ct == NULL) { + if (IsBootstrapProcessingMode()) + return NULL; + ntp = build_dummy_tuple(cache, cache->cc_nkeys, cur_skey); ct = CatalogCacheCreateEntry(cache, ntp, hashValue, hashIndex, @@ -1427,7 +1436,7 @@ SearchCatCacheList(CatCache *cache, relation = heap_open(cache->cc_reloid, AccessShareLock); scandesc = systable_beginscan(relation, - cache->cc_indname, + cache->cc_indexoid, true, SnapshotNow, nkeys, diff --git a/src/backend/utils/cache/lsyscache.c b/src/backend/utils/cache/lsyscache.c index 2c4d20576a5..e46825212e1 100644 --- a/src/backend/utils/cache/lsyscache.c +++ b/src/backend/utils/cache/lsyscache.c @@ -7,7 +7,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.123 2005/04/11 23:06:56 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/cache/lsyscache.c,v 1.124 2005/04/14 20:03:26 tgl Exp $ * * NOTES * Eventually, the index information should go through here, too. @@ -931,25 +931,6 @@ get_relname_relid(const char *relname, Oid relnamespace) 0, 0); } -/* - * get_system_catalog_relid - * Get the OID of a system catalog identified by name. - */ -Oid -get_system_catalog_relid(const char *catname) -{ - Oid relid; - - relid = GetSysCacheOid(RELNAMENSP, - PointerGetDatum(catname), - ObjectIdGetDatum(PG_CATALOG_NAMESPACE), - 0, 0); - if (!OidIsValid(relid)) - elog(ERROR, "cache lookup failed for system relation %s", catname); - - return relid; -} - #ifdef NOT_USED /* * get_relnatts diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index e6c59b1815b..ab773de9c80 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.219 2005/04/14 01:38:19 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/cache/relcache.c,v 1.220 2005/04/14 20:03:26 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -17,7 +17,6 @@ * RelationCacheInitialize - initialize relcache * RelationCacheInitializePhase2 - finish initializing relcache * RelationIdGetRelation - get a reldesc by relation id - * RelationSysNameGetRelation - get a reldesc by system rel name * RelationIdCacheGetRelation - get a cached reldesc by relid * RelationClose - close an open relation * @@ -34,7 +33,6 @@ #include "access/genam.h" #include "access/heapam.h" #include "catalog/catalog.h" -#include "catalog/catname.h" #include "catalog/indexing.h" #include "catalog/namespace.h" #include "catalog/pg_amop.h" @@ -85,14 +83,16 @@ static FormData_pg_attribute Desc_pg_index[Natts_pg_index] = {Schema_pg_index}; /* * Hash tables that index the relation cache * - * Relations are looked up two ways, by OID and by name, - * thus there are two hash tables for referencing them. - * - * The OID index covers all relcache entries. The name index - * covers *only* system relations (only those in PG_CATALOG_NAMESPACE). + * We used to index the cache by both name and OID, but now there + * is only an index by OID. */ +typedef struct relidcacheent +{ + Oid reloid; + Relation reldesc; +} RelIdCacheEnt; + static HTAB *RelationIdCache; -static HTAB *RelationSysNameCache; /* * This flag is false until we have prepared the critical relcache entries @@ -125,33 +125,6 @@ static List *initFileRelationIds = NIL; */ static bool need_eosubxact_work = false; -/* - * RelationBuildDescInfo exists so code can be shared - * between RelationIdGetRelation() and RelationSysNameGetRelation() - */ -typedef struct RelationBuildDescInfo -{ - int infotype; /* lookup by id or by name */ -#define INFO_RELID 1 -#define INFO_RELNAME 2 - union - { - Oid info_id; /* relation object id */ - char *info_name; /* system relation name */ - } i; -} RelationBuildDescInfo; - -typedef struct relidcacheent -{ - Oid reloid; - Relation reldesc; -} RelIdCacheEnt; - -typedef struct relnamecacheent -{ - NameData relname; - Relation reldesc; -} RelNameCacheEnt; /* * macros to manipulate the lookup hashtables @@ -169,39 +142,13 @@ do { \ errmsg("out of memory"))); \ /* used to give notice if found -- now just keep quiet */ \ idhentry->reldesc = RELATION; \ - if (IsSystemNamespace(RelationGetNamespace(RELATION))) \ - { \ - char *relname = RelationGetRelationName(RELATION); \ - RelNameCacheEnt *namehentry; \ - namehentry = (RelNameCacheEnt*)hash_search(RelationSysNameCache, \ - relname, \ - HASH_ENTER, \ - &found); \ - if (namehentry == NULL) \ - ereport(ERROR, \ - (errcode(ERRCODE_OUT_OF_MEMORY), \ - errmsg("out of memory"))); \ - /* used to give notice if found -- now just keep quiet */ \ - namehentry->reldesc = RELATION; \ - } \ } while(0) #define RelationIdCacheLookup(ID, RELATION) \ do { \ RelIdCacheEnt *hentry; \ hentry = (RelIdCacheEnt*)hash_search(RelationIdCache, \ - (void *)&(ID), HASH_FIND,NULL); \ - if (hentry) \ - RELATION = hentry->reldesc; \ - else \ - RELATION = NULL; \ -} while(0) - -#define RelationSysNameCacheLookup(NAME, RELATION) \ -do { \ - RelNameCacheEnt *hentry; \ - hentry = (RelNameCacheEnt*)hash_search(RelationSysNameCache, \ - (void *) (NAME), HASH_FIND,NULL); \ + (void *) &(ID), HASH_FIND,NULL); \ if (hentry) \ RELATION = hentry->reldesc; \ else \ @@ -212,20 +159,10 @@ do { \ do { \ RelIdCacheEnt *idhentry; \ idhentry = (RelIdCacheEnt*)hash_search(RelationIdCache, \ - (void *)&(RELATION->rd_id), \ + (void *) &(RELATION->rd_id), \ HASH_REMOVE, NULL); \ if (idhentry == NULL) \ elog(WARNING, "trying to delete a rd_id reldesc that does not exist"); \ - if (IsSystemNamespace(RelationGetNamespace(RELATION))) \ - { \ - char *relname = RelationGetRelationName(RELATION); \ - RelNameCacheEnt *namehentry; \ - namehentry = (RelNameCacheEnt*)hash_search(RelationSysNameCache, \ - relname, \ - HASH_REMOVE, NULL); \ - if (namehentry == NULL) \ - elog(WARNING, "trying to delete a relname reldesc that does not exist"); \ - } \ } while(0) @@ -253,19 +190,16 @@ static void RelationClearRelation(Relation relation, bool rebuild); static void RelationReloadClassinfo(Relation relation); static void RelationFlushRelation(Relation relation); -static Relation RelationSysNameCacheGetRelation(const char *relationName); static bool load_relcache_init_file(void); static void write_relcache_init_file(void); static void formrdesc(const char *relationName, Oid relationReltype, bool hasoids, int natts, FormData_pg_attribute *att); -static HeapTuple ScanPgRelation(RelationBuildDescInfo buildinfo, bool indexOK); +static HeapTuple ScanPgRelation(Oid targetRelId, bool indexOK); static Relation AllocateRelationDesc(Relation relation, Form_pg_class relp); -static void RelationBuildTupleDesc(RelationBuildDescInfo buildinfo, - Relation relation); -static Relation RelationBuildDesc(RelationBuildDescInfo buildinfo, - Relation oldrelation); +static void RelationBuildTupleDesc(Relation relation); +static Relation RelationBuildDesc(Oid targetRelId, Relation oldrelation); static void RelationInitPhysicalAddr(Relation relation); static TupleDesc GetPgIndexDescriptor(void); static void AttrDefaultFetch(Relation relation); @@ -286,54 +220,26 @@ static OpClassCacheEnt *LookupOpclassInfo(Oid operatorClassOid, * ScanPgRelation * * this is used by RelationBuildDesc to find a pg_class - * tuple matching either a relation name or a relation id - * as specified in buildinfo. + * tuple matching targetRelId. * * NB: the returned tuple has been copied into palloc'd storage * and must eventually be freed with heap_freetuple. */ static HeapTuple -ScanPgRelation(RelationBuildDescInfo buildinfo, bool indexOK) +ScanPgRelation(Oid targetRelId, bool indexOK) { HeapTuple pg_class_tuple; Relation pg_class_desc; - const char *indexRelname; SysScanDesc pg_class_scan; - ScanKeyData key[2]; - int nkeys; + ScanKeyData key[1]; /* * form a scan key */ - switch (buildinfo.infotype) - { - case INFO_RELID: - ScanKeyInit(&key[0], - ObjectIdAttributeNumber, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(buildinfo.i.info_id)); - nkeys = 1; - indexRelname = ClassOidIndex; - break; - - case INFO_RELNAME: - ScanKeyInit(&key[0], - Anum_pg_class_relname, - BTEqualStrategyNumber, F_NAMEEQ, - NameGetDatum(buildinfo.i.info_name)); - ScanKeyInit(&key[1], - Anum_pg_class_relnamespace, - BTEqualStrategyNumber, F_OIDEQ, - ObjectIdGetDatum(PG_CATALOG_NAMESPACE)); - nkeys = 2; - indexRelname = ClassNameNspIndex; - break; - - default: - elog(ERROR, "unrecognized buildinfo type: %d", - buildinfo.infotype); - return NULL; /* keep compiler quiet */ - } + ScanKeyInit(&key[0], + ObjectIdAttributeNumber, + BTEqualStrategyNumber, F_OIDEQ, + ObjectIdGetDatum(targetRelId)); /* * Open pg_class and fetch a tuple. Force heap scan if we haven't yet @@ -341,11 +247,11 @@ ScanPgRelation(RelationBuildDescInfo buildinfo, bool indexOK) * startup without a pg_internal.init file). The caller can also * force a heap scan by setting indexOK == false. */ - pg_class_desc = heap_openr(RelationRelationName, AccessShareLock); - pg_class_scan = systable_beginscan(pg_class_desc, indexRelname, + pg_class_desc = heap_open(RelationRelationId, AccessShareLock); + pg_class_scan = systable_beginscan(pg_class_desc, ClassOidIndexId, indexOK && criticalRelcachesBuilt, SnapshotNow, - nkeys, key); + 1, key); pg_class_tuple = systable_getnext(pg_class_scan); @@ -429,8 +335,7 @@ AllocateRelationDesc(Relation relation, Form_pg_class relp) * the pg_attribute, pg_attrdef & pg_constraint system catalogs. */ static void -RelationBuildTupleDesc(RelationBuildDescInfo buildinfo, - Relation relation) +RelationBuildTupleDesc(Relation relation) { HeapTuple pg_attribute_tuple; Relation pg_attribute_desc; @@ -469,9 +374,9 @@ RelationBuildTupleDesc(RelationBuildDescInfo buildinfo, * yet built the critical relcache entries (this includes initdb and * startup without a pg_internal.init file). */ - pg_attribute_desc = heap_openr(AttributeRelationName, AccessShareLock); + pg_attribute_desc = heap_open(AttributeRelationId, AccessShareLock); pg_attribute_scan = systable_beginscan(pg_attribute_desc, - AttributeRelidNumIndex, + AttributeRelidNumIndexId, criticalRelcachesBuilt, SnapshotNow, 2, skey); @@ -648,15 +553,15 @@ RelationBuildRuleLock(Relation relation) /* * open pg_rewrite and begin a scan * - * Note: since we scan the rules using RewriteRelRulenameIndex, we will - * be reading the rules in name order, except possibly during + * Note: since we scan the rules using RewriteRelRulenameIndexId, + * we will be reading the rules in name order, except possibly during * emergency-recovery operations (ie, IsIgnoringSystemIndexes). This * in turn ensures that rules will be fired in name order. */ - rewrite_desc = heap_openr(RewriteRelationName, AccessShareLock); + rewrite_desc = heap_open(RewriteRelationId, AccessShareLock); rewrite_tupdesc = RelationGetDescr(rewrite_desc); rewrite_scan = systable_beginscan(rewrite_desc, - RewriteRelRulenameIndex, + RewriteRelRulenameIndexId, true, SnapshotNow, 1, &key); @@ -788,8 +693,7 @@ equalRuleLocks(RuleLock *rlock1, RuleLock *rlock2) * -------------------------------- */ static Relation -RelationBuildDesc(RelationBuildDescInfo buildinfo, - Relation oldrelation) +RelationBuildDesc(Oid targetRelId, Relation oldrelation) { Relation relation; Oid relid; @@ -800,7 +704,7 @@ RelationBuildDesc(RelationBuildDescInfo buildinfo, /* * find the tuple in pg_class corresponding to the given relation id */ - pg_class_tuple = ScanPgRelation(buildinfo, true); + pg_class_tuple = ScanPgRelation(targetRelId, true); /* * if no such tuple exists, return NULL @@ -844,7 +748,7 @@ RelationBuildDesc(RelationBuildDescInfo buildinfo, /* * initialize the tuple descriptor (relation->rd_att). */ - RelationBuildTupleDesc(buildinfo, relation); + RelationBuildTupleDesc(relation); /* * Fetch rules and triggers that affect this relation @@ -1191,9 +1095,8 @@ LookupOpclassInfo(Oid operatorClassOid, Anum_pg_amop_amopsubtype, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(InvalidOid)); - rel = heap_openr(AccessMethodOperatorRelationName, - AccessShareLock); - scan = systable_beginscan(rel, AccessMethodStrategyIndex, indexOK, + rel = heap_open(AccessMethodOperatorRelationId, AccessShareLock); + scan = systable_beginscan(rel, AccessMethodStrategyIndexId, indexOK, SnapshotNow, 2, skey); while (HeapTupleIsValid(htup = systable_getnext(scan))) @@ -1226,9 +1129,8 @@ LookupOpclassInfo(Oid operatorClassOid, Anum_pg_amproc_amprocsubtype, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(InvalidOid)); - rel = heap_openr(AccessMethodProcedureRelationName, - AccessShareLock); - scan = systable_beginscan(rel, AccessMethodProcedureIndex, indexOK, + rel = heap_open(AccessMethodProcedureRelationId, AccessShareLock); + scan = systable_beginscan(rel, AccessMethodProcedureIndexId, indexOK, SnapshotNow, 2, skey); while (HeapTupleIsValid(htup = systable_getnext(scan))) @@ -1441,35 +1343,6 @@ RelationIdCacheGetRelation(Oid relationId) } /* - * RelationSysNameCacheGetRelation - * - * As above, but lookup by name; only works for system catalogs. - */ -static Relation -RelationSysNameCacheGetRelation(const char *relationName) -{ - Relation rd; - NameData name; - - /* - * make sure that the name key used for hash lookup is properly - * null-padded - */ - namestrcpy(&name, relationName); - RelationSysNameCacheLookup(NameStr(name), rd); - - if (RelationIsValid(rd)) - { - RelationIncrementReferenceCount(rd); - /* revalidate nailed index if necessary */ - if (!rd->rd_isvalid) - RelationReloadClassinfo(rd); - } - - return rd; -} - -/* * RelationIdGetRelation * * Lookup a reldesc by OID; make one if not already in cache. @@ -1482,7 +1355,6 @@ Relation RelationIdGetRelation(Oid relationId) { Relation rd; - RelationBuildDescInfo buildinfo; /* * first try and get a reldesc from the cache @@ -1495,41 +1367,7 @@ RelationIdGetRelation(Oid relationId) * 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, NULL); - if (RelationIsValid(rd)) - RelationIncrementReferenceCount(rd); - return rd; -} - -/* - * RelationSysNameGetRelation - * - * As above, but lookup by name; only works for system catalogs. - */ -Relation -RelationSysNameGetRelation(const char *relationName) -{ - Relation rd; - RelationBuildDescInfo buildinfo; - - /* - * first try and get a reldesc from the cache - */ - rd = RelationSysNameCacheGetRelation(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 = (char *) relationName; - - rd = RelationBuildDesc(buildinfo, NULL); + rd = RelationBuildDesc(relationId, NULL); if (RelationIsValid(rd)) RelationIncrementReferenceCount(rd); return rd; @@ -1612,7 +1450,6 @@ RelationClose(Relation relation) static void RelationReloadClassinfo(Relation relation) { - RelationBuildDescInfo buildinfo; bool indexOK; HeapTuple pg_class_tuple; Form_pg_class relp; @@ -1620,19 +1457,17 @@ RelationReloadClassinfo(Relation relation) /* Should be called only for invalidated nailed indexes */ Assert(relation->rd_isnailed && !relation->rd_isvalid && relation->rd_rel->relkind == RELKIND_INDEX); - /* Read the pg_class row */ - buildinfo.infotype = INFO_RELID; - buildinfo.i.info_id = relation->rd_id; - /* + * Read the pg_class row + * * Don't try to use an indexscan of pg_class_oid_index to reload the * info for pg_class_oid_index ... */ - indexOK = strcmp(RelationGetRelationName(relation), ClassOidIndex) != 0; - pg_class_tuple = ScanPgRelation(buildinfo, indexOK); + indexOK = (RelationGetRelid(relation) != ClassOidIndexId); + pg_class_tuple = ScanPgRelation(RelationGetRelid(relation), indexOK); if (!HeapTupleIsValid(pg_class_tuple)) elog(ERROR, "could not find tuple for system relation %u", - relation->rd_id); + RelationGetRelid(relation)); relp = (Form_pg_class) GETSTRUCT(pg_class_tuple); memcpy((char *) relation->rd_rel, (char *) relp, CLASS_TUPLE_SIZE); /* Now we can recalculate physical address */ @@ -1750,17 +1585,14 @@ RelationClearRelation(Relation relation, bool rebuild) * is good because whatever ref counts the entry may have do not * necessarily belong to that resource owner. */ + Oid save_relid = RelationGetRelid(relation); int old_refcnt = relation->rd_refcnt; SubTransactionId old_createSubid = relation->rd_createSubid; TupleDesc old_att = relation->rd_att; RuleLock *old_rules = relation->rd_rules; MemoryContext old_rulescxt = relation->rd_rulescxt; - RelationBuildDescInfo buildinfo; - buildinfo.infotype = INFO_RELID; - buildinfo.i.info_id = RelationGetRelid(relation); - - if (RelationBuildDesc(buildinfo, relation) != relation) + if (RelationBuildDesc(save_relid, relation) != relation) { /* Should only get here if relation was deleted */ flush_rowtype_cache(old_reltype); @@ -1768,8 +1600,7 @@ RelationClearRelation(Relation relation, bool rebuild) if (old_rulescxt) MemoryContextDelete(old_rulescxt); pfree(relation); - elog(ERROR, "relation %u deleted while still in use", - buildinfo.i.info_id); + elog(ERROR, "relation %u deleted while still in use", save_relid); } relation->rd_refcnt = old_refcnt; relation->rd_createSubid = old_createSubid; @@ -1952,8 +1783,7 @@ RelationCacheInvalidate(void) if (relation->rd_isnailed && relation->rd_rel->relkind == RELKIND_INDEX) { - if (strcmp(RelationGetRelationName(relation), - ClassOidIndex) == 0) + if (RelationGetRelid(relation) == ClassOidIndexId) rebuildFirstList = lcons(relation, rebuildFirstList); else rebuildFirstList = lappend(rebuildFirstList, relation); @@ -2319,11 +2149,6 @@ RelationCacheInitialize(void) * create hashtables that index the relcache */ MemSet(&ctl, 0, sizeof(ctl)); - ctl.keysize = sizeof(NameData); - ctl.entrysize = sizeof(RelNameCacheEnt); - RelationSysNameCache = hash_create("Relcache by name", INITRELCACHESIZE, - &ctl, HASH_ELEM); - ctl.keysize = sizeof(Oid); ctl.entrysize = sizeof(RelIdCacheEnt); ctl.hash = tag_hash; @@ -2338,13 +2163,13 @@ RelationCacheInitialize(void) if (IsBootstrapProcessingMode() || !load_relcache_init_file()) { - formrdesc(RelationRelationName, PG_CLASS_RELTYPE_OID, + formrdesc("pg_class", PG_CLASS_RELTYPE_OID, true, Natts_pg_class, Desc_pg_class); - formrdesc(AttributeRelationName, PG_ATTRIBUTE_RELTYPE_OID, + formrdesc("pg_attribute", PG_ATTRIBUTE_RELTYPE_OID, false, Natts_pg_attribute, Desc_pg_attribute); - formrdesc(ProcedureRelationName, PG_PROC_RELTYPE_OID, + formrdesc("pg_proc", PG_PROC_RELTYPE_OID, true, Natts_pg_proc, Desc_pg_proc); - formrdesc(TypeRelationName, PG_TYPE_RELTYPE_OID, + formrdesc("pg_type", PG_TYPE_RELTYPE_OID, true, Natts_pg_type, Desc_pg_type); #define NUM_CRITICAL_RELS 4 /* fix if you change list above */ @@ -2393,27 +2218,23 @@ RelationCacheInitializePhase2(void) */ if (!criticalRelcachesBuilt) { - RelationBuildDescInfo buildinfo; Relation ird; -#define LOAD_CRIT_INDEX(indname) \ +#define LOAD_CRIT_INDEX(indexoid) \ do { \ - buildinfo.infotype = INFO_RELNAME; \ - buildinfo.i.info_name = (indname); \ - ird = RelationBuildDesc(buildinfo, NULL); \ + ird = RelationBuildDesc((indexoid), NULL); \ ird->rd_isnailed = true; \ ird->rd_refcnt = 1; \ } while (0) - LOAD_CRIT_INDEX(ClassNameNspIndex); - LOAD_CRIT_INDEX(ClassOidIndex); - LOAD_CRIT_INDEX(AttributeRelidNumIndex); - LOAD_CRIT_INDEX(IndexRelidIndex); - LOAD_CRIT_INDEX(AccessMethodStrategyIndex); - LOAD_CRIT_INDEX(AccessMethodProcedureIndex); - LOAD_CRIT_INDEX(OperatorOidIndex); + LOAD_CRIT_INDEX(ClassOidIndexId); + LOAD_CRIT_INDEX(AttributeRelidNumIndexId); + LOAD_CRIT_INDEX(IndexRelidIndexId); + LOAD_CRIT_INDEX(AccessMethodStrategyIndexId); + LOAD_CRIT_INDEX(AccessMethodProcedureIndexId); + LOAD_CRIT_INDEX(OperatorOidIndexId); -#define NUM_CRITICAL_INDEXES 7 /* fix if you change list above */ +#define NUM_CRITICAL_INDEXES 6 /* fix if you change list above */ criticalRelcachesBuilt = true; } @@ -2510,7 +2331,7 @@ RelationCacheInitializePhase3(void) * fields of pg_index before we have the standard catalog caches available. * We use predefined data that's set up in just the same way as the * bootstrapped reldescs used by formrdesc(). The resulting tupdesc is - * not 100% kosher: it does not have the correct relation OID in attrelid, + * not 100% kosher: it does not have the correct rowtype OID in tdtypeid, * nor does it have a TupleConstr field. But it's good enough for the * purpose of extracting fields. */ @@ -2569,8 +2390,8 @@ AttrDefaultFetch(Relation relation) BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(RelationGetRelid(relation))); - adrel = heap_openr(AttrDefaultRelationName, AccessShareLock); - adscan = systable_beginscan(adrel, AttrDefaultIndex, true, + adrel = heap_open(AttrDefaultRelationId, AccessShareLock); + adscan = systable_beginscan(adrel, AttrDefaultIndexId, true, SnapshotNow, 1, &skey); found = 0; @@ -2634,8 +2455,8 @@ CheckConstraintFetch(Relation relation) BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(RelationGetRelid(relation))); - conrel = heap_openr(ConstraintRelationName, AccessShareLock); - conscan = systable_beginscan(conrel, ConstraintRelidIndex, true, + conrel = heap_open(ConstraintRelationId, AccessShareLock); + conscan = systable_beginscan(conrel, ConstraintRelidIndexId, true, SnapshotNow, 1, skey); while (HeapTupleIsValid(htup = systable_getnext(conscan))) @@ -2725,8 +2546,8 @@ RelationGetIndexList(Relation relation) BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(RelationGetRelid(relation))); - indrel = heap_openr(IndexRelationName, AccessShareLock); - indscan = systable_beginscan(indrel, IndexIndrelidIndex, true, + indrel = heap_open(IndexRelationId, AccessShareLock); + indscan = systable_beginscan(indrel, IndexIndrelidIndexId, true, SnapshotNow, 1, &skey); while (HeapTupleIsValid(htup = systable_getnext(indscan))) diff --git a/src/backend/utils/cache/syscache.c b/src/backend/utils/cache/syscache.c index b7b7ec249d3..0cea023bb90 100644 --- a/src/backend/utils/cache/syscache.c +++ b/src/backend/utils/cache/syscache.c @@ -8,7 +8,7 @@ * * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/cache/syscache.c,v 1.97 2005/03/29 00:17:12 tgl Exp $ + * $PostgreSQL: pgsql/src/backend/utils/cache/syscache.c,v 1.98 2005/04/14 20:03:26 tgl Exp $ * * NOTES * These routines allow the parser/planner/executor to perform @@ -23,7 +23,6 @@ #include "access/heapam.h" #include "access/transam.h" #include "utils/builtins.h" -#include "catalog/catname.h" #include "catalog/indexing.h" #include "catalog/pg_aggregate.h" #include "catalog/pg_amop.h" @@ -57,7 +56,7 @@ Add your entry to the cacheinfo[] array below. All cache lists are alphabetical, so add it in the proper place. Specify the relation - name, index name, number of keys, and key attribute numbers. If the + OID, index OID, number of keys, and key attribute numbers. If the relation contains tuples that are associated with a particular relation (for example, its attributes, rules, triggers, etc) then specify the attribute number that contains the OID of the associated relation. @@ -66,18 +65,18 @@ There must be a unique index underlying each syscache (ie, an index whose key is the same as that of the cache). If there is not one - already, add definitions for it to include/catalog/indexing.h: you - need a #define for the index name and a DECLARE_UNIQUE_INDEX macro - with the actual declaration. (This will require a catversion.h update, - while simply adding/deleting caches only requires a recompile.) + already, add definitions for it to include/catalog/indexing.h: you need + to add a DECLARE_UNIQUE_INDEX macro and a #define for the index OID. + (Adding an index requires a catversion.h update, while simply + adding/deleting caches only requires a recompile.) Finally, any place your relation gets heap_insert() or - heap_update calls, make sure there is a CatalogUpdateIndexes() or + heap_update() calls, make sure there is a CatalogUpdateIndexes() or similar call. The heap_* calls do not update indexes. bjm 1999/11/22 - --------------------------------------------------------------------------- +*--------------------------------------------------------------------------- */ /* @@ -85,16 +84,16 @@ */ struct cachedesc { - const char *name; /* name of the relation being cached */ - const char *indname; /* name of index relation for this cache */ + Oid reloid; /* OID of the relation being cached */ + Oid indoid; /* OID of index relation for this cache */ int reloidattr; /* attr number of rel OID reference, or 0 */ int nkeys; /* # of keys needed for cache lookup */ int key[4]; /* attribute numbers of key attrs */ }; static const struct cachedesc cacheinfo[] = { - {AggregateRelationName, /* AGGFNOID */ - AggregateFnoidIndex, + {AggregateRelationId, /* AGGFNOID */ + AggregateFnoidIndexId, 0, 1, { @@ -103,8 +102,8 @@ static const struct cachedesc cacheinfo[] = { 0, 0 }}, - {AccessMethodRelationName, /* AMNAME */ - AmNameIndex, + {AccessMethodRelationId, /* AMNAME */ + AmNameIndexId, 0, 1, { @@ -113,8 +112,8 @@ static const struct cachedesc cacheinfo[] = { 0, 0 }}, - {AccessMethodRelationName, /* AMOID */ - AmOidIndex, + {AccessMethodRelationId, /* AMOID */ + AmOidIndexId, 0, 1, { @@ -123,8 +122,8 @@ static const struct cachedesc cacheinfo[] = { 0, 0 }}, - {AccessMethodOperatorRelationName, /* AMOPOPID */ - AccessMethodOperatorIndex, + {AccessMethodOperatorRelationId, /* AMOPOPID */ + AccessMethodOperatorIndexId, 0, 2, { @@ -133,8 +132,8 @@ static const struct cachedesc cacheinfo[] = { 0, 0 }}, - {AccessMethodOperatorRelationName, /* AMOPSTRATEGY */ - AccessMethodStrategyIndex, + {AccessMethodOperatorRelationId, /* AMOPSTRATEGY */ + AccessMethodStrategyIndexId, 0, 3, { @@ -143,8 +142,8 @@ static const struct cachedesc cacheinfo[] = { Anum_pg_amop_amopstrategy, 0 }}, - {AccessMethodProcedureRelationName, /* AMPROCNUM */ - AccessMethodProcedureIndex, + {AccessMethodProcedureRelationId, /* AMPROCNUM */ + AccessMethodProcedureIndexId, 0, 3, { @@ -153,8 +152,8 @@ static const struct cachedesc cacheinfo[] = { Anum_pg_amproc_amprocnum, 0 }}, - {AttributeRelationName, /* ATTNAME */ - AttributeRelidNameIndex, + {AttributeRelationId, /* ATTNAME */ + AttributeRelidNameIndexId, Anum_pg_attribute_attrelid, 2, { @@ -163,8 +162,8 @@ static const struct cachedesc cacheinfo[] = { 0, 0 }}, - {AttributeRelationName, /* ATTNUM */ - AttributeRelidNumIndex, + {AttributeRelationId, /* ATTNUM */ + AttributeRelidNumIndexId, Anum_pg_attribute_attrelid, 2, { @@ -174,8 +173,8 @@ static const struct cachedesc cacheinfo[] = { 0 }}, { - CastRelationName, /* CASTSOURCETARGET */ - CastSourceTargetIndex, + CastRelationId, /* CASTSOURCETARGET */ + CastSourceTargetIndexId, 0, 2, { @@ -184,8 +183,8 @@ static const struct cachedesc cacheinfo[] = { 0, 0 }}, - {OperatorClassRelationName, /* CLAAMNAMENSP */ - OpclassAmNameNspIndex, + {OperatorClassRelationId, /* CLAAMNAMENSP */ + OpclassAmNameNspIndexId, 0, 3, { @@ -194,8 +193,8 @@ static const struct cachedesc cacheinfo[] = { Anum_pg_opclass_opcnamespace, 0 }}, - {OperatorClassRelationName, /* CLAOID */ - OpclassOidIndex, + {OperatorClassRelationId, /* CLAOID */ + OpclassOidIndexId, 0, 1, { @@ -204,8 +203,8 @@ static const struct cachedesc cacheinfo[] = { 0, 0 }}, - {ConversionRelationName, /* CONDEFAULT */ - ConversionDefaultIndex, + {ConversionRelationId, /* CONDEFAULT */ + ConversionDefaultIndexId, 0, 4, { @@ -214,8 +213,8 @@ static const struct cachedesc cacheinfo[] = { Anum_pg_conversion_contoencoding, ObjectIdAttributeNumber, }}, - {ConversionRelationName, /* CONNAMENSP */ - ConversionNameNspIndex, + {ConversionRelationId, /* CONNAMENSP */ + ConversionNameNspIndexId, 0, 2, { @@ -224,8 +223,8 @@ static const struct cachedesc cacheinfo[] = { 0, 0 }}, - {ConversionRelationName, /* CONOID */ - ConversionOidIndex, + {ConversionRelationId, /* CONOID */ + ConversionOidIndexId, 0, 1, { @@ -234,8 +233,8 @@ static const struct cachedesc cacheinfo[] = { 0, 0 }}, - {GroupRelationName, /* GRONAME */ - GroupNameIndex, + {GroupRelationId, /* GRONAME */ + GroupNameIndexId, 0, 1, { @@ -244,8 +243,8 @@ static const struct cachedesc cacheinfo[] = { 0, 0 }}, - {GroupRelationName, /* GROSYSID */ - GroupSysidIndex, + {GroupRelationId, /* GROSYSID */ + GroupSysidIndexId, 0, 1, { @@ -254,8 +253,8 @@ static const struct cachedesc cacheinfo[] = { 0, 0 }}, - {IndexRelationName, /* INDEXRELID */ - IndexRelidIndex, + {IndexRelationId, /* INDEXRELID */ + IndexRelidIndexId, Anum_pg_index_indrelid, 1, { @@ -264,8 +263,8 @@ static const struct cachedesc cacheinfo[] = { 0, 0 }}, - {InheritsRelationName, /* INHRELID */ - InheritsRelidSeqnoIndex, + {InheritsRelationId, /* INHRELID */ + InheritsRelidSeqnoIndexId, Anum_pg_inherits_inhrelid, 2, { @@ -274,8 +273,8 @@ static const struct cachedesc cacheinfo[] = { 0, 0 }}, - {LanguageRelationName, /* LANGNAME */ - LanguageNameIndex, + {LanguageRelationId, /* LANGNAME */ + LanguageNameIndexId, 0, 1, { @@ -284,8 +283,8 @@ static const struct cachedesc cacheinfo[] = { 0, 0 }}, - {LanguageRelationName, /* LANGOID */ - LanguageOidIndex, + {LanguageRelationId, /* LANGOID */ + LanguageOidIndexId, 0, 1, { @@ -294,8 +293,8 @@ static const struct cachedesc cacheinfo[] = { 0, 0 }}, - {NamespaceRelationName, /* NAMESPACENAME */ - NamespaceNameIndex, + {NamespaceRelationId, /* NAMESPACENAME */ + NamespaceNameIndexId, 0, 1, { @@ -304,8 +303,8 @@ static const struct cachedesc cacheinfo[] = { 0, 0 }}, - {NamespaceRelationName, /* NAMESPACEOID */ - NamespaceOidIndex, + {NamespaceRelationId, /* NAMESPACEOID */ + NamespaceOidIndexId, 0, 1, { @@ -314,8 +313,8 @@ static const struct cachedesc cacheinfo[] = { 0, 0 }}, - {OperatorRelationName, /* OPERNAMENSP */ - OperatorNameNspIndex, + {OperatorRelationId, /* OPERNAMENSP */ + OperatorNameNspIndexId, 0, 4, { @@ -324,8 +323,8 @@ static const struct cachedesc cacheinfo[] = { Anum_pg_operator_oprright, Anum_pg_operator_oprnamespace }}, - {OperatorRelationName, /* OPEROID */ - OperatorOidIndex, + {OperatorRelationId, /* OPEROID */ + OperatorOidIndexId, 0, 1, { @@ -334,8 +333,8 @@ static const struct cachedesc cacheinfo[] = { 0, 0 }}, - {ProcedureRelationName, /* PROCNAMEARGSNSP */ - ProcedureNameArgsNspIndex, + {ProcedureRelationId, /* PROCNAMEARGSNSP */ + ProcedureNameArgsNspIndexId, 0, 3, { @@ -344,8 +343,8 @@ static const struct cachedesc cacheinfo[] = { Anum_pg_proc_pronamespace, 0 }}, - {ProcedureRelationName, /* PROCOID */ - ProcedureOidIndex, + {ProcedureRelationId, /* PROCOID */ + ProcedureOidIndexId, 0, 1, { @@ -354,8 +353,8 @@ static const struct cachedesc cacheinfo[] = { 0, 0 }}, - {RelationRelationName, /* RELNAMENSP */ - ClassNameNspIndex, + {RelationRelationId, /* RELNAMENSP */ + ClassNameNspIndexId, ObjectIdAttributeNumber, 2, { @@ -364,8 +363,8 @@ static const struct cachedesc cacheinfo[] = { 0, 0 }}, - {RelationRelationName, /* RELOID */ - ClassOidIndex, + {RelationRelationId, /* RELOID */ + ClassOidIndexId, ObjectIdAttributeNumber, 1, { @@ -374,8 +373,8 @@ static const struct cachedesc cacheinfo[] = { 0, 0 }}, - {RewriteRelationName, /* RULERELNAME */ - RewriteRelRulenameIndex, + {RewriteRelationId, /* RULERELNAME */ + RewriteRelRulenameIndexId, Anum_pg_rewrite_ev_class, 2, { @@ -384,8 +383,8 @@ static const struct cachedesc cacheinfo[] = { 0, 0 }}, - {ShadowRelationName, /* SHADOWNAME */ - ShadowNameIndex, + {ShadowRelationId, /* SHADOWNAME */ + ShadowNameIndexId, 0, 1, { @@ -394,8 +393,8 @@ static const struct cachedesc cacheinfo[] = { 0, 0 }}, - {ShadowRelationName, /* SHADOWSYSID */ - ShadowSysidIndex, + {ShadowRelationId, /* SHADOWSYSID */ + ShadowSysidIndexId, 0, 1, { @@ -404,8 +403,8 @@ static const struct cachedesc cacheinfo[] = { 0, 0 }}, - {StatisticRelationName, /* STATRELATT */ - StatisticRelidAttnumIndex, + {StatisticRelationId, /* STATRELATT */ + StatisticRelidAttnumIndexId, Anum_pg_statistic_starelid, 2, { @@ -414,8 +413,8 @@ static const struct cachedesc cacheinfo[] = { 0, 0 }}, - {TypeRelationName, /* TYPENAMENSP */ - TypeNameNspIndex, + {TypeRelationId, /* TYPENAMENSP */ + TypeNameNspIndexId, Anum_pg_type_typrelid, 2, { @@ -424,8 +423,8 @@ static const struct cachedesc cacheinfo[] = { 0, 0 }}, - {TypeRelationName, /* TYPEOID */ - TypeOidIndex, + {TypeRelationId, /* TYPEOID */ + TypeOidIndexId, Anum_pg_type_typrelid, 1, { @@ -436,8 +435,7 @@ static const struct cachedesc cacheinfo[] = { }} }; -static CatCache *SysCache[ - lengthof(cacheinfo)]; +static CatCache *SysCache[lengthof(cacheinfo)]; static int SysCacheSize = lengthof(cacheinfo); static bool CacheInitialized = false; @@ -462,14 +460,14 @@ InitCatalogCache(void) for (cacheId = 0; cacheId < SysCacheSize; cacheId++) { SysCache[cacheId] = InitCatCache(cacheId, - cacheinfo[cacheId].name, - cacheinfo[cacheId].indname, + cacheinfo[cacheId].reloid, + cacheinfo[cacheId].indoid, cacheinfo[cacheId].reloidattr, cacheinfo[cacheId].nkeys, cacheinfo[cacheId].key); if (!PointerIsValid(SysCache[cacheId])) - elog(ERROR, "could not initialize cache %s (%d)", - cacheinfo[cacheId].name, cacheId); + elog(ERROR, "could not initialize cache %u (%d)", + cacheinfo[cacheId].reloid, cacheId); } CacheInitialized = true; } diff --git a/src/backend/utils/cache/typcache.c b/src/backend/utils/cache/typcache.c index 7e15f884f61..01990db8ad9 100644 --- a/src/backend/utils/cache/typcache.c +++ b/src/backend/utils/cache/typcache.c @@ -36,7 +36,7 @@ * Portions Copyright (c) 1994, Regents of the University of California * * IDENTIFICATION - * $PostgreSQL: pgsql/src/backend/utils/cache/typcache.c,v 1.11 2004/12/31 22:01:25 pgsql Exp $ + * $PostgreSQL: pgsql/src/backend/utils/cache/typcache.c,v 1.12 2005/04/14 20:03:26 tgl Exp $ * *------------------------------------------------------------------------- */ @@ -46,7 +46,6 @@ #include "access/heapam.h" #include "access/hash.h" #include "access/nbtree.h" -#include "catalog/catname.h" #include "catalog/indexing.h" #include "catalog/pg_am.h" #include "catalog/pg_opclass.h" @@ -328,14 +327,14 @@ lookup_default_opclass(Oid type_id, Oid am_id) * that we consider all opclasses, regardless of the current search * path. */ - rel = heap_openr(OperatorClassRelationName, AccessShareLock); + rel = heap_open(OperatorClassRelationId, AccessShareLock); ScanKeyInit(&skey[0], Anum_pg_opclass_opcamid, BTEqualStrategyNumber, F_OIDEQ, ObjectIdGetDatum(am_id)); - scan = systable_beginscan(rel, OpclassAmNameNspIndex, true, + scan = systable_beginscan(rel, OpclassAmNameNspIndexId, true, SnapshotNow, 1, skey); while (HeapTupleIsValid(tup = systable_getnext(scan))) |