Introduce access/{table.h, relation.h}, for generic functions from heapam.h.
authorAndres Freund <[email protected]>
Mon, 21 Jan 2019 18:14:09 +0000 (10:14 -0800)
committerAndres Freund <[email protected]>
Mon, 21 Jan 2019 18:51:36 +0000 (10:51 -0800)
access/heapam contains functions that are very storage specific (say
heap_insert() and a lot of lower level functions), and fairly generic
infrastructure like relation_open(), heap_open() etc.  In the upcoming
pluggable storage work we're introducing a layer between table
accesses in general and heapam, to allow for different storage
methods. For a bit cleaner separation it thus seems advantageous to
move generic functions like the aforementioned to their own headers.

access/relation.h will contain relation_open() etc, and access/table.h
will contain table_open() (formerly known as heap_open()). I've decided
for table.h not to include relation.h, but we might change that at a
later stage.

relation.h already exists in another directory, but the other
plausible name (rel.h) also conflicts. It'd be nice if there were a
non-conflicting name, but nobody came up with a suggestion. It's
possible that the appropriate way to address the naming conflict would
be to rename nodes/relation.h, which isn't particularly well named.

To avoid breaking a lot of extensions that just use heap_open() etc,
table.h has macros mapping the old names to the new ones, and heapam.h
includes relation, table.h.  That also allows to keep the
bulk renaming of existing callers in a separate commit.

Author: Andres Freund
Discussion: https://postgr.es/m/20190111000539[email protected]

src/backend/access/Makefile
src/backend/access/common/Makefile
src/backend/access/common/relation.c [new file with mode: 0644]
src/backend/access/heap/heapam.c
src/backend/access/table/Makefile [new file with mode: 0644]
src/backend/access/table/table.c [new file with mode: 0644]
src/include/access/heapam.h
src/include/access/relation.h [new file with mode: 0644]
src/include/access/table.h [new file with mode: 0644]

index bd93a6a8d1e606fcb6ce30deeddd5068c97b3f85..0880e0a8bbb63901164aef4a2de577db59c98b25 100644 (file)
@@ -9,6 +9,6 @@ top_builddir = ../../..
 include $(top_builddir)/src/Makefile.global
 
 SUBDIRS        = brin common gin gist hash heap index nbtree rmgrdesc spgist \
-             tablesample transam
+             table tablesample transam
 
 include $(top_srcdir)/src/backend/common.mk
index f130b6e3501662b468661833ce88e27577241463..d46950433771b5a38e5612a7ba3db8b1e189b1aa 100644 (file)
@@ -13,6 +13,6 @@ top_builddir = ../../../..
 include $(top_builddir)/src/Makefile.global
 
 OBJS = bufmask.o heaptuple.o indextuple.o printsimple.o printtup.o \
-   reloptions.o scankey.o session.o tupconvert.o tupdesc.o
+   relation.o reloptions.o scankey.o session.o tupconvert.o tupdesc.o
 
 include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/access/common/relation.c b/src/backend/access/common/relation.c
