From b4104f6def7d7bc979ab5cb36815c1a1556e1c47 Mon Sep 17 00:00:00 2001
From: Hari Babu <kommi.haribabu@gmail.com>
Date: Thu, 29 Mar 2018 16:17:54 +1100
Subject: [PATCH 02/15] Table AM API init functions

---
 src/backend/access/Makefile              |   2 +-
 src/backend/access/heap/Makefile         |   3 +-
 src/backend/access/heap/heapam_handler.c |  33 ++++++++++
 src/backend/access/table/Makefile        |  17 +++++
 src/backend/access/table/tableamapi.c    | 103 +++++++++++++++++++++++++++++++
 src/include/access/tableamapi.h          |  39 ++++++++++++
 src/include/catalog/pg_am.dat            |   3 +
 src/include/catalog/pg_proc.dat          |   6 ++
 src/include/nodes/nodes.h                |   1 +
 9 files changed, 205 insertions(+), 2 deletions(-)
 create mode 100644 src/backend/access/heap/heapam_handler.c
 create mode 100644 src/backend/access/table/Makefile
 create mode 100644 src/backend/access/table/tableamapi.c
 create mode 100644 src/include/access/tableamapi.h

diff --git a/src/backend/access/Makefile b/src/backend/access/Makefile
index bd93a6a8d1..0880e0a8bb 100644
--- a/src/backend/access/Makefile
+++ b/src/backend/access/Makefile
@@ -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
diff --git a/src/backend/access/heap/Makefile b/src/backend/access/heap/Makefile
index b83d496bcd..87bea410f9 100644
--- a/src/backend/access/heap/Makefile
+++ b/src/backend/access/heap/Makefile
@@ -12,6 +12,7 @@ subdir = src/backend/access/heap
 top_builddir = ../../../..
 include $(top_builddir)/src/Makefile.global
 
-OBJS = heapam.o hio.o pruneheap.o rewriteheap.o syncscan.o tuptoaster.o visibilitymap.o
+OBJS = heapam.o heapam_handler.o hio.o pruneheap.o rewriteheap.o \
+	syncscan.o tuptoaster.o visibilitymap.o
 
 include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/access/heap/heapam_handler.c b/src/backend/access/heap/heapam_handler.c
