diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c
new file mode 100644
index d657c20..56344a3
*** a/src/backend/catalog/dependency.c
--- b/src/backend/catalog/dependency.c
***************
*** 20,25 ****
--- 20,26 ----
  #include "catalog/heap.h"
  #include "catalog/index.h"
  #include "catalog/objectaccess.h"
+ #include "catalog/pg_am.h"
  #include "catalog/pg_amop.h"
  #include "catalog/pg_amproc.h"
  #include "catalog/pg_attrdef.h"
*************** static const Oid object_classes[] = {
*** 159,165 ****
  	ExtensionRelationId,		/* OCLASS_EXTENSION */
  	EventTriggerRelationId,		/* OCLASS_EVENT_TRIGGER */
  	PolicyRelationId,			/* OCLASS_POLICY */
! 	TransformRelationId			/* OCLASS_TRANSFORM */
  };
  
  
--- 160,167 ----
  	ExtensionRelationId,		/* OCLASS_EXTENSION */
  	EventTriggerRelationId,		/* OCLASS_EVENT_TRIGGER */
  	PolicyRelationId,			/* OCLASS_POLICY */
! 	TransformRelationId,		/* OCLASS_TRANSFORM */
! 	AccessMethodRelationId		/* OCLASS_AM */
  };
  
  
*************** doDeletion(const ObjectAddress *object, 
*** 1269,1274 ****
--- 1271,1279 ----
  
  		case OCLASS_TRANSFORM:
  			DropTransformById(object->objectId);
+ 
+ 		case OCLASS_AM:
+ 			RemoveAccessMethodById(object->objectId);
  			break;
  
  		default:
*************** getObjectClass(const ObjectAddress *obje
*** 2414,2419 ****
--- 2419,2427 ----
  
  		case TransformRelationId:
  			return OCLASS_TRANSFORM;
+ 
+ 		case AccessMethodRelationId:
+ 			return OCLASS_AM;
  	}
  
  	/* shouldn't get here */
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
new file mode 100644
index 0232e0d..01997a9
*** a/src/backend/catalog/objectaddress.c
--- b/src/backend/catalog/objectaddress.c
*************** static const ObjectPropertyType ObjectPr
*** 437,442 ****
--- 437,454 ----
  		Anum_pg_type_typacl,
  		ACL_KIND_TYPE,
  		true
+ 	},
+ 	{
+ 		AccessMethodRelationId,
+ 		AmOidIndexId,
+ 		AMOID,
+ 		AMNAME,
+ 		Anum_pg_am_amname,
+ 		InvalidAttrNumber,
+ 		InvalidAttrNumber,
+ 		InvalidAttrNumber,
+ 		-1,
+ 		true
  	}
  };
  
*************** static ObjectAddress get_object_address_
*** 673,678 ****
--- 685,692 ----
  							   List *objargs, bool missing_ok);
  static ObjectAddress get_object_address_defacl(List *objname, List *objargs,
  						  bool missing_ok);
+ static ObjectAddress get_object_address_am(ObjectType objtype, List *objname,
+ 						bool missing_ok);
  static const ObjectPropertyType *get_object_property_data(Oid class_id);
  
  static void getRelationDescription(StringInfo buffer, Oid relid);
