From faa7a8c667484ee8841b131e6b6b59a24be21d23 Mon Sep 17 00:00:00 2001
From: Hari Babu <haribabuk@fast.au.fujitsu.com>
Date: Wed, 30 Aug 2017 12:41:15 +1000
Subject: [PATCH 2/8] Storage AM folder and init functions

---
 src/backend/access/Makefile               |   2 +-
 src/backend/access/heap/Makefile          |   3 +-
 src/backend/access/heap/heapam_storage.c  |  33 ++++++++++
 src/backend/access/storage/Makefile       |  17 +++++
 src/backend/access/storage/storageam.c    |  15 +++++
 src/backend/access/storage/storageamapi.c | 103 ++++++++++++++++++++++++++++++
 src/include/access/storageamapi.h         |  39 +++++++++++
 src/include/catalog/pg_am.h               |   3 +
 src/include/catalog/pg_proc.h             |   5 ++
 src/include/nodes/nodes.h                 |   1 +
 10 files changed, 219 insertions(+), 2 deletions(-)
 create mode 100644 src/backend/access/heap/heapam_storage.c
 create mode 100644 src/backend/access/storage/Makefile
 create mode 100644 src/backend/access/storage/storageam.c
 create mode 100644 src/backend/access/storage/storageamapi.c
 create mode 100644 src/include/access/storageamapi.h

