aboutsummaryrefslogtreecommitdiff
path: root/src/backend/utils/cache/relcache.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/backend/utils/cache/relcache.c')
-rw-r--r--src/backend/utils/cache/relcache.c123
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);