new file mode 100644 (file)
index 0000000..beec34f
--- /dev/null
@@ -0,0 +1,217 @@
+/*-------------------------------------------------------------------------
+ *
+ * relation.c
+ *   Generic relation related routines.
+ *
+ * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ *   src/backend/access/common/relation.c
+ *
+ * NOTES
+ *   This file contains relation_ routines that implement access to relations
+ *   (tables, indexes, etc). Support that's specific to subtypes of relations
+ *   should go into their respective files, not here.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "access/relation.h"
+#include "access/xact.h"
+#include "catalog/namespace.h"
+#include "miscadmin.h"
+#include "pgstat.h"
+#include "storage/lmgr.h"
+#include "utils/inval.h"
+#include "utils/syscache.h"
+
+
+/* ----------------
+ *     relation_open - open any relation by relation OID
+ *
+ *     If lockmode is not "NoLock", the specified kind of lock is
+ *     obtained on the relation.  (Generally, NoLock should only be
+ *     used if the caller knows it has some appropriate lock on the
+ *     relation already.)
+ *
+ *     An error is raised if the relation does not exist.
+ *
+ *     NB: a "relation" is anything with a pg_class entry.  The caller is
+ *     expected to check whether the relkind is something it can handle.
+ * ----------------
+ */
+Relation
+relation_open(Oid relationId, LOCKMODE lockmode)
+{
+   Relation    r;
+
+   Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);
+
+   /* Get the lock before trying to open the relcache entry */
+   if (lockmode != NoLock)
+       LockRelationOid(relationId, lockmode);
+
+   /* The relcache does all the real work... */
+   r = RelationIdGetRelation(relationId);
+
+   if (!RelationIsValid(r))
+       elog(ERROR, "could not open relation with OID %u", relationId);
+
+   /*
+    * If we didn't get the lock ourselves, assert that caller holds one,
+    * except in bootstrap mode where no locks are used.
+    */
+   Assert(lockmode != NoLock ||
+          IsBootstrapProcessingMode() ||
+          CheckRelationLockedByMe(r, AccessShareLock, true));
+
+   /* Make note that we've accessed a temporary relation */
+   if (RelationUsesLocalBuffers(r))
+       MyXactFlags |= XACT_FLAGS_ACCESSEDTEMPREL;
+
+   pgstat_initstats(r);
+
+   return r;
+}
+
+/* ----------------
+ *     try_relation_open - open any relation by relation OID
+ *
+ *     Same as relation_open, except return NULL instead of failing
+ *     if the relation does not exist.
+ * ----------------
+ */
+Relation
+try_relation_open(Oid relationId, LOCKMODE lockmode)
+{
+   Relation    r;
+
+   Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);
+
+   /* Get the lock first */
+   if (lockmode != NoLock)
+       LockRelationOid(relationId, lockmode);
+
+   /*
+    * Now that we have the lock, probe to see if the relation really exists
+    * or not.
+    */
+   if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(relationId)))
+   {
+       /* Release useless lock */
+       if (lockmode != NoLock)
+           UnlockRelationOid(relationId, lockmode);
+
+       return NULL;
+   }
+
+   /* Should be safe to do a relcache load */
+   r = RelationIdGetRelation(relationId);
+
+   if (!RelationIsValid(r))
+       elog(ERROR, "could not open relation with OID %u", relationId);
+
+   /* If we didn't get the lock ourselves, assert that caller holds one */
+   Assert(lockmode != NoLock ||
+          CheckRelationLockedByMe(r, AccessShareLock, true));
+
+   /* Make note that we've accessed a temporary relation */
+   if (RelationUsesLocalBuffers(r))
+       MyXactFlags |= XACT_FLAGS_ACCESSEDTEMPREL;
+
+   pgstat_initstats(r);
+
+   return r;
+}
+
+/* ----------------
+ *     relation_openrv - open any relation specified by a RangeVar
+ *
+ *     Same as relation_open, but the relation is specified by a RangeVar.
+ * ----------------
+ */
+Relation
+relation_openrv(const RangeVar *relation, LOCKMODE lockmode)
+{
+   Oid         relOid;
+
+   /*
+    * Check for shared-cache-inval messages before trying to open the
+    * relation.  This is needed even if we already hold a lock on the
+    * relation, because GRANT/REVOKE are executed without taking any lock on
+    * the target relation, and we want to be sure we see current ACL
+    * information.  We can skip this if asked for NoLock, on the assumption
+    * that such a call is not the first one in the current command, and so we
+    * should be reasonably up-to-date already.  (XXX this all could stand to
+    * be redesigned, but for the moment we'll keep doing this like it's been
+    * done historically.)
+    */
+   if (lockmode != NoLock)
+       AcceptInvalidationMessages();
+
+   /* Look up and lock the appropriate relation using namespace search */
+   relOid = RangeVarGetRelid(relation, lockmode, false);
+
+   /* Let relation_open do the rest */
+   return relation_open(relOid, NoLock);
+}
+
+/* ----------------
+ *     relation_openrv_extended - open any relation specified by a RangeVar
+ *
+ *     Same as relation_openrv, but with an additional missing_ok argument
+ *     allowing a NULL return rather than an error if the relation is not
+ *     found.  (Note that some other causes, such as permissions problems,
+ *     will still result in an ereport.)
+ * ----------------
+ */
+Relation
+relation_openrv_extended(const RangeVar *relation, LOCKMODE lockmode,
+                        bool missing_ok)
+{
+   Oid         relOid;
+
+   /*
+    * Check for shared-cache-inval messages before trying to open the
+    * relation.  See comments in relation_openrv().
+    */
+   if (lockmode != NoLock)
+       AcceptInvalidationMessages();
+
+   /* Look up and lock the appropriate relation using namespace search */
+   relOid = RangeVarGetRelid(relation, lockmode, missing_ok);
+
+   /* Return NULL on not-found */
+   if (!OidIsValid(relOid))
+       return NULL;
+
+   /* Let relation_open do the rest */
+   return relation_open(relOid, NoLock);
+}
+
+/* ----------------
+ *     relation_close - close any relation
+ *
+ *     If lockmode is not "NoLock", we then release the specified lock.
+ *
+ *     Note that it is often sensible to hold a lock beyond relation_close;
+ *     in that case, the lock is released automatically at xact end.
+ * ----------------
+ */
+void
+relation_close(Relation relation, LOCKMODE lockmode)
+{
+   LockRelId   relid = relation->rd_lockInfo.lockRelId;
+
+   Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);
+
+   /* The relcache does the real work... */
+   RelationClose(relation);
+
+   if (lockmode != NoLock)
+       UnlockRelationId(&relid, lockmode);
+}
index b6fe3a92f088d8c86ea0d9a0a9157dd6d21f3329..6c33aefd8553b460cdbfeea887169a283dfb1595 100644 (file)
  *
  *
  * INTERFACE ROUTINES