diff --git a/src/backend/access/Makefile b/src/backend/access/Makefile
index bd93a6a8d1..e72ad6c86c 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
+			  storage 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..816f03a86f 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 hio.o heapam_storage.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_storage.c b/src/backend/access/heap/heapam_storage.c
new file mode 100644
index 0000000000..792e9cb436
--- /dev/null
+++ b/src/backend/access/heap/heapam_storage.c
@@ -0,0 +1,33 @@
+/*-------------------------------------------------------------------------
+ *
+ * heapam_storage.c
+ *	  heap storage 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_storage.c
+ *
+ *
+ * NOTES
+ *	  This file contains the heap_ routines which implement
+ *	  the POSTGRES heap access method used for all POSTGRES
+ *	  relations.
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/storageamapi.h"
+#include "utils/builtins.h"
+
+
+Datum
+heapam_storage_handler(PG_FUNCTION_ARGS)
+{
+	StorageAmRoutine *amroutine = makeNode(StorageAmRoutine);
+
+	PG_RETURN_POINTER(amroutine);
+}
diff --git a/src/backend/access/storage/Makefile b/src/backend/access/storage/Makefile
new file mode 100644
index 0000000000..2a05c7ce66
--- /dev/null
+++ b/src/backend/access/storage/Makefile
@@ -0,0 +1,17 @@
+#-------------------------------------------------------------------------
+#
+# Makefile--
+#    Makefile for access/storage
+#
+# IDENTIFICATION
+#    src/backend/access/storage/Makefile
+#
+#-------------------------------------------------------------------------
+
+subdir = src/backend/access/storage
+top_builddir = ../../../..
+include $(top_builddir)/src/Makefile.global
+
+OBJS = storageam.o storageamapi.o
+
+include $(top_srcdir)/src/backend/common.mk
diff --git a/src/backend/access/storage/storageam.c b/src/backend/access/storage/storageam.c
new file mode 100644
index 0000000000..8541c75782
--- /dev/null
+++ b/src/backend/access/storage/storageam.c
@@ -0,0 +1,15 @@
+/*-------------------------------------------------------------------------
+ *
+ * storageam.c
+ *	  storage 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/storage/storageam.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
diff --git a/src/backend/access/storage/storageamapi.c b/src/backend/access/storage/storageamapi.c
new file mode 100644
index 0000000000..bcbe14588b
--- /dev/null
+++ b/src/backend/access/storage/storageamapi.c
@@ -0,0 +1,103 @@
+/*----------------------------------------------------------------------
+ *
+ * storageamapi.c
+ *		Support routines for API for Postgres storage access methods
+ *
+ * FIXME: looks like this should be in amapi.c.
+ *
+ * Copyright (c) 2016, PostgreSQL Global Development Group
+ *
+ * src/backend/access/heap/storageamapi.c
+ *----------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/htup_details.h"
+#include "access/storageamapi.h"
+#include "catalog/pg_am.h"
+#include "catalog/pg_proc.h"
+#include "utils/syscache.h"
+#include "utils/memutils.h"
+
+
+/*
+ * GetStorageAmRoutine
+ *		Call the specified access method handler routine to get its
+ *		StorageAmRoutine struct, which will be palloc'd in the caller's
+ *		memory context.
+ */
+StorageAmRoutine *
+GetStorageAmRoutine(Oid amhandler)
+{
+	Datum		datum;
+	StorageAmRoutine *routine;
+
+	datum = OidFunctionCall0(amhandler);
+	routine = (StorageAmRoutine *) DatumGetPointer(datum);
+
+	if (routine == NULL || !IsA(routine, StorageAmRoutine))
+		elog(ERROR, "storage access method handler %u did not return a StorageAmRoutine struct",
+			 amhandler);
+
+	return routine;
+}
+
+/* A crock */
+StorageAmRoutine *
+GetHeapamStorageAmRoutine(void)
+{
+	Datum		datum;
+	static StorageAmRoutine * HeapamStorageAmRoutine = NULL;
+
+	if (HeapamStorageAmRoutine == NULL)
+	{
+		MemoryContext oldcxt;
+
+		oldcxt = MemoryContextSwitchTo(TopMemoryContext);
+		datum = OidFunctionCall0(HEAPAM_STORAGE_AM_HANDLER_OID);
+		HeapamStorageAmRoutine = (StorageAmRoutine *) DatumGetPointer(datum);
+		MemoryContextSwitchTo(oldcxt);
+	}
+
+	return HeapamStorageAmRoutine;
+}
+
+/*
+ * GetStorageAmRoutineByAmId - look up the handler of the storage access
+ * method with the given OID, and get its StorageAmRoutine struct.
+ */
+StorageAmRoutine *
+GetStorageAmRoutineByAmId(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 storage access method */
+	if (amform->amtype != AMTYPE_STORAGE)
+		ereport(ERROR,
+				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+				 errmsg("access method \"%s\" is not of type %s",
+						NameStr(amform->amname), "STORAGE")));
+
+	amhandler = amform->amhandler;
+
+	/* Complain if handler OID is invalid */
+	if (!RegProcedureIsValid(amhandler))
+		ereport(ERROR,
+				(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
+				 errmsg("storage 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 GetStorageAmRoutine(amhandler);
+}
diff --git a/src/include/access/storageamapi.h b/src/include/access/storageamapi.h
new file mode 100644
index 0000000000..6fae4eea5c
--- /dev/null
+++ b/src/include/access/storageamapi.h
@@ -0,0 +1,39 @@
+/*---------------------------------------------------------------------
+ *
+ * storageamapi.h
+ *		API for Postgres storage access methods
+ *
+ * Copyright (c) 2017, PostgreSQL Global Development Group
+ *
+ * src/include/access/storageamapi.h
+ *---------------------------------------------------------------------
+ */
+#ifndef STORAGEAMAPI_H
+#define STORAGEAMAPI_H
+
+#include "nodes/nodes.h"
+#include "fmgr.h"
+
+/* A physical tuple coming from a storage AM scan */
+typedef void *StorageTuple;
+
+/*
+ * API struct for a storage 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 StorageAmRoutine
+ * for them -- it'd only have a few functions in TupleTableSlotAmRoutine or so.
+ */
+typedef struct StorageAmRoutine
+{
+	NodeTag		type;
+
+}			StorageAmRoutine;
+
+extern StorageAmRoutine * GetStorageAmRoutine(Oid amhandler);
+extern StorageAmRoutine * GetStorageAmRoutineByAmId(Oid amoid);
+extern StorageAmRoutine * GetHeapamStorageAmRoutine(void);
+
+#endif							/* STORAGEAMAPI_H */
diff --git a/src/include/catalog/pg_am.h b/src/include/catalog/pg_am.h
index dd9c263ade..2c3e33c104 100644
--- a/src/include/catalog/pg_am.h
+++ b/src/include/catalog/pg_am.h
@@ -84,5 +84,8 @@ DESCR("SP-GiST index access method");
 DATA(insert OID = 3580 (  brin		brinhandler i ));
 DESCR("block range index (BRIN) access method");
 #define BRIN_AM_OID 3580
+DATA(insert OID = 4001 (  heapam         heapam_storage_handler s ));
+DESCR("heapam storage access method");
+#define HEAPAM_STORAGE_AM_OID 4001
 
 #endif							/* PG_AM_H */
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index 1449a9cfd8..b26b5900de 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -558,6 +558,11 @@ DESCR("convert int4 to float4");
 DATA(insert OID = 319 (  int4			   PGNSP PGUID 12 1 0 0 0 f f f f t f i s 1  0 23 "700" _null_ _null_ _null_ _null_ _null_	ftoi4 _null_ _null_ _null_ ));
 DESCR("convert float4 to int4");
 
+/* Storage access method handlers */
+DATA(insert OID = 4002 (  heapam_storage_handler		PGNSP PGUID 12 1 0 0 0 f f f f t f v s 1 0 3998 "2281" _null_ _null_ _null_ _null_ _null_	heapam_storage_handler _null_ _null_ _null_ ));
+DESCR("row-oriented storage access method handler");
+#define HEAPAM_STORAGE_AM_HANDLER_OID	4002
+
 /* Index access method handlers */
 DATA(insert OID = 330 (  bthandler		PGNSP PGUID 12 1 0 0 0 f f f f t f v s 1 0 325 "2281" _null_ _null_ _null_ _null_ _null_	bthandler _null_ _null_ _null_ ));
 DESCR("btree index access method handler");
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index c5b5115f5b..927126f729 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -499,6 +499,7 @@ typedef enum NodeTag
 	T_InlineCodeBlock,			/* in nodes/parsenodes.h */
 	T_FdwRoutine,				/* in foreign/fdwapi.h */
 	T_IndexAmRoutine,			/* in access/amapi.h */
+	T_StorageAmRoutine,			/* in access/storageamapi.h */
 	T_TsmRoutine,				/* in access/tsmapi.h */
 	T_ForeignKeyCacheInfo		/* in utils/rel.h */
 } NodeTag;
-- 
2.15.0.windows.1