*************** get_object_address(ObjectType objtype, L
*** 912,917 ****
--- 926,934 ----
  				address = get_object_address_defacl(objname, objargs,
  													missing_ok);
  				break;
+ 			case OBJECT_ACCESS_METHOD:
+ 				address = get_object_address_am(objtype, objname, missing_ok);
+ 				break;
  			default:
  				elog(ERROR, "unrecognized objtype: %d", (int) objtype);
  				/* placate compiler, in case it thinks elog might return */
*************** get_object_address_opcf(ObjectType objty
*** 1515,1520 ****
--- 1532,1596 ----
  }
  
  /*
+  * Find the ObjectAddress for an access method.
+  */
+ static ObjectAddress
+ get_object_address_am(ObjectType objtype, List *objname, bool missing_ok)
+ {
+ 	ObjectAddress	address;
+ 	char		   *amname, *catalogname;
+ 	Type		tup;
+ 
+ 	switch (list_length(objname))
+ 	{
+ 		case 1:
+ 			amname = strVal(linitial(objname));
+ 			break;
+ 		case 2:
+ 			catalogname = strVal(linitial(objname));
+ 			amname = strVal(lsecond(objname));
+ 
+ 			/*
+ 			 * We check the catalog name and then ignore it.
+ 			 */
+ 			if (strcmp(catalogname, get_database_name(MyDatabaseId)) != 0)
+ 				ereport(ERROR,
+ 						(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
+ 				  errmsg("cross-database references are not implemented: %s",
+ 						 NameListToString(objname))));
+ 			break;
+ 		default:
+ 			ereport(ERROR,
+ 					(errcode(ERRCODE_SYNTAX_ERROR),
+ 				errmsg("improper access method name (too many dotted names): %s",
+ 					   NameListToString(objname))));
+ 			break;
+ 	}
+ 
+ 	address.classId = AccessMethodRelationId;
+ 	address.objectId = InvalidOid;
+ 	address.objectSubId = 0;
+ 
+ 	tup = SearchSysCache1(AMNAME, PointerGetDatum(amname));
+ 	if (!HeapTupleIsValid(tup))
+ 	{
+ 		/* Access method is missing, report error if needed */
+ 		if (!missing_ok)
+ 			ereport(ERROR,
+ 					(errcode(ERRCODE_UNDEFINED_OBJECT),
+ 					 errmsg("access method \"%s\" does not exist",
+ 							amname)));
+ 		return address;
+ 	}
+ 
+ 	/* Access method is found, return its oid */
+ 	address.objectId = HeapTupleGetOid(tup);
+ 	ReleaseSysCache(tup);
+ 
+ 	return address;
+ }
+ 
+ /*
   * Find the ObjectAddress for an opclass/opfamily member.
   *
   * (The returned address corresponds to a pg_amop/pg_amproc object).
*************** check_object_ownership(Oid roleid, Objec
*** 2178,2183 ****
--- 2254,2260 ----
  			break;
  		case OBJECT_TSPARSER:
  		case OBJECT_TSTEMPLATE:
+ 		case OBJECT_ACCESS_METHOD:
  			/* We treat these object types as being owned by superusers */
  			if (!superuser_arg(roleid))
  				ereport(ERROR,
*************** getObjectDescription(const ObjectAddress
*** 3128,3133 ****
--- 3205,3225 ----
  				break;
  			}
  
+ 		case OCLASS_AM:
+ 			{
+ 				HeapTuple	tup;
+ 
+ 				tup = SearchSysCache1(AMOID,
+ 									  ObjectIdGetDatum(object->objectId));
+ 				if (!HeapTupleIsValid(tup))
+ 					elog(ERROR, "cache lookup failed for access method %u",
+ 						 object->objectId);
+ 				appendStringInfo(&buffer, _("access method %s"),
+ 							NameStr(((Form_pg_am) GETSTRUCT(tup))->amname));
+ 				ReleaseSysCache(tup);
+ 				break;
+ 			}
+ 
  		default:
  			appendStringInfo(&buffer, "unrecognized object %u %u %d",
  							 object->classId,
diff --git a/src/backend/commands/Makefile b/src/backend/commands/Makefile
new file mode 100644
index b1ac704..6b3742c
*** a/src/backend/commands/Makefile
--- b/src/backend/commands/Makefile
*************** subdir = src/backend/commands
*** 12,18 ****
  top_builddir = ../../..
  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 \
  	event_trigger.o explain.o extension.o foreigncmds.o functioncmds.o \
--- 12,18 ----
  top_builddir = ../../..
  include $(top_builddir)/src/Makefile.global
  
! OBJS = amcmds.o 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 \
  	event_trigger.o explain.o extension.o foreigncmds.o functioncmds.o \
diff --git a/src/backend/commands/amcmds.c b/src/backend/commands/amcmds.c
new file mode 100644
index ...0bec2a8
*** a/src/backend/commands/amcmds.c
--- b/src/backend/commands/amcmds.c
***************
*** 0 ****
--- 1,193 ----
+ /*-------------------------------------------------------------------------
+  *
+  * amcmds.c
+  *	  Routines for SQL commands that manipulate access methods.
+  *
+  * Portions Copyright (c) 1996-2014, PostgreSQL Global Development Group
+  * Portions Copyright (c) 1994, Regents of the University of California
+  *
+  *
+  * IDENTIFICATION
+  *	  src/backend/commands/amcmds.c
+  *-------------------------------------------------------------------------
+  */
+ #include "postgres.h"
+ 
+ #include "access/genam.h"
+ #include "access/heapam.h"
+ #include "access/htup_details.h"
+ #include "access/xact.h"
+ #include "catalog/binary_upgrade.h"
+ #include "catalog/catalog.h"
+ #include "catalog/dependency.h"
+ #include "catalog/heap.h"
+ #include "catalog/indexing.h"
+ #include "catalog/objectaccess.h"
+ #include "catalog/pg_authid.h"
+ #include "catalog/pg_am.h"
+ #include "catalog/pg_collation.h"
+ #include "catalog/pg_constraint.h"
+ #include "catalog/pg_depend.h"
+ #include "catalog/pg_enum.h"
+ #include "catalog/pg_language.h"
+ #include "catalog/pg_namespace.h"
+ #include "catalog/pg_proc.h"
+ #include "catalog/pg_proc_fn.h"
+ #include "catalog/pg_range.h"
+ #include "catalog/pg_type.h"
+ #include "catalog/pg_type_fn.h"
+ #include "commands/dbcommands.h"
+ #include "commands/defrem.h"
+ #include "commands/tablecmds.h"
+ #include "commands/typecmds.h"
+ #include "executor/executor.h"
+ #include "miscadmin.h"
+ #include "nodes/makefuncs.h"
+ #include "optimizer/planner.h"
+ #include "optimizer/var.h"
+ #include "parser/parse_coerce.h"
+ #include "parser/parse_collate.h"
+ #include "parser/parse_expr.h"
+ #include "parser/parse_func.h"
+ #include "parser/parse_type.h"
+ #include "utils/acl.h"
+ #include "utils/builtins.h"
+ #include "utils/fmgroids.h"
+ #include "utils/lsyscache.h"
+ #include "utils/memutils.h"
+ #include "utils/rel.h"
+ #include "utils/snapmgr.h"
+ #include "utils/syscache.h"
+ #include "utils/tqual.h"
+ 
+ /*
+  * Convert a handler function name passed from the parser to an Oid.
+  */
+ static Oid
+ lookup_am_handler_func(List *handler_name)
+ {
+ 	Oid			handlerOid;
+ 	Oid			funcargtypes[1] = {INTERNALOID};
+ 
+ 	if (handler_name == NIL)
+ 		return InvalidOid;
+ 
+ 	/* handlers have no arguments */
+ 	handlerOid = LookupFuncName(handler_name, 1, funcargtypes, false);
+ 
+ 	/* check that handler has correct return type */
+ 	if (get_func_rettype(handlerOid) != INDEX_AM_HANDLEROID)
+ 		ereport(ERROR,
+ 				(errcode(ERRCODE_WRONG_OBJECT_TYPE),
+ 				 errmsg("function %s must return type \"index_am_handler\"",
+ 						NameListToString(handler_name))));
+ 
+ 	return handlerOid;
+ }
+ 
+ 
+ /*
+  * DefineAccessMethod
+  *		Registers a new access method.
+  */
+ ObjectAddress
+ CreateAccessMethod(CreateAmStmt *stmt)
+ {
+ 	Relation		rel;
+ 	ObjectAddress	myself;
+ 	ObjectAddress	referenced;
+ 	Oid				amoid;
+ 	Oid				amhandler;
+ 	bool			nulls[Natts_pg_am];
+ 	Datum			values[Natts_pg_am];
+ 	HeapTuple		tup;
+ 
+ 	rel = heap_open(AccessMethodRelationId, RowExclusiveLock);
+ 
+ 	/* Must be super user */
+ 	if (!superuser())
+ 		ereport(ERROR,
+ 				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ 			errmsg("permission denied to create access method \"%s\"",
+ 				   stmt->amname),
+ 			errhint("Must be superuser to create access method.")));
+ 
+ 	/* Check if name is busy */
+ 	amoid = GetSysCacheOid1(AMNAME, CStringGetDatum(stmt->amname));
+ 	if (OidIsValid(amoid))
+ 	{
+ 		ereport(ERROR,
+ 				(errcode(ERRCODE_DUPLICATE_OBJECT),
+ 				 errmsg("access method \"%s\" already exists", stmt->amname)));
+ 	}
+ 
+ 	/* Get handler function oid */
+ 	amhandler = lookup_am_handler_func(stmt->handler_name);
+ 	if (!OidIsValid(amhandler))
+ 	{
+ 		ereport(ERROR,
+ 				(errcode(ERRCODE_UNDEFINED_FUNCTION),
+ 				 errmsg("handler function \"%s\" is undefined",
+ 						NameListToString(stmt->handler_name))));
+ 	}
+ 
+ 	/*
+ 	 * Insert tuple into pg_am.
+ 	 */
+ 	memset(values, 0, sizeof(values));
+ 	memset(nulls, false, sizeof(nulls));
+ 
+ 	values[Anum_pg_am_amname - 1] =
+ 		DirectFunctionCall1(namein, CStringGetDatum(stmt->amname));
+ 	values[Anum_pg_am_amhandler - 1] = ObjectIdGetDatum(amhandler);
+ 
+ 	tup = heap_form_tuple(RelationGetDescr(rel), values, nulls);
+ 
+ 	amoid = simple_heap_insert(rel, tup);
+ 	CatalogUpdateIndexes(rel, tup);
+ 	heap_freetuple(tup);
+ 
+ 	myself.classId = AccessMethodRelationId;
+ 	myself.objectId = amoid;
+ 	myself.objectSubId = 0;
+ 
+ 	/* Record dependecy on handler function */
+ 	referenced.classId = ProcedureRelationId;
+ 	referenced.objectId = amhandler;
+ 	referenced.objectSubId = 0;
+ 
+ 	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ 
+ 	recordDependencyOnCurrentExtension(&myself, false);
+ 
+ 	heap_close(rel, RowExclusiveLock);
+ 
+ 	return myself;
+ }
+ 
+ /*
+  * Guts of access method deletion.
+  */
+ void
+ RemoveAccessMethodById(Oid amOid)
+ {
+ 	Relation	relation;
+ 	HeapTuple	tup;
+ 
+ 	if (!superuser())
+ 		ereport(ERROR,
+ 				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+ 				 errmsg("must be superuser to drop access methods")));
+ 
+ 	relation = heap_open(AccessMethodRelationId, RowExclusiveLock);
+ 
+ 	tup = SearchSysCache1(AMOID, ObjectIdGetDatum(amOid));
+ 	if (!HeapTupleIsValid(tup))
+ 		elog(ERROR, "cache lookup failed for access method %u", amOid);
+ 
+ 	simple_heap_delete(relation, &tup->t_self);
+ 
+ 	ReleaseSysCache(tup);
+ 
+ 	heap_close(relation, RowExclusiveLock);
+ }
diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c
new file mode 100644
index 9e32f8d..3f52ad8
*** a/src/backend/commands/event_trigger.c
--- b/src/backend/commands/event_trigger.c
*************** typedef enum
*** 86,91 ****
--- 86,92 ----
  
  /* XXX merge this with ObjectTypeMap? */
  static event_trigger_support_data event_trigger_support[] = {
+ 	{"ACCESS METHOD", true},
  	{"AGGREGATE", true},
  	{"CAST", true},
  	{"CONSTRAINT", true},
*************** EventTriggerSupportsObjectType(ObjectTyp
*** 1078,1083 ****
--- 1079,1085 ----
  		case OBJECT_EVENT_TRIGGER:
  			/* no support for event triggers on event triggers */
  			return false;
+ 		case OBJECT_ACCESS_METHOD:
  		case OBJECT_AGGREGATE:
  		case OBJECT_AMOP:
  		case OBJECT_AMPROC:
*************** EventTriggerSupportsObjectClass(ObjectCl
*** 1167,1172 ****
--- 1169,1175 ----
  		case OCLASS_DEFACL:
  		case OCLASS_EXTENSION:
  		case OCLASS_POLICY:
+ 		case OCLASS_AM:
  			return true;
  	}
  
diff --git a/src/backend/commands/opclasscmds.c b/src/backend/commands/opclasscmds.c
new file mode 100644
index 8a66196..8bd2658
*** a/src/backend/commands/opclasscmds.c
--- b/src/backend/commands/opclasscmds.c
*************** DefineOpClass(CreateOpClassStmt *stmt)
*** 678,683 ****
--- 678,689 ----
  	myself.objectId = opclassoid;
  	myself.objectSubId = 0;
  
+ 	/* dependency on access method */
+ 	referenced.classId = AccessMethodRelationId;
+ 	referenced.objectId = amoid;
+ 	referenced.objectSubId = 0;
+ 	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+ 
  	/* dependency on namespace */
  	referenced.classId = NamespaceRelationId;
  	referenced.objectId = namespaceoid;
diff --git a/src/backend/nodes/copyfuncs.c b/src/backend/nodes/copyfuncs.c
new file mode 100644
index a8b79fa..5678058
*** a/src/backend/nodes/copyfuncs.c
--- b/src/backend/nodes/copyfuncs.c
*************** _copyCreateTransformStmt(const CreateTra
*** 3826,3831 ****
--- 3826,3842 ----
  	return newnode;
  }
  
+ static CreateAmStmt *
+ _copyCreateAmStmt(const CreateAmStmt *from)
+ {
+ 	CreateAmStmt *newnode = makeNode(CreateAmStmt);
+ 
+ 	COPY_STRING_FIELD(amname);
+ 	COPY_NODE_FIELD(handler_name);
+ 
+ 	return newnode;
+ }
+ 
  static CreateTrigStmt *
  _copyCreateTrigStmt(const CreateTrigStmt *from)
  {
*************** copyObject(const void *from)
*** 4789,4794 ****
--- 4800,4808 ----
  		case T_CreateTransformStmt:
  			retval = _copyCreateTransformStmt(from);
  			break;
+ 		case T_CreateAmStmt:
+ 			retval = _copyCreateAmStmt(from);
+ 			break;
  		case T_CreateTrigStmt:
  			retval = _copyCreateTrigStmt(from);
  			break;
diff --git a/src/backend/nodes/equalfuncs.c b/src/backend/nodes/equalfuncs.c
new file mode 100644
index 08ccc0d..7fd4896
*** a/src/backend/nodes/equalfuncs.c
--- b/src/backend/nodes/equalfuncs.c
*************** _equalCreateTransformStmt(const CreateTr
*** 1835,1840 ****
--- 1835,1849 ----
  }
  
  static bool
+ _equalCreateAmStmt(const CreateAmStmt *a, const CreateAmStmt *b)
+ {
+ 	COMPARE_STRING_FIELD(amname);
+ 	COMPARE_NODE_FIELD(handler_name);
+ 
+ 	return true;
+ }
+ 
+ static bool
  _equalCreateTrigStmt(const CreateTrigStmt *a, const CreateTrigStmt *b)
  {
  	COMPARE_STRING_FIELD(trigname);
*************** equal(const void *a, const void *b)
*** 3119,3124 ****
--- 3128,3136 ----
  		case T_CreateTransformStmt:
  			retval = _equalCreateTransformStmt(a, b);
  			break;
+ 		case T_CreateAmStmt:
+ 			retval = _equalCreateAmStmt(a, b);
+ 			break;
  		case T_CreateTrigStmt:
  			retval = _equalCreateTrigStmt(a, b);
  			break;
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
new file mode 100644
index b307b48..2b99503
*** a/src/backend/parser/gram.y
--- b/src/backend/parser/gram.y
*************** static Node *makeRecursiveViewSelect(cha
*** 263,269 ****
  		DeallocateStmt PrepareStmt ExecuteStmt
  		DropOwnedStmt ReassignOwnedStmt
  		AlterTSConfigurationStmt AlterTSDictionaryStmt
! 		CreateMatViewStmt RefreshMatViewStmt
  
  %type <node>	select_no_parens select_with_parens select_clause
  				simple_select values_clause
--- 263,269 ----
  		DeallocateStmt PrepareStmt ExecuteStmt
  		DropOwnedStmt ReassignOwnedStmt
  		AlterTSConfigurationStmt AlterTSDictionaryStmt
! 		CreateMatViewStmt RefreshMatViewStmt CreateAmStmt DropAmStmt
  
  %type <node>	select_no_parens select_with_parens select_clause
  				simple_select values_clause
*************** static Node *makeRecursiveViewSelect(cha
*** 604,610 ****
  	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
  
  	NAME_P NAMES NATIONAL NATURAL NCHAR NEXT NO NONE
  	NOT NOTHING NOTIFY NOTNULL NOWAIT NULL_P NULLIF
--- 604,610 ----
  	LEADING LEAKPROOF LEAST LEFT LEVEL LIKE LIMIT LISTEN LOAD LOCAL
  	LOCALTIME LOCALTIMESTAMP LOCATION LOCK_P LOCKED LOGGED
  
! 	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
*************** stmt :
*** 789,794 ****
--- 789,795 ----
  			| CommentStmt
  			| ConstraintsSetStmt
  			| CopyStmt
+ 			| CreateAmStmt
  			| CreateAsStmt
  			| CreateAssertStmt
  			| CreateCastStmt
*************** stmt :
*** 823,828 ****
--- 824,830 ----
  			| DeleteStmt
  			| DiscardStmt
  			| DoStmt
+ 			| DropAmStmt
  			| DropAssertStmt
  			| DropCastStmt
  			| DropFdwStmt
*************** row_security_cmd:
*** 4708,4713 ****
--- 4710,4763 ----
  
  /*****************************************************************************
   *
+  *		QUERY:
+  *             CREATE ACCESS METHOD name HANDLER handler_name
+  *
+  *****************************************************************************/
+ 
+ CreateAmStmt: CREATE ACCESS METHOD name HANDLER handler_name
+ 				{
+ 					CreateAmStmt *n = makeNode(CreateAmStmt);
+ 					n->amname = $4;
+ 					n->handler_name = $6;
+ 					$$ = (Node *) n;
+ 				}
+ 		;
+ 
+ /*****************************************************************************
+  *
+  *		QUERY :
+  *				DROP ACCESS METHOD name
+  *
+  ****************************************************************************/
+ 
+ DropAmStmt: DROP ACCESS METHOD name opt_drop_behavior
+ 				{
+ 					DropStmt *n = makeNode(DropStmt);
+ 					n->removeType = OBJECT_ACCESS_METHOD;
+ 					n->objects = list_make1(list_make1(makeString($4)));
+ 					n->arguments = NIL;
+ 					n->missing_ok = false;
+ 					n->behavior = $5;
+ 					n->concurrent = false;
+ 					$$ = (Node *) n;
+ 				}
+ 				|  DROP ACCESS METHOD IF_P EXISTS name opt_drop_behavior
+ 				{
+ 					DropStmt *n = makeNode(DropStmt);
+ 					n->removeType = OBJECT_ACCESS_METHOD;
+ 					n->objects = list_make1(list_make1(makeString($6)));
+ 					n->arguments = NIL;
+ 					n->missing_ok = true;
+ 					n->behavior = $7;
+ 					n->concurrent = false;
+ 					$$ = (Node *) n;
+ 				}
+ 		;
+ 
+ 
+ /*****************************************************************************
+  *
   *		QUERIES :
   *				CREATE TRIGGER ...
   *				DROP TRIGGER ...
*************** unreserved_keyword:
*** 13778,13783 ****
--- 13828,13834 ----
  			| MATCH
  			| MATERIALIZED
  			| MAXVALUE
+ 			| METHOD
  			| MINUTE_P
  			| MINVALUE
  			| MODE
diff --git a/src/backend/tcop/utility.c b/src/backend/tcop/utility.c
new file mode 100644
index 045f7f0..4d0aac9
*** a/src/backend/tcop/utility.c
--- b/src/backend/tcop/utility.c
*************** ProcessUtilitySlow(Node *parsetree,
*** 1520,1525 ****
--- 1520,1529 ----
  				address = ExecSecLabelStmt((SecLabelStmt *) parsetree);
  				break;
  
+ 			case T_CreateAmStmt:
+ 				address = CreateAccessMethod((CreateAmStmt *) parsetree);
+ 				break;
+ 
  			default:
  				elog(ERROR, "unrecognized node type: %d",
  					 (int) nodeTag(parsetree));
*************** CreateCommandTag(Node *parsetree)
*** 2160,2165 ****
--- 2164,2172 ----
  				case OBJECT_TRANSFORM:
  					tag = "DROP TRANSFORM";
  					break;
+ 				case OBJECT_ACCESS_METHOD:
+ 					tag = "DROP ACCESS METHOD";
+ 					break;
  				default:
  					tag = "???";
  			}
*************** CreateCommandTag(Node *parsetree)
*** 2256,2261 ****
--- 2263,2271 ----
  				case OBJECT_COLLATION:
  					tag = "CREATE COLLATION";
  					break;
+ 				case OBJECT_ACCESS_METHOD:
+ 					tag = "CREATE ACCESS METHOD";
+ 					break;
  				default:
  					tag = "???";
  			}
*************** CreateCommandTag(Node *parsetree)
*** 2519,2524 ****
--- 2529,2538 ----
  			tag = "ALTER POLICY";
  			break;
  
+ 		case T_CreateAmStmt:
+ 			tag = "CREATE ACCESS METHOD";
+ 			break;
+ 
  		case T_PrepareStmt:
  			tag = "PREPARE";
  			break;
*************** GetCommandLogLevel(Node *parsetree)
*** 3076,3081 ****
--- 3090,3099 ----
  			lev = LOGSTMT_DDL;
  			break;
  
+ 		case T_CreateAmStmt:
+ 			lev = LOGSTMT_DDL;
+ 			break;
+ 
  			/* already-planned queries */
  		case T_PlannedStmt:
  			{
diff --git a/src/backend/utils/adt/selfuncs.c b/src/backend/utils/adt/selfuncs.c
new file mode 100644
index 46c95b0..516af92
*** a/src/backend/utils/adt/selfuncs.c
--- b/src/backend/utils/adt/selfuncs.c
*************** string_to_bytea_const(const char *str, s
*** 6012,6032 ****
   *-------------------------------------------------------------------------
   */
  
! /*
!  * deconstruct_indexquals is a simple function to examine the indexquals
!  * attached to a proposed IndexPath.  It returns a list of IndexQualInfo
!  * structs, one per qual expression.
!  */
! typedef struct
! {
! 	RestrictInfo *rinfo;		/* the indexqual itself */
! 	int			indexcol;		/* zero-based index column number */
! 	bool		varonleft;		/* true if index column is on left of qual */
! 	Oid			clause_op;		/* qual's operator OID, if relevant */
! 	Node	   *other_operand;	/* non-index operand of qual's operator */
! } IndexQualInfo;
! 
! static List *
  deconstruct_indexquals(IndexPath *path)
  {
  	List	   *result = NIL;
--- 6012,6018 ----
   *-------------------------------------------------------------------------
   */
  
! List *
  deconstruct_indexquals(IndexPath *path)
  {
  	List	   *result = NIL;
*************** orderby_operands_eval_cost(PlannerInfo *
*** 6176,6210 ****
  	return qual_arg_cost;
  }
  
! /*
!  * genericcostestimate is a general-purpose estimator that can be used for
!  * most index types.  In some cases we use genericcostestimate as the base
!  * code and then incorporate additional index-type-specific knowledge in
!  * the type-specific calling function.  To avoid code duplication, we make
!  * genericcostestimate return a number of intermediate values as well as
!  * its preliminary estimates of the output cost values.  The GenericCosts
!  * struct includes all these values.
!  *
!  * Callers should initialize all fields of GenericCosts to zero.  In addition,
!  * they can set numIndexTuples to some positive value if they have a better
!  * than default way of estimating the number of leaf index tuples visited.
!  */
! typedef struct
! {
! 	/* These are the values the cost estimator must return to the planner */
! 	Cost		indexStartupCost;		/* index-related startup cost */
! 	Cost		indexTotalCost; /* total index-related scan cost */
! 	Selectivity indexSelectivity;		/* selectivity of index */
! 	double		indexCorrelation;		/* order correlation of index */
! 
! 	/* Intermediate values we obtain along the way */
! 	double		numIndexPages;	/* number of leaf pages visited */
! 	double		numIndexTuples; /* number of leaf tuples visited */
! 	double		spc_random_page_cost;	/* relevant random_page_cost value */
! 	double		num_sa_scans;	/* # indexscans from ScalarArrayOps */
! } GenericCosts;
! 
! static void
  genericcostestimate(PlannerInfo *root,
  					IndexPath *path,
  					double loop_count,
--- 6162,6168 ----
  	return qual_arg_cost;
  }
  
! void
  genericcostestimate(PlannerInfo *root,
  					IndexPath *path,
  					double loop_count,
diff --git a/src/bin/pg_dump/common.c b/src/bin/pg_dump/common.c
new file mode 100644
index f798b15..1acd91a
*** a/src/bin/pg_dump/common.c
--- b/src/bin/pg_dump/common.c
*************** getSchemaData(Archive *fout, int *numTab
*** 98,103 ****
--- 98,104 ----
  	int			numProcLangs;
  	int			numCasts;
  	int			numTransforms;
+ 	int			numAccessMethods;
  	int			numOpclasses;
  	int			numOpfamilies;
  	int			numConversions;
*************** getSchemaData(Archive *fout, int *numTab
*** 169,174 ****
--- 170,179 ----
  	oprinfoindex = buildIndexArray(oprinfo, numOperators, sizeof(OprInfo));
  
  	if (g_verbose)
+ 		write_msg(NULL, "reading user-defined access methods\n");
+ 	getAccessMethods(fout, &numAccessMethods);
+ 
+ 	if (g_verbose)
  		write_msg(NULL, "reading user-defined operator classes\n");
  	getOpclasses(fout, &numOpclasses);
  
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
new file mode 100644
index aa01d6a..2341cf0
*** a/src/bin/pg_dump/pg_dump.c
--- b/src/bin/pg_dump/pg_dump.c
*************** static void dumpFunc(Archive *fout, Func
*** 173,178 ****
--- 173,179 ----
  static void dumpCast(Archive *fout, CastInfo *cast);
  static void dumpTransform(Archive *fout, TransformInfo *transform);
  static void dumpOpr(Archive *fout, OprInfo *oprinfo);
+ static void dumpAccessMethod(Archive *fout, AccessMethodInfo *oprinfo);
  static void dumpOpclass(Archive *fout, OpclassInfo *opcinfo);
  static void dumpOpfamily(Archive *fout, OpfamilyInfo *opfinfo);
  static void dumpCollation(Archive *fout, CollInfo *convinfo);
*************** getConversions(Archive *fout, int *numCo
*** 4101,4106 ****
--- 4102,4183 ----
  }
  
  /*
+  * getAccessMethods:
+  *	  read all user-defined access methods in the system catalogs and return
+  *    them in the AccessMethodInfo* structure
+  *
+  *	numAccessMethods is set to the number of access methods read in
+  */
+ AccessMethodInfo *
+ getAccessMethods(Archive *fout, int *numAccessMethods)
+ {
+ 	DumpOptions *dopt = fout->dopt;
+ 	PGresult   *res;
+ 	int			ntups;
+ 	int			i;
+ 	PQExpBuffer query;
+ 	AccessMethodInfo *aminfo;
+ 	int			i_tableoid;
+ 	int			i_oid;
+ 	int			i_amname;
+ 	int			i_amhandler;
+ 
+ 	/* Before 9.6, there are no user-defined access methods */
+ 	if (fout->remoteVersion < 90600)
+ 	{
+ 		*numAccessMethods = 0;
+ 		return NULL;
+ 	}
+ 
+ 	query = createPQExpBuffer();
+ 
+ 	/* Make sure we are in proper schema */
+ 	selectSourceSchema(fout, "pg_catalog");
+ 
+ 	/*
+ 	 * Select only user-defined access methods assuming all built-in access
+ 	 * methods have oid < 10000.
+ 	 */
+ 	appendPQExpBuffer(query, "SELECT tableoid, oid, amname, "
+ 					  "amhandler::pg_catalog.regproc AS amhandler "
+ 					  "FROM pg_am "
+ 					  "WHERE oid >= 10000");
+ 
+ 	res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
+ 
+ 	ntups = PQntuples(res);
+ 	*numAccessMethods = ntups;
+ 
+ 	aminfo = (AccessMethodInfo *) pg_malloc(ntups * sizeof(AccessMethodInfo));
+ 
+ 	i_tableoid = PQfnumber(res, "tableoid");
+ 	i_oid = PQfnumber(res, "oid");
+ 	i_amname = PQfnumber(res, "amname");
+ 	i_amhandler = PQfnumber(res, "amhandler");
+ 
+ 	for (i = 0; i < ntups; i++)
+ 	{
+ 		aminfo[i].dobj.objType = DO_ACCESS_METHOD;
+ 		aminfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
+ 		aminfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
+ 		AssignDumpId(&aminfo[i].dobj);
+ 		aminfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_amname));
+ 		aminfo[i].dobj.namespace = NULL;
+ 		aminfo[i].amhandler = pg_strdup(PQgetvalue(res, i, i_amhandler));
+ 
+ 		/* Decide whether we want to dump it */
+ 		selectDumpableObject(&(aminfo[i].dobj), dopt);
+ 	}
+ 
+ 	PQclear(res);
+ 
+ 	destroyPQExpBuffer(query);
+ 
+ 	return aminfo;
+ }
+ 
+ 
+ /*
   * getOpclasses:
   *	  read all opclasses in the system catalogs and return them in the
   * OpclassInfo* structure
*************** dumpDumpableObject(Archive *fout, Dumpab
*** 8405,8410 ****
--- 8482,8490 ----
  		case DO_OPERATOR:
  			dumpOpr(fout, (OprInfo *) dobj);
  			break;
+ 		case DO_ACCESS_METHOD:
+ 			dumpAccessMethod(fout, (AccessMethodInfo *) dobj);
+ 			break;
  		case DO_OPCLASS:
  			dumpOpclass(fout, (OpclassInfo *) dobj);
  			break;
*************** convertTSFunction(Archive *fout, Oid fun
*** 11443,11448 ****
--- 11523,11581 ----
  	return result;
  }
  
+ /*
+  * dumpAccessMethod
+  *	  write out a single access method definition
+  */
+ static void
+ dumpAccessMethod(Archive *fout, AccessMethodInfo *aminfo)
+ {
+ 	DumpOptions *dopt = fout->dopt;
+ 	PQExpBuffer q;
+ 	PQExpBuffer delq;
+ 	PQExpBuffer labelq;
+ 	char	   *qamname;
+ 
+ 	/* Skip if not to be dumped */
+ 	if (!aminfo->dobj.dump || dopt->dataOnly)
+ 		return;
+ 
+ 	q = createPQExpBuffer();
+ 	delq = createPQExpBuffer();
+ 	labelq = createPQExpBuffer();
+ 
+ 	qamname = pg_strdup(fmtId(aminfo->dobj.name));
+ 
+ 	appendPQExpBuffer(q, "CREATE ACCESS METHOD %s HANDLER %s;\n",
+ 					  qamname, aminfo->amhandler);
+ 
+ 	appendPQExpBuffer(delq, "DROP ACCESS METHOD %s;\n",
+ 					  qamname);
+ 
+ 	appendPQExpBuffer(labelq, "ACCESS METHOD %s",
+ 					  qamname);
+ 
+ 	ArchiveEntry(fout, aminfo->dobj.catId, aminfo->dobj.dumpId,
+ 				 aminfo->dobj.name,
+ 				 NULL,
+ 				 NULL,
+ 				 "",
+ 				 false, "ACCESS METHOD", SECTION_PRE_DATA,
+ 				 q->data, delq->data, NULL,
+ 				 NULL, 0,
+ 				 NULL, NULL);
+ 
+ 	/* Dump Access Method Comments */
+ 	dumpComment(fout, labelq->data,
+ 				NULL, "",
+ 				aminfo->dobj.catId, 0, aminfo->dobj.dumpId);
+ 
+ 	free(qamname);
+ 
+ 	destroyPQExpBuffer(q);
+ 	destroyPQExpBuffer(delq);
+ 	destroyPQExpBuffer(labelq);
+ }
  
  /*
   * dumpOpclass
*************** addBoundaryDependencies(DumpableObject *
*** 16224,16229 ****
--- 16357,16363 ----
  			case DO_FUNC:
  			case DO_AGG:
  			case DO_OPERATOR:
+ 			case DO_ACCESS_METHOD:
  			case DO_OPCLASS:
  			case DO_OPFAMILY:
  			case DO_COLLATION:
diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h
new file mode 100644
index 78b2584..3046feb
*** a/src/bin/pg_dump/pg_dump.h
--- b/src/bin/pg_dump/pg_dump.h
*************** typedef enum
*** 48,53 ****
--- 48,54 ----
  	DO_FUNC,
  	DO_AGG,
  	DO_OPERATOR,
+ 	DO_ACCESS_METHOD,
  	DO_OPCLASS,
  	DO_OPFAMILY,
  	DO_COLLATION,
*************** typedef enum
*** 77,83 ****
  	DO_POST_DATA_BOUNDARY,
  	DO_EVENT_TRIGGER,
  	DO_REFRESH_MATVIEW,
! 	DO_POLICY
  } DumpableObjectType;
  
  typedef struct _dumpableObject
--- 78,84 ----
  	DO_POST_DATA_BOUNDARY,
  	DO_EVENT_TRIGGER,
  	DO_REFRESH_MATVIEW,
! 	DO_POLICY,
  } DumpableObjectType;
  
  typedef struct _dumpableObject
*************** typedef struct _oprInfo
*** 167,172 ****
--- 168,179 ----
  	Oid			oprcode;
  } OprInfo;
  
+ typedef struct _accessMethodInfo
+ {
+ 	DumpableObject dobj;
+ 	char	   *amhandler;
+ } AccessMethodInfo;
+ 
  typedef struct _opclassInfo
  {
  	DumpableObject dobj;
*************** extern TypeInfo *getTypes(Archive *fout,
*** 546,551 ****
--- 553,559 ----
  extern FuncInfo *getFuncs(Archive *fout, int *numFuncs);
  extern AggInfo *getAggregates(Archive *fout, int *numAggregates);
  extern OprInfo *getOperators(Archive *fout, int *numOperators);
+ extern AccessMethodInfo *getAccessMethods(Archive *fout, int *numAccessMethods);
  extern OpclassInfo *getOpclasses(Archive *fout, int *numOpclasses);
  extern OpfamilyInfo *getOpfamilies(Archive *fout, int *numOpfamilies);
  extern CollInfo *getCollations(Archive *fout, int *numCollations);
diff --git a/src/bin/pg_dump/pg_dump_sort.c b/src/bin/pg_dump/pg_dump_sort.c
new file mode 100644
index b0f6ace..b03561a
*** a/src/bin/pg_dump/pg_dump_sort.c
--- b/src/bin/pg_dump/pg_dump_sort.c
*************** static const int oldObjectTypePriority[]
*** 45,50 ****
--- 45,51 ----
  	2,							/* DO_FUNC */
  	3,							/* DO_AGG */
  	3,							/* DO_OPERATOR */
+ 	3,							/* DO_ACCESS_METHOD */
  	4,							/* DO_OPCLASS */
  	4,							/* DO_OPFAMILY */
  	4,							/* DO_COLLATION */
*************** static const int newObjectTypePriority[]
*** 95,100 ****
--- 96,102 ----
  	6,							/* DO_FUNC */
  	7,							/* DO_AGG */
  	8,							/* DO_OPERATOR */
+ 	8,							/* DO_ACCESS_METHOD */
  	9,							/* DO_OPCLASS */
  	9,							/* DO_OPFAMILY */
  	3,							/* DO_COLLATION */
*************** describeDumpableObject(DumpableObject *o
*** 1325,1330 ****
--- 1327,1336 ----
  					 "OPERATOR %s  (ID %d OID %u)",
  					 obj->name, obj->dumpId, obj->catId.oid);
  			return;
+ 		case DO_ACCESS_METHOD:
+ 			snprintf(buf, bufsize,
+ 					 "");
+ 			return;
  		case DO_OPCLASS:
  			snprintf(buf, bufsize,
  					 "OPERATOR CLASS %s  (ID %d OID %u)",
diff --git a/src/include/catalog/dependency.h b/src/include/catalog/dependency.h
new file mode 100644
index 049bf9f..ac16740
*** a/src/include/catalog/dependency.h
--- b/src/include/catalog/dependency.h
*************** typedef enum ObjectClass
*** 153,162 ****
  	OCLASS_EXTENSION,			/* pg_extension */
  	OCLASS_EVENT_TRIGGER,		/* pg_event_trigger */
  	OCLASS_POLICY,				/* pg_policy */
! 	OCLASS_TRANSFORM			/* pg_transform */
  } ObjectClass;
  
! #define LAST_OCLASS		OCLASS_TRANSFORM
  
  
  /* in dependency.c */
--- 153,163 ----
  	OCLASS_EXTENSION,			/* pg_extension */
  	OCLASS_EVENT_TRIGGER,		/* pg_event_trigger */
  	OCLASS_POLICY,				/* pg_policy */
! 	OCLASS_TRANSFORM,			/* pg_transform */
! 	OCLASS_AM,					/* pg_am */
  } ObjectClass;
  
! #define LAST_OCLASS		OCLASS_AM
  
  
  /* in dependency.c */
diff --git a/src/include/commands/defrem.h b/src/include/commands/defrem.h
new file mode 100644
index 54f67e9..2ba24df
*** a/src/include/commands/defrem.h
--- b/src/include/commands/defrem.h
*************** extern Datum transformGenericOptions(Oid
*** 137,142 ****
--- 137,146 ----
  						List *options,
  						Oid fdwvalidator);
  
+ /* commands/amcmds.c */
+ extern ObjectAddress CreateAccessMethod(CreateAmStmt *stmt);
+ extern void RemoveAccessMethodById(Oid amOid);
+ 
  /* support routines in commands/define.c */
  
  extern char *defGetString(DefElem *def);
diff --git a/src/include/nodes/nodes.h b/src/include/nodes/nodes.h
new file mode 100644
index cf09db4..6fb349f
*** a/src/include/nodes/nodes.h
--- b/src/include/nodes/nodes.h
*************** typedef enum NodeTag
*** 381,386 ****
--- 381,387 ----
  	T_CreatePolicyStmt,
  	T_AlterPolicyStmt,
  	T_CreateTransformStmt,
+ 	T_CreateAmStmt,
  
  	/*
  	 * TAGS FOR PARSE TREE NODES (parsenodes.h)
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
new file mode 100644
index 2fd0629..8421d41
*** a/src/include/nodes/parsenodes.h
--- b/src/include/nodes/parsenodes.h
*************** typedef struct SetOperationStmt
*** 1379,1384 ****
--- 1379,1385 ----
  
  typedef enum ObjectType
  {
+ 	OBJECT_ACCESS_METHOD,
  	OBJECT_AGGREGATE,
  	OBJECT_AMOP,
  	OBJECT_AMPROC,
*************** typedef struct AlterPolicyStmt
*** 2070,2075 ****
--- 2071,2087 ----
  	Node	   *with_check;		/* the policy's WITH CHECK condition. */
  } AlterPolicyStmt;
  
+ /*----------------------
+  *		Create ACCESS METHOD Statement
+  *----------------------
+  */
+ typedef struct CreateAmStmt
+ {
+ 	NodeTag		type;
+ 	char	   *amname;			/* access method name */
+ 	List	   *handler_name;	/* handler function name */
+ } CreateAmStmt;
+ 
  /* ----------------------
   *		Create TRIGGER Statement
   * ----------------------
diff --git a/src/include/parser/kwlist.h b/src/include/parser/kwlist.h
new file mode 100644
index 6e1e820..7de3404
*** a/src/include/parser/kwlist.h
--- b/src/include/parser/kwlist.h
*************** PG_KEYWORD("mapping", MAPPING, UNRESERVE
*** 239,244 ****
--- 239,245 ----
  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/selfuncs.h b/src/include/utils/selfuncs.h
new file mode 100644
index 06fbca7..7fb7466
*** a/src/include/utils/selfuncs.h
--- b/src/include/utils/selfuncs.h
*************** typedef enum
*** 95,100 ****
--- 95,142 ----
  	Pattern_Prefix_None, Pattern_Prefix_Partial, Pattern_Prefix_Exact
  } Pattern_Prefix_Status;
  
+ /*
+  * deconstruct_indexquals is a simple function to examine the indexquals
+  * attached to a proposed IndexPath.  It returns a list of IndexQualInfo
+  * structs, one per qual expression.
+  */
+ typedef struct
+ {
+ 	RestrictInfo *rinfo;		/* the indexqual itself */
+ 	int			indexcol;		/* zero-based index column number */
+ 	bool		varonleft;		/* true if index column is on left of qual */
+ 	Oid			clause_op;		/* qual's operator OID, if relevant */
+ 	Node	   *other_operand;	/* non-index operand of qual's operator */
+ } IndexQualInfo;
+ 
+ /*
+  * genericcostestimate is a general-purpose estimator that can be used for
+  * most index types.  In some cases we use genericcostestimate as the base
+  * code and then incorporate additional index-type-specific knowledge in
+  * the type-specific calling function.  To avoid code duplication, we make
+  * genericcostestimate return a number of intermediate values as well as
+  * its preliminary estimates of the output cost values.  The GenericCosts
+  * struct includes all these values.
+  *
+  * Callers should initialize all fields of GenericCosts to zero.  In addition,
+  * they can set numIndexTuples to some positive value if they have a better
+  * than default way of estimating the number of leaf index tuples visited.
+  */
+ typedef struct
+ {
+ 	/* These are the values the cost estimator must return to the planner */
+ 	Cost		indexStartupCost;		/* index-related startup cost */
+ 	Cost		indexTotalCost; /* total index-related scan cost */
+ 	Selectivity indexSelectivity;		/* selectivity of index */
+ 	double		indexCorrelation;		/* order correlation of index */
+ 
+ 	/* Intermediate values we obtain along the way */
+ 	double		numIndexPages;	/* number of leaf pages visited */
+ 	double		numIndexTuples; /* number of leaf tuples visited */
+ 	double		spc_random_page_cost;	/* relevant random_page_cost value */
+ 	double		num_sa_scans;	/* # indexscans from ScalarArrayOps */
+ } GenericCosts;
+ 
  /* Hooks for plugins to get control when we ask for stats */
  typedef bool (*get_relation_stats_hook_type) (PlannerInfo *root,
  														  RangeTblEntry *rte,
*************** extern double estimate_num_groups(Planne
*** 191,196 ****
--- 233,244 ----
  extern Selectivity estimate_hash_bucketsize(PlannerInfo *root, Node *hashkey,
  						 double nbuckets);
  
+ extern List *deconstruct_indexquals(IndexPath *path);
+ extern void genericcostestimate(PlannerInfo *root, IndexPath *path,
+ 								double loop_count,
+ 								List *qinfos,
+ 								GenericCosts *costs);
+ 
  /* Functions in array_selfuncs.c */
  
  extern Selectivity scalararraysel_containment(PlannerInfo *root,
