From b53ff348bfbd0f6baa26dcb15847a59867f6988b Mon Sep 17 00:00:00 2001
From: Alvaro Herrera <alvherre@alvh.no-ip.org>
Date: Fri, 28 Aug 2015 22:21:31 -0300
Subject: [PATCH 15/24] New command: CREATE COLUMN STORE ACCESS METHOD

This allows access methods to be created using ad-hoc DDL.

Whether to use this exact wording is not clear.  Perhaps we want CREATE
ACCESS METHOD (i.e. make it more generic), so that this can be used by
sequence access methods too?  There would be a clause to indicate what
type of access method we're creating.

A further question is whether we actually need this to be DDL at all.
We've discussed that it's not trivial to add further access methods of
any kind given the lack of support for extensions to write and replay
WAL.  That makes the accessibility to create access methods pretty much
useless, until we fix that problem.

Implementation notes:

- This makes METHOD an unreserved keyword.

- Creates a new pseudo type cstore_handler

- Creates a new parse node CreateColumnStoreAMStmt.

- There's no ALTER/DROP support yet.

- ProcessUtilitySlow is not properly capturing data for event triggers.
---
 src/backend/commands/Makefile        |   2 +-
 src/backend/commands/colstorecmds.c  | 177 +++++++++++++++++++++++++++++++++++
 src/backend/commands/event_trigger.c |   1 +
 src/backend/nodes/copyfuncs.c        |  14 +++
 src/backend/nodes/equalfuncs.c       |  12 +++
 src/backend/parser/gram.y            |  41 +++++++-
 src/backend/tcop/utility.c           |   9 ++
 src/backend/utils/adt/pseudotypes.c  |  27 ++++++
 src/include/catalog/pg_proc.h        |   4 +
 src/include/catalog/pg_type.h        |   2 +
 src/include/commands/defrem.h        |   1 +
 src/include/nodes/nodes.h            |   1 +
 src/include/nodes/parsenodes.h       |  13 +++
 src/include/parser/kwlist.h          |   1 +
 src/include/utils/builtins.h         |   2 +
 15 files changed, 304 insertions(+), 3 deletions(-)
 create mode 100644 src/backend/commands/colstorecmds.c

diff --git a/src/backend/commands/Makefile b/src/backend/commands/Makefile
index b1ac704..d2bb636 100644
--- a/src/backend/commands/Makefile
+++ b/src/backend/commands/Makefile
@@ -14,7 +14,7 @@ include $(top_builddir)/src/Makefile.global
 
 OBJS = aggregatecmds.o alter.o analyze.o async.o cluster.o comment.o  \
 	collationcmds.o constraint.o conversioncmds.o copy.o createas.o \
-	dbcommands.o define.o discard.o dropcmds.o \
+	colstorecmds.o dbcommands.o define.o discard.o dropcmds.o \
 	event_trigger.o explain.o extension.o foreigncmds.o functioncmds.o \
 	indexcmds.o lockcmds.o matview.o operatorcmds.o opclasscmds.o \
 	policy.o portalcmds.o prepare.o proclang.o \
