diff options
Diffstat (limited to 'src/backend/utils/cache/relcache.c')
-rw-r--r-- | src/backend/utils/cache/relcache.c | 123 |
1 files changed, 120 insertions, 3 deletions
diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index 54a40ef00bd..0b0508c01d8 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -37,6 +37,7 @@ #include "access/reloptions.h" #include "access/sysattr.h" #include "access/table.h" +#include "access/tableam.h" #include "access/tupdesc_details.h" #include "access/xact.h" #include "access/xlog.h" @@ -1137,10 +1138,32 @@ RelationBuildDesc(Oid targetRelId, bool insertIt) } /* - * if it's an index, initialize index-related information + * initialize access method information */ - if (OidIsValid(relation->rd_rel->relam)) - RelationInitIndexAccessInfo(relation); + switch (relation->rd_rel->relkind) + { + case RELKIND_INDEX: + case RELKIND_PARTITIONED_INDEX: + Assert(relation->rd_rel->relam != InvalidOid); + RelationInitIndexAccessInfo(relation); + break; + case RELKIND_RELATION: + case RELKIND_TOASTVALUE: + case RELKIND_MATVIEW: + Assert(relation->rd_rel->relam != InvalidOid); + RelationInitTableAccessMethod(relation); + break; + case RELKIND_SEQUENCE: + Assert(relation->rd_rel->relam == InvalidOid); + RelationInitTableAccessMethod(relation); + break; + case RELKIND_VIEW: + case RELKIND_COMPOSITE_TYPE: + case RELKIND_FOREIGN_TABLE: + case RELKIND_PARTITIONED_TABLE: + Assert(relation->rd_rel->relam == InvalidOid); + break; + } /* extract reloptions if any */ RelationParseRelOptions(relation, pg_class_tuple); @@ -1646,6 +1669,65 @@ LookupOpclassInfo(Oid operatorClassOid, return opcentry; } +/* + * Fill in the TableAmRoutine for a relation + * + * relation's rd_amhandler must be valid already. + */ +static void +InitTableAmRoutine(Relation relation) +{ + relation->rd_tableam = GetTableAmRoutine(relation->rd_amhandler); +} + +/* + * Initialize table access method support for a table like relation relation + */ +void +RelationInitTableAccessMethod(Relation relation) +{ + HeapTuple tuple; + Form_pg_am aform; + + if (relation->rd_rel->relkind == RELKIND_SEQUENCE) + { + /* + * Sequences are currently accessed like heap tables, but it doesn't + * seem prudent to show that in the catalog. So just overwrite it + * here. + */ + relation->rd_amhandler = HEAP_TABLE_AM_HANDLER_OID; + } + else if (IsCatalogRelation(relation)) + { + /* + * Avoid doing a syscache lookup for catalog tables. + */ + Assert(relation->rd_rel->relam == HEAP_TABLE_AM_OID); + relation->rd_amhandler = HEAP_TABLE_AM_HANDLER_OID; + } + else + { + /* + * Look up the table access method, save the OID of its handler + * function. + */ + Assert(relation->rd_rel->relam != InvalidOid); + tuple = SearchSysCache1(AMOID, + ObjectIdGetDatum(relation->rd_rel->relam)); + if (!HeapTupleIsValid(tuple)) + elog(ERROR, "cache lookup failed for access method %u", + relation->rd_rel->relam); + aform = (Form_pg_am) GETSTRUCT(tuple); + relation->rd_amhandler = aform->amhandler; + ReleaseSysCache(tuple); + } + + /* + * Now we can fetch the table AM's API struct + */ + InitTableAmRoutine(relation); +} /* * formrdesc @@ -1732,6 +1814,7 @@ formrdesc(const char *relationName, Oid relationReltype, relation->rd_rel->relallvisible = 0; relation->rd_rel->relkind = RELKIND_RELATION; relation->rd_rel->relnatts = (int16) natts; + relation->rd_rel->relam = HEAP_TABLE_AM_OID; /* * initialize attribute tuple form @@ -1800,6 +1883,12 @@ formrdesc(const char *relationName, Oid relationReltype, RelationInitPhysicalAddr(relation); /* + * initialize the table am handler + */ + relation->rd_rel->relam = HEAP_TABLE_AM_OID; + relation->rd_tableam = GetHeapamTableAmRoutine(); + + /* * initialize the rel-has-index flag, using hardwired knowledge */ if (IsBootstrapProcessingMode()) @@ -3032,6 +3121,7 @@ RelationBuildLocalRelation(const char *relname, Oid relnamespace, TupleDesc tupDesc, Oid relid, + Oid accessmtd, Oid relfilenode, Oid reltablespace, bool shared_relation, @@ -3211,6 +3301,14 @@ RelationBuildLocalRelation(const char *relname, RelationInitPhysicalAddr(rel); + rel->rd_rel->relam = accessmtd; + + if (relkind == RELKIND_RELATION || + relkind == RELKIND_SEQUENCE || + relkind == RELKIND_TOASTVALUE || + relkind == RELKIND_MATVIEW) + RelationInitTableAccessMethod(rel); + /* * Okay to insert into the relcache hash table. * @@ -3731,6 +3829,18 @@ RelationCacheInitializePhase3(void) restart = true; } + if (relation->rd_tableam == NULL && + (relation->rd_rel->relkind == RELKIND_RELATION || + relation->rd_rel->relkind == RELKIND_SEQUENCE || + relation->rd_rel->relkind == RELKIND_TOASTVALUE || + relation->rd_rel->relkind == RELKIND_MATVIEW)) + { + RelationInitTableAccessMethod(relation); + Assert(relation->rd_tableam != NULL); + + restart = true; + } + /* Release hold on the relation */ RelationDecrementReferenceCount(relation); @@ -5380,6 +5490,13 @@ load_relcache_init_file(bool shared) if (rel->rd_isnailed) nailed_rels++; + /* Load table AM data */ + if (rel->rd_rel->relkind == RELKIND_RELATION || + rel->rd_rel->relkind == RELKIND_SEQUENCE || + rel->rd_rel->relkind == RELKIND_TOASTVALUE || + rel->rd_rel->relkind == RELKIND_MATVIEW) + RelationInitTableAccessMethod(rel); + Assert(rel->rd_index == NULL); Assert(rel->rd_indextuple == NULL); Assert(rel->rd_indexcxt == NULL); |