]> granicus.if.org Git - postgresql/commitdiff
Introduce access/{table.h, relation.h}, for generic functions from heapam.h.
authorAndres Freund <andres@anarazel.de>
Mon, 21 Jan 2019 18:14:09 +0000 (10:14 -0800)
committerAndres Freund <andres@anarazel.de>
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.xbv7s6w7ilcvm7dp@alap3.anarazel.de

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 */