From be8cd6f8e676e3b158928f0e31185ade0215a10f Mon Sep 17 00:00:00 2001 From: Hari Babu Date: Thu, 29 Mar 2018 16:59:20 +1100 Subject: [PATCH 03/16] Adding tableam hanlder to relation structure And also the necessary functions to initialize the tableam handler --- src/backend/utils/cache/relcache.c | 121 ++++++++++++++++++++++++++++++++++++- src/include/utils/rel.h | 12 ++++ src/include/utils/relcache.h | 2 + 3 files changed, 132 insertions(+), 3 deletions(-) diff --git a/src/backend/utils/cache/relcache.c b/src/backend/utils/cache/relcache.c index d85dc92505..4ad19db3e4 100644 --- a/src/backend/utils/cache/relcache.c +++ b/src/backend/utils/cache/relcache.c @@ -36,6 +36,7 @@ #include "access/nbtree.h" #include "access/reloptions.h" #include "access/sysattr.h" +#include "access/tableamapi.h" #include "access/tupdesc_details.h" #include "access/xact.h" #include "access/xlog.h" @@ -1199,10 +1200,29 @@ 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_SEQUENCE: + case RELKIND_TOASTVALUE: + case RELKIND_VIEW: /* Not exactly the storage, but underlying + * tuple access, it is required */ + case RELKIND_MATVIEW: + case RELKIND_PARTITIONED_TABLE: + case RELKIND_FOREIGN_TABLE: /* hari FIXME :To support COPY on foreign tables */ + RelationInitTableAccessMethod(relation); + break; + default: + /* nothing to do in other cases */ + break; + } /* extract reloptions if any */ RelationParseRelOptions(relation, pg_class_tuple); @@ -1704,6 +1724,71 @@ LookupOpclassInfo(Oid operatorClassOid, return opcentry; } +/* + * Fill in the TableAmRoutine for a relation + * + * relation's rd_tableamhandler must be valid already. + */ +static void +InitTableAmRoutine(Relation relation) +{ + TableAmRoutine *cached; + TableAmRoutine *tmp; + + /* + * Call the tableamhandler in current, short-lived memory context, just in case + * it leaks anything (it probably won't, but let's be paranoid). + */ + tmp = GetTableAmRoutine(relation->rd_tableamhandler); + + /* XXX do we need a separate memory context for this? */ + /* OK, now transfer the data into cache context */ + cached = (TableAmRoutine *) MemoryContextAlloc(CacheMemoryContext, + sizeof(TableAmRoutine)); + memcpy(cached, tmp, sizeof(TableAmRoutine)); + relation->rd_tableamroutine = cached; + + pfree(tmp); +} + +/* + * Initialize table-access-method support data for a heap relation + */ +void +RelationInitTableAccessMethod(Relation relation) +{ + HeapTuple tuple; + Form_pg_am aform; + + /* + * Relations that don't have a catalogued table access method use the + * standard heap tableam module; otherwise a catalog lookup is in order. + */ + if (!OidIsValid(relation->rd_rel->relam)) + { + relation->rd_tableamhandler = HEAP_TABLE_AM_HANDLER_OID; + } + else + { + /* + * Look up the table access method, save the OID of its handler + * function. + */ + 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_tableamhandler = aform->amhandler; + ReleaseSysCache(tuple); + } + + /* + * Now we can fetch the table AM's API struct + */ + InitTableAmRoutine(relation); +} /* * formrdesc @@ -1858,6 +1943,11 @@ formrdesc(const char *relationName, Oid relationReltype, */ RelationInitPhysicalAddr(relation); + /* + * initialize the table am handler + */ + relation->rd_tableamroutine = GetHeapamTableAmRoutine(); + /* * initialize the rel-has-index flag, using hardwired knowledge */ @@ -2274,6 +2364,8 @@ RelationDestroyRelation(Relation relation, bool remember_tupdesc) pfree(relation->rd_pubactions); if (relation->rd_options) pfree(relation->rd_options); + if (relation->rd_tableamroutine) + pfree(relation->rd_tableamroutine); if (relation->rd_indextuple) pfree(relation->rd_indextuple); if (relation->rd_indexcxt) @@ -3275,6 +3367,14 @@ RelationBuildLocalRelation(const char *relname, RelationInitPhysicalAddr(rel); + if (relkind == RELKIND_RELATION || + relkind == RELKIND_MATVIEW || + relkind == RELKIND_VIEW || /* Not exactly the storage, but underlying + * tuple access, it is required */ + relkind == RELKIND_PARTITIONED_TABLE || + relkind == RELKIND_TOASTVALUE) + RelationInitTableAccessMethod(rel); + /* * Okay to insert into the relcache hash table. * @@ -3796,6 +3896,18 @@ RelationCacheInitializePhase3(void) restart = true; } + if (relation->rd_tableamroutine == NULL && + (relation->rd_rel->relkind == RELKIND_RELATION || + relation->rd_rel->relkind == RELKIND_MATVIEW || + relation->rd_rel->relkind == RELKIND_PARTITIONED_TABLE || + relation->rd_rel->relkind == RELKIND_TOASTVALUE)) + { + RelationInitTableAccessMethod(relation); + Assert(relation->rd_tableamroutine != NULL); + + restart = true; + } + /* Release hold on the relation */ RelationDecrementReferenceCount(relation); @@ -5620,6 +5732,9 @@ load_relcache_init_file(bool shared) if (rel->rd_isnailed) nailed_rels++; + /* Load table AM stuff */ + RelationInitTableAccessMethod(rel); + Assert(rel->rd_index == NULL); Assert(rel->rd_indextuple == NULL); Assert(rel->rd_indexcxt == NULL); diff --git a/src/include/utils/rel.h b/src/include/utils/rel.h index c97f9d1b43..ded5b077e0 100644 --- a/src/include/utils/rel.h +++ b/src/include/utils/rel.h @@ -132,6 +132,12 @@ typedef struct RelationData /* use "struct" here to avoid needing to include htup.h: */ struct HeapTupleData *rd_indextuple; /* all of pg_index tuple */ + /* + * Underlying table access method support + */ + Oid rd_tableamhandler; /* OID of table AM handler function */ + struct TableAmRoutine *rd_tableamroutine; /* table AM's API struct */ + /* * index access support info (used only for an index relation) * @@ -432,6 +438,12 @@ typedef struct ViewOptions */ #define RelationGetDescr(relation) ((relation)->rd_att) +/* + * RelationGetTableamRoutine + * Returns the table AM routine for a relation. + */ +#define RelationGettableamRoutine(relation) ((relation)->rd_tableamroutine) + /* * RelationGetRelationName * Returns the rel's name. diff --git a/src/include/utils/relcache.h b/src/include/utils/relcache.h index dbbf41b0c1..df16b4ca98 100644 --- a/src/include/utils/relcache.h +++ b/src/include/utils/relcache.h @@ -77,6 +77,8 @@ extern void RelationInitIndexAccessInfo(Relation relation); struct PublicationActions; extern struct PublicationActions *GetRelationPublicationActions(Relation relation); +extern void RelationInitTableAccessMethod(Relation relation); + /* * Routines to support ereport() reports of relation-related errors */ -- 2.16.1.windows.4