diff --git a/src/backend/commands/colstorecmds.c b/src/backend/commands/colstorecmds.c
new file mode 100644
index 0000000..eabcced
--- /dev/null
+++ b/src/backend/commands/colstorecmds.c
@@ -0,0 +1,177 @@
+/*-------------------------------------------------------------------------
+ *
+ * colstorecmds.c
+ *	  column store creation/manipulation commands
+ *
+ * Portions Copyright (c) 1996-2015, PostgreSQL Global Development Group
+ *
+ *
+ * IDENTIFICATION
+ *	  src/backend/commands/colstorecmds.c
+ *
+ *-------------------------------------------------------------------------
+ */
+#include "postgres.h"
+
+#include "access/heapam.h"
+#include "access/htup_details.h"
+#include "access/reloptions.h"
+#include "access/xact.h"
+#include "catalog/colstore.h"
+#include "catalog/dependency.h"
+#include "catalog/indexing.h"
+#include "catalog/objectaccess.h"
+#include "catalog/pg_cstore_am.h"
+#include "catalog/pg_proc.h"
+#include "catalog/pg_type.h"
+#include "commands/defrem.h"
+#include "colstore/colstoreapi.h"
+#include "miscadmin.h"
+#include "parser/parse_func.h"
+#include "tcop/utility.h"
+#include "utils/acl.h"
+#include "utils/builtins.h"
+#include "utils/lsyscache.h"
+#include "utils/rel.h"
+#include "utils/syscache.h"
+
+
+/*
+ * Convert a handler function name passed from the parser to an Oid.
+ */
+static Oid
+lookup_cstore_handler_func(DefElem *handler)
+{
+	Oid			handlerOid;
+	Oid			funcargtypes[1];
+
+	if (handler == NULL || handler->arg == NULL)
+		return InvalidOid;
+
+	/* handlers have no arguments */
+	handlerOid = LookupFuncName((List *) handler->arg, 0, funcargtypes, false);
+
+	/* check that handler has correct return type */
+	if (get_func_rettype(handlerOid) != CSTORE_HANDLEROID)
+		ereport(ERROR,
+				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+				 errmsg("function %s must return type \"cstore_handler\"",
+						NameListToString((List *) handler->arg))));
+
+	return handlerOid;
+}
+
+/*
+ * Process function options of CREATE COLUMN STORE ACCESS METHOD
+ */
+static void
+parse_func_options(List *func_options,
+				   bool *handler_given, Oid *csthandler)
+{
+	ListCell   *cell;
+
+	*handler_given = false;
+	*csthandler = InvalidOid;
+
+	foreach(cell, func_options)
+	{
+		DefElem    *def = (DefElem *) lfirst(cell);
+
+		if (strcmp(def->defname, "handler") == 0)
+		{
+			if (*handler_given)
+				ereport(ERROR,
+						(errcode(ERRCODE_SYNTAX_ERROR),
+						 errmsg("conflicting or redundant options")));
+			*handler_given = true;
+			*csthandler = lookup_cstore_handler_func(def);
+		}
+		else
+			elog(ERROR, "option \"%s\" not recognized",
+				 def->defname);
+	}
+}
+
+/*
+ * Create a column store access method
+ */
+ObjectAddress
+CreateColumnStoreAM(CreateColumnStoreAMStmt *stmt)
+{
+	Relation	rel;
+	Datum		values[Natts_pg_cstore_am];
+	bool		nulls[Natts_pg_cstore_am];
+	HeapTuple	tuple;
+	Oid			cstamId;
+	bool		handler_given;
+	Oid			csthandler;
+	ObjectAddress myself;
+	ObjectAddress referenced;
+
+	rel = heap_open(CStoreAmRelationId, RowExclusiveLock);
+
+	/* Must be super user */
+	if (!superuser())
+		ereport(ERROR,
+				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+				 errmsg("permission denied to create column store access method \"%s\"",
+						stmt->cstamname),
+				 errhint("Must be superuser to create a column store access method.")));
+
+	/*
+	 * Check that there is no other column store AM by this name.
+	 */
+	if (GetColumnStoreAMByName(stmt->cstamname, true) != InvalidOid)
+		ereport(ERROR,
+				(errcode(ERRCODE_DUPLICATE_OBJECT),
+				 errmsg("column store access method \"%s\" already exists",
+						stmt->cstamname)));
+
+	/*
+	 * Insert tuple into pg_cstore_am.
+	 */
+	memset(values, 0, sizeof(values));
+	memset(nulls, false, sizeof(nulls));
+
+	values[Anum_pg_cstore_am_cstamname - 1] =
+		DirectFunctionCall1(namein, CStringGetDatum(stmt->cstamname));
+
+	/* Lookup handler and validator functions, if given */
+	parse_func_options(stmt->func_options, &handler_given, &csthandler);
+
+	/* XXX ereport */
+	if (!handler_given)
+		elog(ERROR, "column store access method requires HANDLER option");
+
+	values[Anum_pg_cstore_am_cstamhandler - 1] = ObjectIdGetDatum(csthandler);
+
+	tuple = heap_form_tuple(rel->rd_att, values, nulls);
+
+	cstamId = simple_heap_insert(rel, tuple);
+	CatalogUpdateIndexes(rel, tuple);
+
+	heap_freetuple(tuple);
+
+	/* record dependencies */
+	myself.classId = CStoreAmRelationId;
+	myself.objectId = cstamId;
+	myself.objectSubId = 0;
+
+	if (OidIsValid(csthandler))
+	{
+		referenced.classId = ProcedureRelationId;
+		referenced.objectId = csthandler;
+		referenced.objectSubId = 0;
+		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+	}
+
+	/* dependency on extension */
+	recordDependencyOnCurrentExtension(&myself, false);
+
+	/* Post creation hook for new column store access method */
+	InvokeObjectPostCreateHook(CStoreAmRelationId, cstamId, 0);
+
+	heap_close(rel, RowExclusiveLock);
+
+	return myself;
+}
diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c
index d323932..0488ea9 100644
--- a/src/backend/commands/event_trigger.c
+++ b/src/backend/commands/event_trigger.c
@@ -90,6 +90,7 @@ static event_trigger_support_data event_trigger_support[] = {
 	{"CAST", true},
 	{"CONSTRAINT", true},
 	{"COLLATION", true},
+	{"COLUMN STORE ACCESS METHOD", true},
 	{"CONVERSION", true},
 	{"DATABASE", false},
 	{"DOMAIN", true},
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
index ae7ca30..3aaf221 100644
--- a/src/backend/nodes/copyfuncs.c
+++ b/src/backend/nodes/copyfuncs.c
@@ -3811,6 +3811,17 @@ _copyImportForeignSchemaStmt(const ImportForeignSchemaStmt *from)
 	return newnode;
 }
 