new file mode 100644
index 0000000000..6d4323152e
--- /dev/null
+++ b/src/backend/access/heap/heapam_handler.c
@@ -0,0 +1,33 @@
+/*-------------------------------------------------------------------------
+ *
+ * heapam_handler.c
+ *	  heap table access method code
+ *
+ * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
+ * Portions Copyright (c) 1994, Regents of the University of California
+ *
+ *
+ * IDENTIFICATION
+ *	  src/backend/access/heap/heapam_handler.c
+ *
+ *
+ * NOTES
+ *	  This file contains the heap_ routines which implement
+ *	  the POSTGRES heap table access method used for all POSTGRES
+ *	  relations.
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/tableamapi.h"
+#include "utils/builtins.h"
+
+
+Datum
+heap_tableam_handler(PG_FUNCTION_ARGS)
+{
+	TableAmRoutine *amroutine = makeNode(TableAmRoutine);
+
+	PG_RETURN_POINTER(amroutine);
+}
diff --git a/src/backend/access/table/Makefile b/src/backend/access/table/Makefile
new file mode 100644
index 0000000000..496b7387c6
--- /dev/null
+++ b/src/backend/access/table/Makefile
@@ -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 = tableamapi.o
+
+include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/access/table/tableamapi.c b/src/backend/access/table/tableamapi.c
new file mode 100644
index 0000000000..f94660e306
--- /dev/null
+++ b/src/backend/access/table/tableamapi.c
@@ -0,0 +1,103 @@
+/*----------------------------------------------------------------------
+ *
+ * tableamapi.c
+ *		Support routines for API for Postgres table access methods
+ *
+ * FIXME: looks like this should be in amapi.c.
+ *
+ * Copyright (c) 2016, PostgreSQL Global Development Group
+ *
+ * src/backend/access/table/tableamapi.c
+ *----------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/htup_details.h"
+#include "access/tableamapi.h"
+#include "catalog/pg_am.h"
+#include "catalog/pg_proc.h"
+#include "utils/syscache.h"
+#include "utils/memutils.h"
+
+
+/*
+ * GetTableAmRoutine
+ *		Call the specified access method handler routine to get its
+ *		TableAmRoutine struct, which will be palloc'd in the caller's
+ *		memory context.
+ */
+TableAmRoutine *
+GetTableAmRoutine(Oid amhandler)
+{
+	Datum		datum;
+	TableAmRoutine *routine;
+
+	datum = OidFunctionCall0(amhandler);
+	routine = (TableAmRoutine *) DatumGetPointer(datum);
+
+	if (routine == NULL || !IsA(routine, TableAmRoutine))
+		elog(ERROR, "Table access method handler %u did not return a TableAmRoutine struct",
+			 amhandler);
+
+	return routine;
+}
+
+/* A crock */
+TableAmRoutine *
+GetHeapamTableAmRoutine(void)
+{
+	Datum		datum;
+	static TableAmRoutine * HeapTableAmRoutine = NULL;
+
+	if (HeapTableAmRoutine == NULL)
+	{
+		MemoryContext oldcxt;
+
+		oldcxt = MemoryContextSwitchTo(TopMemoryContext);
+		datum = OidFunctionCall0(HEAP_TABLE_AM_HANDLER_OID);
+		HeapTableAmRoutine = (TableAmRoutine *) DatumGetPointer(datum);
+		MemoryContextSwitchTo(oldcxt);
+	}
+
+	return HeapTableAmRoutine;
+}
+
+/*
+ * GetTableAmRoutineByAmId - look up the handler of the table access
+ * method with the given OID, and get its TableAmRoutine struct.
+ */
+TableAmRoutine *
+GetTableAmRoutineByAmId(Oid amoid)
+{
+	regproc		amhandler;
+	HeapTuple	tuple;
+	Form_pg_am	amform;
+
+	/* Get handler function OID for the access method */
+	tuple = SearchSysCache1(AMOID, ObjectIdGetDatum(amoid));
+	if (!HeapTupleIsValid(tuple))
+		elog(ERROR, "cache lookup failed for access method %u",
+			 amoid);
+	amform = (Form_pg_am) GETSTRUCT(tuple);
+
+	/* Check that it is a table access method */
+	if (amform->amtype != AMTYPE_TABLE)
+		ereport(ERROR,
+				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+				 errmsg("access method \"%s\" is not of type %s",
+						NameStr(amform->amname), "TABLE")));
+
+	amhandler = amform->amhandler;
+
+	/* Complain if handler OID is invalid */
+	if (!RegProcedureIsValid(amhandler))
+		ereport(ERROR,
+				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+				 errmsg("table access method \"%s\" does not have a handler",
+						NameStr(amform->amname))));
+
+	ReleaseSysCache(tuple);
+
+	/* And finally, call the handler function to get the API struct. */
+	return GetTableAmRoutine(amhandler);
+}
diff --git a/src/include/access/tableamapi.h b/src/include/access/tableamapi.h
new file mode 100644
index 0000000000..55ddad68fb
--- /dev/null
+++ b/src/include/access/tableamapi.h
@@ -0,0 +1,39 @@
+/*---------------------------------------------------------------------
+ *
+ * tableamapi.h
+ *		API for Postgres table access methods
+ *
+ * Copyright (c) 2017, PostgreSQL Global Development Group
+ *
+ * src/include/access/tableamapi.h
+ *---------------------------------------------------------------------
+ */
+#ifndef TABLEEAMAPI_H
+#define TABLEEAMAPI_H
+
+#include "nodes/nodes.h"
+#include "fmgr.h"
+
+/* A physical tuple coming from a table AM scan */
+typedef void *TableTuple;
+
+/*
+ * API struct for a table AM.  Note this must be stored in a single palloc'd
+ * chunk of memory.
+ *
+ * XXX currently all functions are together in a single struct.  Would it be
+ * worthwhile to split the slot-accessor functions to a different struct?
+ * That way, MinimalTuple could be handled without a complete TableAmRoutine
+ * for them -- it'd only have a few functions in TupleTableSlotAmRoutine or so.
+ */
+typedef struct TableAmRoutine
+{
+	NodeTag		type;
+
+}			TableAmRoutine;
+
+extern TableAmRoutine * GetTableAmRoutine(Oid amhandler);
+extern TableAmRoutine * GetTableAmRoutineByAmId(Oid amoid);
+extern TableAmRoutine * GetHeapamTableAmRoutine(void);
+
+#endif							/* TABLEEAMAPI_H */
diff --git a/src/include/catalog/pg_am.dat b/src/include/catalog/pg_am.dat
index 8722cacaae..1c3166d83e 100644
--- a/src/include/catalog/pg_am.dat
+++ b/src/include/catalog/pg_am.dat
@@ -30,5 +30,8 @@
 { oid => '3580', oid_symbol => 'BRIN_AM_OID',
   descr => 'block range index (BRIN) access method',
   amname => 'brin', amhandler => 'brinhandler', amtype => 'i' },
+{ oid => '4001', oid_symbol => 'HEAP_TABLE_AM_OID',
+  descr => 'heap table access method',
+  amname => 'heap_tableam', amhandler => 'heap_tableam_handler', amtype => 't' },
 
 ]
diff --git a/src/include/catalog/pg_proc.dat b/src/include/catalog/pg_proc.dat
index 5543a22ea4..7681211c4a 100644
--- a/src/include/catalog/pg_proc.dat
+++ b/src/include/catalog/pg_proc.dat
@@ -918,6 +918,12 @@
   proname => 'int4', prorettype => 'int4', proargtypes => 'float4',
   prosrc => 'ftoi4' },
 
+# Table access method handlers
+{ oid => '4002', oid_symbol => 'HEAP_TABLE_AM_HANDLER_OID', 
+  descr => 'row-oriented heap table access method handler',
+  proname => 'heap_tableam_handler', provolatile => 'v', prorettype => 'table_am_handler',
+  proargtypes => 'internal', prosrc => 'heap_tableam_handler' },
+
 # Index access method handlers
 { oid => '330', descr => 'btree index access method handler',
   proname => 'bthandler', provolatile => 'v', prorettype => 'index_am_handler',
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index adb159a6da..6b368d4d14 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -503,6 +503,7 @@ typedef enum NodeTag
 	T_InlineCodeBlock,			/* in nodes/parsenodes.h */
 	T_FdwRoutine,				/* in foreign/fdwapi.h */
 	T_IndexAmRoutine,			/* in access/amapi.h */
+	T_TableAmRoutine,			/* in access/tableamapi.h */
 	T_TsmRoutine,				/* in access/tsmapi.h */
 	T_ForeignKeyCacheInfo,		/* in utils/rel.h */
 	T_CallContext				/* in nodes/parsenodes.h */
-- 
2.16.1.windows.4