- *     relation_open   - open any relation by relation OID
- *     relation_openrv - open any relation specified by a RangeVar
- *     relation_close  - close any relation
- *     heap_open       - open a heap relation by relation OID
- *     heap_openrv     - open a heap relation specified by a RangeVar
- *     heap_close      - (now just a macro for relation_close)
  *     heap_beginscan  - begin relation scan
  *     heap_rescan     - restart a relation scan
  *     heap_endscan    - end relation scan
@@ -56,7 +50,6 @@
 #include "access/xloginsert.h"
 #include "access/xlogutils.h"
 #include "catalog/catalog.h"
-#include "catalog/namespace.h"
 #include "miscadmin.h"
 #include "pgstat.h"
 #include "port/atomics.h"
@@ -73,7 +66,6 @@
 #include "utils/lsyscache.h"
 #include "utils/relcache.h"
 #include "utils/snapmgr.h"
-#include "utils/syscache.h"
 #include "utils/tqual.h"
 
 
@@ -1103,287 +1095,6 @@ fastgetattr(HeapTuple tup, int attnum, TupleDesc tupleDesc,
  * ----------------------------------------------------------------
  */
 
-/* ----------------
- *     relation_open - open any relation by relation OID
- *
- *     If lockmode is not "NoLock", the specified kind of lock is
- *     obtained on the relation.  (Generally, NoLock should only be
- *     used if the caller knows it has some appropriate lock on the
- *     relation already.)
- *
- *     An error is raised if the relation does not exist.
- *
- *     NB: a "relation" is anything with a pg_class entry.  The caller is
- *     expected to check whether the relkind is something it can handle.
- * ----------------
- */
-Relation
-relation_open(Oid relationId, LOCKMODE lockmode)
-{
-   Relation    r;
-
-   Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);
-
-   /* Get the lock before trying to open the relcache entry */
-   if (lockmode != NoLock)
-       LockRelationOid(relationId, lockmode);
-
-   /* The relcache does all the real work... */
-   r = RelationIdGetRelation(relationId);
-
-   if (!RelationIsValid(r))
-       elog(ERROR, "could not open relation with OID %u", relationId);
-
-   /*
-    * If we didn't get the lock ourselves, assert that caller holds one,
-    * except in bootstrap mode where no locks are used.
-    */
-   Assert(lockmode != NoLock ||
-          IsBootstrapProcessingMode() ||
-          CheckRelationLockedByMe(r, AccessShareLock, true));
-
-   /* Make note that we've accessed a temporary relation */
-   if (RelationUsesLocalBuffers(r))
-       MyXactFlags |= XACT_FLAGS_ACCESSEDTEMPREL;
-
-   pgstat_initstats(r);
-
-   return r;
-}
-
-/* ----------------
- *     try_relation_open - open any relation by relation OID
- *
- *     Same as relation_open, except return NULL instead of failing
- *     if the relation does not exist.
- * ----------------
- */
-Relation
-try_relation_open(Oid relationId, LOCKMODE lockmode)
-{
-   Relation    r;
-
-   Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);
-
-   /* Get the lock first */
-   if (lockmode != NoLock)
-       LockRelationOid(relationId, lockmode);
-
-   /*
-    * Now that we have the lock, probe to see if the relation really exists
-    * or not.
-    */
-   if (!SearchSysCacheExists1(RELOID, ObjectIdGetDatum(relationId)))
-   {
-       /* Release useless lock */
-       if (lockmode != NoLock)
-           UnlockRelationOid(relationId, lockmode);
-
-       return NULL;
-   }
-
-   /* Should be safe to do a relcache load */
-   r = RelationIdGetRelation(relationId);
-
-   if (!RelationIsValid(r))
-       elog(ERROR, "could not open relation with OID %u", relationId);
-
-   /* If we didn't get the lock ourselves, assert that caller holds one */
-   Assert(lockmode != NoLock ||
-          CheckRelationLockedByMe(r, AccessShareLock, true));
-
-   /* Make note that we've accessed a temporary relation */
-   if (RelationUsesLocalBuffers(r))
-       MyXactFlags |= XACT_FLAGS_ACCESSEDTEMPREL;
-
-   pgstat_initstats(r);
-
-   return r;
-}
-
-/* ----------------
- *     relation_openrv - open any relation specified by a RangeVar
- *
- *     Same as relation_open, but the relation is specified by a RangeVar.
- * ----------------
- */
-Relation
-relation_openrv(const RangeVar *relation, LOCKMODE lockmode)
-{
-   Oid         relOid;
-
-   /*
-    * Check for shared-cache-inval messages before trying to open the
-    * relation.  This is needed even if we already hold a lock on the
-    * relation, because GRANT/REVOKE are executed without taking any lock on
-    * the target relation, and we want to be sure we see current ACL
-    * information.  We can skip this if asked for NoLock, on the assumption
-    * that such a call is not the first one in the current command, and so we
-    * should be reasonably up-to-date already.  (XXX this all could stand to
-    * be redesigned, but for the moment we'll keep doing this like it's been
-    * done historically.)
-    */
-   if (lockmode != NoLock)
-       AcceptInvalidationMessages();
-
-   /* Look up and lock the appropriate relation using namespace search */
-   relOid = RangeVarGetRelid(relation, lockmode, false);
-
-   /* Let relation_open do the rest */
-   return relation_open(relOid, NoLock);
-}
-
-/* ----------------
- *     relation_openrv_extended - open any relation specified by a RangeVar
- *
- *     Same as relation_openrv, but with an additional missing_ok argument
- *     allowing a NULL return rather than an error if the relation is not
- *     found.  (Note that some other causes, such as permissions problems,
- *     will still result in an ereport.)
- * ----------------
- */
-Relation
-relation_openrv_extended(const RangeVar *relation, LOCKMODE lockmode,
-                        bool missing_ok)
-{
-   Oid         relOid;
-
-   /*
-    * Check for shared-cache-inval messages before trying to open the
-    * relation.  See comments in relation_openrv().
-    */
-   if (lockmode != NoLock)
-       AcceptInvalidationMessages();
-
-   /* Look up and lock the appropriate relation using namespace search */
-   relOid = RangeVarGetRelid(relation, lockmode, missing_ok);
-
-   /* Return NULL on not-found */
-   if (!OidIsValid(relOid))
-       return NULL;
-
-   /* Let relation_open do the rest */
-   return relation_open(relOid, NoLock);
-}
-
-/* ----------------
- *     relation_close - close any relation
- *
- *     If lockmode is not "NoLock", we then release the specified lock.
- *
- *     Note that it is often sensible to hold a lock beyond relation_close;
- *     in that case, the lock is released automatically at xact end.
- * ----------------
- */
-void
-relation_close(Relation relation, LOCKMODE lockmode)
-{
-   LockRelId   relid = relation->rd_lockInfo.lockRelId;
-
-   Assert(lockmode >= NoLock && lockmode < MAX_LOCKMODES);
-
-   /* The relcache does the real work... */
-   RelationClose(relation);
-
-   if (lockmode != NoLock)
-       UnlockRelationId(&relid, lockmode);
-}
-
-
-/* ----------------
- *     heap_open - open a heap relation by relation OID
- *
- *     This is essentially relation_open plus check that the relation
- *     is not an index nor a composite type.  (The caller should also
- *     check that it's not a view or foreign table before assuming it has
- *     storage.)
- * ----------------
- */
-Relation
-heap_open(Oid relationId, LOCKMODE lockmode)
-{
-   Relation    r;
-
-   r = relation_open(relationId, lockmode);
-
-   if (r->rd_rel->relkind == RELKIND_INDEX ||
-       r->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
-       ereport(ERROR,
-               (errcode(ERRCODE_WRONG_OBJECT_TYPE),
-                errmsg("\"%s\" is an index",
-                       RelationGetRelationName(r))));
-   else if (r->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
-       ereport(ERROR,
-               (errcode(ERRCODE_WRONG_OBJECT_TYPE),
-                errmsg("\"%s\" is a composite type",
-                       RelationGetRelationName(r))));
-
-   return r;
-}
-
-/* ----------------
- *     heap_openrv - open a heap relation specified
- *     by a RangeVar node
- *
- *     As above, but relation is specified by a RangeVar.
- * ----------------
- */
-Relation
-heap_openrv(const RangeVar *relation, LOCKMODE lockmode)
-{
-   Relation    r;
-
-   r = relation_openrv(relation, lockmode);
-
-   if (r->rd_rel->relkind == RELKIND_INDEX ||
-       r->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
-       ereport(ERROR,
-               (errcode(ERRCODE_WRONG_OBJECT_TYPE),
-                errmsg("\"%s\" is an index",
-                       RelationGetRelationName(r))));
-   else if (r->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
-       ereport(ERROR,
-               (errcode(ERRCODE_WRONG_OBJECT_TYPE),
-                errmsg("\"%s\" is a composite type",
-                       RelationGetRelationName(r))));
-
-   return r;
-}
-
-/* ----------------
- *     heap_openrv_extended - open a heap relation specified
- *     by a RangeVar node
- *
- *     As above, but optionally return NULL instead of failing for
- *     relation-not-found.
- * ----------------
- */
-Relation
-heap_openrv_extended(const RangeVar *relation, LOCKMODE lockmode,
-                    bool missing_ok)
-{
-   Relation    r;
-
-   r = relation_openrv_extended(relation, lockmode, missing_ok);
-
-   if (r)
-   {
-       if (r->rd_rel->relkind == RELKIND_INDEX ||
-           r->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
-           ereport(ERROR,
-                   (errcode(ERRCODE_WRONG_OBJECT_TYPE),
-                    errmsg("\"%s\" is an index",
-                           RelationGetRelationName(r))));
-       else if (r->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
-           ereport(ERROR,
-                   (errcode(ERRCODE_WRONG_OBJECT_TYPE),
-                    errmsg("\"%s\" is a composite type",
-                           RelationGetRelationName(r))));
-   }
-
-   return r;
-}
-
 
 /* ----------------
  *     heap_beginscan  - begin relation scan
diff --git a/src/backend/access/table/Makefile b/src/backend/access/table/Makefile
new file mode 100644 (file)
index 0000000..ac1de5a
--- /dev/null
@@ -0,0 +1,17 @@
+#-------------------------------------------------------------------------
+#
+# Makefile--
+#    Makefile for access/table
+#
+# IDENTIFICATION
+#    src/backend/access/table/Makefile
+#
+#-------------------------------------------------------------------------
+
+subdir = src/backend/access/table
+top_builddir = ../../../..
+include $(top_builddir)/src/Makefile.global
+
+OBJS = table.o
+
+include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/access/table/table.c b/src/backend/access/table/table.c
new file mode 100644 (file)
index 0000000..a51c06c
--- /dev/null
@@ -0,0 +1,136 @@
+/*-------------------------------------------------------------------------
+ *
+ * table.c
+ *   Generic routines for table related code.
+ *
+ * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ *   src/backend/access/table/table.c
+ *
+ *
+ * NOTES
+ *   This file contains table_ routines that implement access to tables (in
+ *   contrast to other relation types like indexes) that are independent of
+ *   individual table access methods.
+ *
+ *-------------------------------------------------------------------------
+ */
+
+#include "postgres.h"
+
+#include "access/relation.h"
+#include "access/table.h"
+#include "storage/lmgr.h"
+
+
+/* ----------------
+ *     table_open - open a table relation by relation OID
+ *
+ *     This is essentially relation_open plus check that the relation
+ *     is not an index nor a composite type.  (The caller should also
+ *     check that it's not a view or foreign table before assuming it has
+ *     storage.)
+ * ----------------
+ */
+Relation
+table_open(Oid relationId, LOCKMODE lockmode)
+{
+   Relation    r;
+
+   r = relation_open(relationId, lockmode);
+
+   if (r->rd_rel->relkind == RELKIND_INDEX ||
+       r->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
+       ereport(ERROR,
+               (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+                errmsg("\"%s\" is an index",
+                       RelationGetRelationName(r))));
+   else if (r->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
+       ereport(ERROR,
+               (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+                errmsg("\"%s\" is a composite type",
+                       RelationGetRelationName(r))));
+
+   return r;
+}
+
+/* ----------------
+ *     table_openrv - open a table relation specified
+ *     by a RangeVar node
+ *
+ *     As above, but relation is specified by a RangeVar.
+ * ----------------
+ */
+Relation
+table_openrv(const RangeVar *relation, LOCKMODE lockmode)
+{
+   Relation    r;
+
+   r = relation_openrv(relation, lockmode);
+
+   if (r->rd_rel->relkind == RELKIND_INDEX ||
+       r->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
+       ereport(ERROR,
+               (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+                errmsg("\"%s\" is an index",
+                       RelationGetRelationName(r))));
+   else if (r->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
+       ereport(ERROR,
+               (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+                errmsg("\"%s\" is a composite type",
+                       RelationGetRelationName(r))));
+
+   return r;
+}
+
+/* ----------------
+ *     table_openrv_extended - open a table relation specified
+ *     by a RangeVar node
+ *
+ *     As above, but optionally return NULL instead of failing for
+ *     relation-not-found.
+ * ----------------
+ */
+Relation
+table_openrv_extended(const RangeVar *relation, LOCKMODE lockmode,
+                     bool missing_ok)
+{
+   Relation    r;
+
+   r = relation_openrv_extended(relation, lockmode, missing_ok);
+
+   if (r)
+   {
+       if (r->rd_rel->relkind == RELKIND_INDEX ||
+           r->rd_rel->relkind == RELKIND_PARTITIONED_INDEX)
+           ereport(ERROR,
+                   (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+                    errmsg("\"%s\" is an index",
+                           RelationGetRelationName(r))));
+       else if (r->rd_rel->relkind == RELKIND_COMPOSITE_TYPE)
+           ereport(ERROR,
+                   (errcode(ERRCODE_WRONG_OBJECT_TYPE),
+                    errmsg("\"%s\" is a composite type",
+                           RelationGetRelationName(r))));
+   }
+
+   return r;
+}
+
+/* ----------------
+ *     table_close - close a table
+ *
+ *     If lockmode is not "NoLock", we then release the specified lock.
+ *
+ *     Note that it is often sensible to hold a lock beyond relation_close;
+ *     in that case, the lock is released automatically at xact end.
+ *     ----------------
+ */
+void
+table_close(Relation relation, LOCKMODE lockmode)
+{
+   relation_close(relation, lockmode);
+}
index 4b7815033054bd0a0f03f7605459591e6476e22b..6a2489ede3cb8836b09223038da4a55a17ae9245 100644 (file)
 #ifndef HEAPAM_H
 #define HEAPAM_H
 
+#include "access/relation.h"   /* for backward compatibility */
 #include "access/sdir.h"
 #include "access/skey.h"
+#include "access/table.h"      /* for backward compatibility */
 #include "nodes/lockoptions.h"
 #include "nodes/primnodes.h"
 #include "storage/bufpage.h"
@@ -67,20 +69,6 @@ typedef struct HeapUpdateFailureData
  * ----------------
  */
 
-/* in heap/heapam.c */
-extern Relation relation_open(Oid relationId, LOCKMODE lockmode);
-extern Relation try_relation_open(Oid relationId, LOCKMODE lockmode);
-extern Relation relation_openrv(const RangeVar *relation, LOCKMODE lockmode);
-extern Relation relation_openrv_extended(const RangeVar *relation,
-                        LOCKMODE lockmode, bool missing_ok);
-extern void relation_close(Relation relation, LOCKMODE lockmode);
-
-extern Relation heap_open(Oid relationId, LOCKMODE lockmode);
-extern Relation heap_openrv(const RangeVar *relation, LOCKMODE lockmode);
-extern Relation heap_openrv_extended(const RangeVar *relation,
-                    LOCKMODE lockmode, bool missing_ok);
-
-#define heap_close(r,l)  relation_close(r,l)
 
 /* struct definitions appear in relscan.h */
 typedef struct HeapScanDescData *HeapScanDesc;
diff --git a/src/include/access/relation.h b/src/include/access/relation.h
new file mode 100644 (file)
index 0000000..d2c019e
--- /dev/null
@@ -0,0 +1,29 @@
+/*-------------------------------------------------------------------------
+ *
+ * relation.h
+ *   Generic relation related routines.
+ *
+ *
+ * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/relation.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef ACCESS_RELATION_H
+#define ACCESS_RELATION_H
+
+#include "nodes/primnodes.h"
+#include "utils/relcache.h"
+#include "storage/lockdefs.h"
+
+
+extern Relation relation_open(Oid relationId, LOCKMODE lockmode);
+extern Relation try_relation_open(Oid relationId, LOCKMODE lockmode);
+extern Relation relation_openrv(const RangeVar *relation, LOCKMODE lockmode);
+extern Relation relation_openrv_extended(const RangeVar *relation,
+                        LOCKMODE lockmode, bool missing_ok);
+extern void relation_close(Relation relation, LOCKMODE lockmode);
+
+#endif                         /* ACCESS_RELATION_H */
diff --git a/src/include/access/table.h b/src/include/access/table.h
new file mode 100644 (file)
index 0000000..453f4dd
--- /dev/null
@@ -0,0 +1,38 @@
+/*-------------------------------------------------------------------------
+ *
+ * table.h
+ *   Generic routines for table related code.
+ *
+ *
+ * Portions Copyright (c) 1996-2019, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ * src/include/access/table.h
+ *
+ *-------------------------------------------------------------------------
+ */
+#ifndef TABLE_H
+#define TABLE_H
+
+#include "nodes/primnodes.h"
+#include "utils/relcache.h"
+#include "storage/lockdefs.h"
+
+
+extern Relation table_open(Oid relationId, LOCKMODE lockmode);
+extern Relation table_openrv(const RangeVar *relation, LOCKMODE lockmode);
+extern Relation table_openrv_extended(const RangeVar *relation,
+                     LOCKMODE lockmode, bool missing_ok);
+extern void table_close(Relation relation, LOCKMODE lockmode);
+
+/*
+ * heap_ used to be the prefix for these routines, and a lot of code will just
+ * continue to work without adaptions after the introduction of pluggable
+ * storage, therefore just map these names.
+ */
+#define heap_open(r, l)                    table_open(r, l)
+#define heap_openrv(r, l)              table_openrv(r, l)
+#define heap_openrv_extended(r, l, m)  table_openrv_extended(r, l, m)
+#define heap_close(r, l)               table_close(r, l)
+
+#endif                         /* TABLE_H */