+static CreateColumnStoreAMStmt *
+_copyCreateColumnStoreAMStmt(const CreateColumnStoreAMStmt *from)
+{
+	CreateColumnStoreAMStmt *newnode = makeNode(CreateColumnStoreAMStmt);
+
+	COPY_STRING_FIELD(cstamname);
+	COPY_NODE_FIELD(func_options);
+
+	return newnode;
+}
+
 static CreateTransformStmt *
 _copyCreateTransformStmt(const CreateTransformStmt *from)
 {
@@ -4785,6 +4796,9 @@ copyObject(const void *from)
 		case T_ImportForeignSchemaStmt:
 			retval = _copyImportForeignSchemaStmt(from);
 			break;
+		case T_CreateColumnStoreAMStmt:
+			retval = _copyCreateColumnStoreAMStmt(from);
+			break;
 		case T_CreateTransformStmt:
 			retval = _copyCreateTransformStmt(from);
 			break;
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
index 18c2119..6db8fef 100644
--- a/src/backend/nodes/equalfuncs.c
+++ b/src/backend/nodes/equalfuncs.c
@@ -1832,6 +1832,15 @@ _equalImportForeignSchemaStmt(const ImportForeignSchemaStmt *a, const ImportFore
 }
 
 static bool
+_equalCreateColumnStoreAMStmt(const CreateColumnStoreAMStmt *a, const CreateColumnStoreAMStmt *b)
+{
+	COMPARE_STRING_FIELD(cstamname);
+	COMPARE_NODE_FIELD(func_options);
+
+	return true;
+}
+
+static bool
 _equalCreateTransformStmt(const CreateTransformStmt *a, const CreateTransformStmt *b)
 {
 	COMPARE_SCALAR_FIELD(replace);
@@ -3140,6 +3149,9 @@ equal(const void *a, const void *b)
 		case T_ImportForeignSchemaStmt:
 			retval = _equalImportForeignSchemaStmt(a, b);
 			break;
+		case T_CreateColumnStoreAMStmt:
+			retval = _equalCreateColumnStoreAMStmt(a, b);
+			break;
 		case T_CreateTransformStmt:
 			retval = _equalCreateTransformStmt(a, b);
 			break;
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 1ec1426..cd308fb 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -264,7 +264,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
 		DeallocateStmt PrepareStmt ExecuteStmt
 		DropOwnedStmt ReassignOwnedStmt
 		AlterTSConfigurationStmt AlterTSDictionaryStmt
-		CreateMatViewStmt RefreshMatViewStmt
+		CreateMatViewStmt RefreshMatViewStmt CreateColumnStoreAMStmt
 
 %type <node>	select_no_parens select_with_parens select_clause
 				simple_select values_clause
@@ -379,6 +379,9 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
 %type <list>	opt_fdw_options fdw_options
 %type <defelt>	fdw_option
 
+%type <list>	opt_cstam_options cstam_options
+%type <defelt>	cstam_option
+
 %type <range>	OptTempTableName
 %type <into>	into_clause create_as_target create_mv_target
 
@@ -605,7 +608,7 @@ static Node *makeRecursiveViewSelect(char *relname, List *aliases, Node *query);
 	LEADING LEAKPROOF LEAST LEFT LEVEL LIKE LIMIT LISTEN LOAD LOCAL
 	LOCALTIME LOCALTIMESTAMP LOCATION LOCK_P LOCKED LOGGED
 
-	MAPPING MATCH MATERIALIZED MAXVALUE MINUTE_P MINVALUE MODE MONTH_P MOVE
+	MAPPING MATCH MATERIALIZED MAXVALUE METHOD MINUTE_P MINVALUE MODE MONTH_P MOVE
 
 	NAME_P NAMES NATIONAL NATURAL NCHAR NEXT NO NONE
 	NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P NULLIF
@@ -793,6 +796,7 @@ stmt :
 			| CreateAsStmt
 			| CreateAssertStmt
 			| CreateCastStmt
+			| CreateColumnStoreAMStmt
 			| CreateConversionStmt
 			| CreateDomainStmt
 			| CreateExtensionStmt
@@ -4212,6 +4216,38 @@ opt_fdw_options:
 			| /*EMPTY*/							{ $$ = NIL; }
 		;
 
+
+/*****************************************************************************
+ *
+ *		QUERY:
+ *             CREATE COLUMN STORE ACCESS METHOD name options
+ *
+ *****************************************************************************/
+
+CreateColumnStoreAMStmt: CREATE COLUMN STORE ACCESS METHOD name opt_cstam_options
+				{
+					CreateColumnStoreAMStmt *n = makeNode(CreateColumnStoreAMStmt);
+					n->cstamname = $6;
+					n->func_options = $7;
+					$$ = (Node *) n;
+				}
+		;
+
+cstam_option:
+			HANDLER handler_name				{ $$ = makeDefElem("handler", (Node *)$2); }
+			| NO HANDLER						{ $$ = makeDefElem("handler", NULL); }
+		;
+
+cstam_options:
+			cstam_option						{ $$ = list_make1($1); }
+			| cstam_options cstam_option		{ $$ = lappend($1, $2); }
+		;
+
+opt_cstam_options:
+			cstam_options						{ $$ = $1; }
+			| /*EMPTY*/							{ $$ = NIL; }
+		;
+
 /*****************************************************************************
  *
  *		QUERY :
@@ -13787,6 +13823,7 @@ unreserved_keyword:
 			| MATCH
 			| MATERIALIZED
 			| MAXVALUE
+			| METHOD
 			| MINUTE_P
 			| MINVALUE
 			| MODE
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
index e81bbc6..711c64f 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -209,6 +209,7 @@ check_xact_readonly(Node *parsetree)
 		case T_CreateForeignTableStmt:
 		case T_ImportForeignSchemaStmt:
 		case T_SecLabelStmt:
+		case T_CreateColumnStoreAMStmt:
 			PreventCommandIfReadOnly(CreateCommandTag(parsetree));
 			PreventCommandIfParallelMode(CreateCommandTag(parsetree));
 			break;
@@ -1520,6 +1521,10 @@ ProcessUtilitySlow(Node *parsetree,
 				address = ExecSecLabelStmt((SecLabelStmt *) parsetree);
 				break;
 
+			case T_CreateColumnStoreAMStmt:
+				CreateColumnStoreAM((CreateColumnStoreAMStmt *) parsetree);
+				break;
+
 			default:
 				elog(ERROR, "unrecognized node type: %d",
 					 (int) nodeTag(parsetree));
@@ -2665,6 +2670,10 @@ CreateCommandTag(Node *parsetree)
 			}
 			break;
 
+		case T_CreateColumnStoreAMStmt:
+			tag = "CREATE COLUMN STORE ACCESS METHOD";
+			break;
+
 		default:
 			elog(WARNING, "unrecognized node type: %d",
 				 (int) nodeTag(parsetree));
diff --git a/src/backend/utils/adt/pseudotypes.c b/src/backend/utils/adt/pseudotypes.c
index 5b809aa..7680777 100644
--- a/src/backend/utils/adt/pseudotypes.c
+++ b/src/backend/utils/adt/pseudotypes.c
@@ -401,6 +401,33 @@ tsm_handler_out(PG_FUNCTION_ARGS)
 
 
 /*
+ * cstore_handler_in		- input routine for pseudo-type CSTORE_HANDLER.
+ */
+Datum
+cstore_handler_in(PG_FUNCTION_ARGS)
+{
+	ereport(ERROR,
+			(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+			 errmsg("cannot accept a value of type cstore_handler")));
+
+	PG_RETURN_VOID();			/* keep compiler quiet */
+}
+
+/*
+ * cstore_handler_out		- output routine for pseudo-type CSTORE_HANDLER.
+ */
+Datum
+cstore_handler_out(PG_FUNCTION_ARGS)
+{
+	ereport(ERROR,
+			(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+			 errmsg("cannot display a value of type cstore_handler")));
+
+	PG_RETURN_VOID();			/* keep compiler quiet */
+}
+
+
+/*
  * internal_in		- input routine for pseudo-type INTERNAL.
  */
 Datum
diff --git a/src/include/catalog/pg_proc.h b/src/include/catalog/pg_proc.h
index f0481bd..c5befcb 100644
--- a/src/include/catalog/pg_proc.h
+++ b/src/include/catalog/pg_proc.h
@@ -3740,6 +3740,10 @@ DATA(insert OID = 3311 (  tsm_handler_in	PGNSP PGUID 12 1 0 0 0 f f f f f f i 1
 DESCR("I/O");
 DATA(insert OID = 3312 (  tsm_handler_out	PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2275 "3310" _null_ _null_ _null_ _null_ _null_ tsm_handler_out _null_ _null_ _null_ ));
 DESCR("I/O");
+DATA(insert OID = 3352 (  cstore_handler_in	PGNSP PGUID 12 1 0 0 0 f f f f f f i 1 0 3351 "2275" _null_ _null_ _null_ _null_ _null_ cstore_handler_in _null_ _null_ _null_ ));
+DESCR("I/O");
+DATA(insert OID = 3353 (  cstore_handler_out	PGNSP PGUID 12 1 0 0 0 f f f f t f i 1 0 2275 "3351" _null_ _null_ _null_ _null_ _null_ cstore_handler_out _null_ _null_ _null_ ));
+DESCR("I/O");
 
 /* tablesample method handlers */
 DATA(insert OID = 3313 (  bernoulli			PGNSP PGUID 12 1 0 0 0 f f f f t f v 1 0 3310 "2281" _null_ _null_ _null_ _null_ _null_ tsm_bernoulli_handler _null_ _null_ _null_ ));
diff --git a/src/include/catalog/pg_type.h b/src/include/catalog/pg_type.h
index 7dc95c8..716d487 100644
--- a/src/include/catalog/pg_type.h
+++ b/src/include/catalog/pg_type.h
@@ -696,6 +696,8 @@ DATA(insert OID = 3115 ( fdw_handler	PGNSP PGUID  4 t p P f t \054 0 0 0 fdw_han
 #define FDW_HANDLEROID	3115
 DATA(insert OID = 3310 ( tsm_handler	PGNSP PGUID  4 t p P f t \054 0 0 0 tsm_handler_in tsm_handler_out - - - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
 #define TSM_HANDLEROID	3310
+DATA(insert OID = 3351 ( cstore_handler	PGNSP PGUID  4 t p P f t \054 0 0 0 cstore_handler_in cstore_handler_out - - - - - i p f 0 -1 0 0 _null_ _null_ _null_ ));
+#define CSTORE_HANDLEROID	3351
 DATA(insert OID = 3831 ( anyrange		PGNSP PGUID  -1 f p P f t \054 0 0 0 anyrange_in anyrange_out - - - - - d x f 0 -1 0 0 _null_ _null_ _null_ ));
 #define ANYRANGEOID		3831
 
diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h
index adae296..cd4bed3 100644
--- a/src/include/commands/defrem.h
+++ b/src/include/commands/defrem.h
@@ -132,6 +132,7 @@ extern Oid	RemoveUserMapping(DropUserMappingStmt *stmt);
 extern void RemoveUserMappingById(Oid umId);
 extern void CreateForeignTable(CreateForeignTableStmt *stmt, Oid relid);
 extern void ImportForeignSchema(ImportForeignSchemaStmt *stmt);
+extern ObjectAddress CreateColumnStoreAM(CreateColumnStoreAMStmt *stmt);
 extern Datum transformGenericOptions(Oid catalogId,
 						Datum oldOptions,
 						List *options,
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
index 6950e87..97efd24 100644
--- a/src/include/nodes/nodes.h
+++ b/src/include/nodes/nodes.h
@@ -381,6 +381,7 @@ typedef enum NodeTag
 	T_CreatePolicyStmt,
 	T_AlterPolicyStmt,
 	T_CreateTransformStmt,
+	T_CreateColumnStoreAMStmt,
 
 	/*
 	 * TAGS FOR PARSE TREE NODES (parsenodes.h)
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 7c790bf..cbf7c90 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -2057,6 +2057,19 @@ typedef struct ImportForeignSchemaStmt
 	List	   *options;		/* list of options to pass to FDW */
 } ImportForeignSchemaStmt;
 
+
+/* ----------------------
+ *		Create COLUMN STORE ACCESS METHOD Statements
+ * ----------------------
+ */
+
+typedef struct CreateColumnStoreAMStmt
+{
+	NodeTag		type;
+	char	   *cstamname;		/* column store AM name */
+	List	   *func_options;	/* HANDLER option */
+} CreateColumnStoreAMStmt;
+
 /*----------------------
  *		Create POLICY Statement
  *----------------------
diff --git a/src/include/parser/kwlist.h b/src/include/parser/kwlist.h
index 3d499c1..59e2996 100644
--- a/src/include/parser/kwlist.h
+++ b/src/include/parser/kwlist.h
@@ -239,6 +239,7 @@ PG_KEYWORD("mapping", MAPPING, UNRESERVED_KEYWORD)
 PG_KEYWORD("match", MATCH, UNRESERVED_KEYWORD)
 PG_KEYWORD("materialized", MATERIALIZED, UNRESERVED_KEYWORD)
 PG_KEYWORD("maxvalue", MAXVALUE, UNRESERVED_KEYWORD)
+PG_KEYWORD("method", METHOD, UNRESERVED_KEYWORD)
 PG_KEYWORD("minute", MINUTE_P, UNRESERVED_KEYWORD)
 PG_KEYWORD("minvalue", MINVALUE, UNRESERVED_KEYWORD)
 PG_KEYWORD("mode", MODE, UNRESERVED_KEYWORD)
diff --git a/src/include/utils/builtins.h b/src/include/utils/builtins.h
index aa79730..75709d0 100644
--- a/src/include/utils/builtins.h
+++ b/src/include/utils/builtins.h
@@ -569,6 +569,8 @@ extern Datum fdw_handler_in(PG_FUNCTION_ARGS);
 extern Datum fdw_handler_out(PG_FUNCTION_ARGS);
 extern Datum tsm_handler_in(PG_FUNCTION_ARGS);
 extern Datum tsm_handler_out(PG_FUNCTION_ARGS);
+extern Datum cstore_handler_in(PG_FUNCTION_ARGS);
+extern Datum cstore_handler_out(PG_FUNCTION_ARGS);
 extern Datum internal_in(PG_FUNCTION_ARGS);
 extern Datum internal_out(PG_FUNCTION_ARGS);
 extern Datum opaque_in(PG_FUNCTION_ARGS);
-- 
2.1.4

