From feef921584489c4787f87d50c93eeddac10aefb3 Mon Sep 17 00:00:00 2001
From: Petr Jelinek <pjmodos@pjmodos.net>
Date: Sun, 15 Feb 2015 03:00:24 +0100
Subject: [PATCH 2/3] seqam ddl v3

---
 doc/src/sgml/catalogs.sgml           |   6 +
 doc/src/sgml/ref/allfiles.sgml       |   2 +
 doc/src/sgml/ref/create_seqam.sgml   | 163 ++++++++++++++++++
 doc/src/sgml/ref/drop_seqam.sgml     |  87 ++++++++++
 doc/src/sgml/reference.sgml          |   2 +
 src/backend/access/sequence/seqam.c  | 313 +++++++++++++++++++++++++++++++++++
 src/backend/catalog/dependency.c     |  11 +-
 src/backend/catalog/objectaddress.c  |  66 +++++++-
 src/backend/commands/dropcmds.c      |   4 +
 src/backend/commands/event_trigger.c |   3 +
 src/backend/commands/sequence.c      |  17 ++
 src/backend/parser/gram.y            |  13 +-
 src/backend/tcop/utility.c           |  12 ++
 src/bin/pg_dump/common.c             |   5 +
 src/bin/pg_dump/pg_dump.c            | 158 +++++++++++++++++-
 src/bin/pg_dump/pg_dump.h            |   9 +-
 src/bin/pg_dump/pg_dump_sort.c       |  11 +-
 src/include/access/seqam.h           |   3 +
 src/include/catalog/dependency.h     |   1 +
 src/include/nodes/parsenodes.h       |   1 +
 src/include/parser/kwlist.h          |   1 +
 21 files changed, 880 insertions(+), 8 deletions(-)
 create mode 100644 doc/src/sgml/ref/create_seqam.sgml
 create mode 100644 doc/src/sgml/ref/drop_seqam.sgml

diff --git a/doc/src/sgml/catalogs.sgml b/doc/src/sgml/catalogs.sgml
index 9e27980..4f8c784 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -5539,6 +5539,12 @@
    installed on the system.
   </para>
 
+  <para>
+   The contents of this catalog can be manipulated by
+   <command>CREATE ACCESS METHOD FOR SEQUENCES</> and
+   <command>DROP ACCESS METHOD FOR SEQUENCES</>.
+  </para>
+
   <table>
    <title><structname>pg_seqam</> Columns</title>
 
diff --git a/doc/src/sgml/ref/allfiles.sgml b/doc/src/sgml/ref/allfiles.sgml
index 7aa3128..2e4a250 100644
--- a/doc/src/sgml/ref/allfiles.sgml
+++ b/doc/src/sgml/ref/allfiles.sgml
@@ -74,6 +74,7 @@ Complete list of usable sgml source files in this directory.
 <!ENTITY createRole         SYSTEM "create_role.sgml">
 <!ENTITY createRule         SYSTEM "create_rule.sgml">
 <!ENTITY createSchema       SYSTEM "create_schema.sgml">
+<!ENTITY createSeqAM        SYSTEM "create_seqam.sgml">
 <!ENTITY createSequence     SYSTEM "create_sequence.sgml">
 <!ENTITY createServer       SYSTEM "create_server.sgml">
 <!ENTITY createTable        SYSTEM "create_table.sgml">
@@ -116,6 +117,7 @@ Complete list of usable sgml source files in this directory.
 <!ENTITY dropRole           SYSTEM "drop_role.sgml">
 <!ENTITY dropRule           SYSTEM "drop_rule.sgml">
 <!ENTITY dropSchema         SYSTEM "drop_schema.sgml">
+<!ENTITY dropSeqAM          SYSTEM "drop_seqam.sgml">
 <!ENTITY dropSequence       SYSTEM "drop_sequence.sgml">
 <!ENTITY dropServer         SYSTEM "drop_server.sgml">
 <!ENTITY dropTable          SYSTEM "drop_table.sgml">
diff --git a/doc/src/sgml/ref/create_seqam.sgml b/doc/src/sgml/ref/create_seqam.sgml
new file mode 100644
index 0000000..e95409f
--- /dev/null
+++ b/doc/src/sgml/ref/create_seqam.sgml
@@ -0,0 +1,163 @@
+<!--
+doc/src/sgml/ref/create_seqam.sgml
+PostgreSQL documentation
+-->
+
+<refentry id="SQL-CREATESEQAM">
+ <indexterm zone="sql-createseqam">
+  <primary>CREATE ACCESS METHOD FOR SEQUENCES</primary>
+ </indexterm>
+
+ <refmeta>
+  <refentrytitle>CREATE ACCESS METHOD FOR SEQUENCES</refentrytitle>
+  <manvolnum>7</manvolnum>
+  <refmiscinfo>SQL - Language Statements</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+  <refname>CREATE ACCESS METHOD FOR SEQUENCES</refname>
+  <refpurpose>define custom sequence access method</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+<synopsis>
+CREATE ACCESS METHOD FOR SEQUENCES <replaceable class="parameter">name</replaceable> (
+    RELOPTIONS = <replaceable class="parameter">reloptions_function</replaceable> ,
+    INIT = <replaceable class="parameter">init_function</replaceable> ,
+    ALLOC = <replaceable class="parameter">alloc_function</replaceable> ,
+    SETVAL = <replaceable class="parameter">setval_function</replaceable> ,
+    GETSTATE = <replaceable class="parameter">getstate_function</replaceable>,
+    SETSTATE = <replaceable class="parameter">setstate_function</replaceable>
+)
+</synopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+  <title>Description</title>
+
+  <para>
+   <command>CREATE ACCESS METHOD FOR SEQUENCES</command> creates a sequence
+   access method. A sequence access method changes how values for SEQUENCEs
+   are generated.
+  </para>
+
+  <para>
+   You must be a superuser to use <command>CREATE ACCESS METHOD FOR SEQUENCES</command>.
+  </para>
+ </refsect1>
+
+ <refsect1>
+  <title>Parameters</title>
+
+  <variablelist>
+   <varlistentry>
+    <term><replaceable class="parameter">name</replaceable></term>
+    <listitem>
+     <para>
+      The name of the sequence access method to be created. This name must be
+      unique within the database.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term><replaceable class="parameter">reloptions_function</replaceable></term>
+    <listitem>
+     <para>
+      The name of the function for parsing reloptions for the sequence access
+      method.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term><replaceable class="parameter">init_function</replaceable></term>
+    <listitem>
+     <para>
+      The name of the init function for the sequence access method.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term><replaceable class="parameter">alloc_function</replaceable></term>
+    <listitem>
+     <para>
+      The name of the function which allocates new sequence id.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term><replaceable class="parameter">setval_function</replaceable></term>
+    <listitem>
+     <para>
+      The name of the function which handles the <function>setval</function>
+      function call.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term><replaceable class="parameter">getstate_function</replaceable></term>
+    <listitem>
+     <para>
+      The name of the function used for dumping current state of the sequence
+      to a string. This function will be called by
+      <application>pg_dump</application>.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term><replaceable class="parameter">setstate_function</replaceable></term>
+    <listitem>
+     <para>
+      The name of the function used for restoring the state of the sequence
+      from a string. Calls to this function will be present in a database dumps
+      created by <application>pg_dump</application>.
+     </para>
+    </listitem>
+   </varlistentry>
+
+  </variablelist>
+
+  <para>
+   The function names can be schema-qualified if necessary.  Argument types
+   are not given, since the argument list for each type of function is
+   predetermined.  All functions are required.
+  </para>
+
+  <para>
+   The arguments can appear in any order, not only the one shown above.
+  </para>
+ </refsect1>
+
+ <refsect1>
+  <title>Examples</title>
+
+  <para>
+   See the <filename>contrib/gapless_seq</> for example on how to write new
+   sequence access methods and how to use this command.
+  </para>
+
+ </refsect1>
+
+ <refsect1>
+  <title>Compatibility</title>
+
+  <para>
+   There is no
+   <command>CREATE ACCESS METHOD FOR SEQUENCES</command> statement in the SQL
+   standard.
+  </para>
+ </refsect1>
+
+ <refsect1>
+  <title>See Also</title>
+
+  <simplelist type="inline">
+   <member><xref linkend="sql-dropseqam"></member>
+  </simplelist>
+ </refsect1>
+</refentry>
diff --git a/doc/src/sgml/ref/drop_seqam.sgml b/doc/src/sgml/ref/drop_seqam.sgml
new file mode 100644
index 0000000..959b777
--- /dev/null
+++ b/doc/src/sgml/ref/drop_seqam.sgml
@@ -0,0 +1,87 @@
+<!--
+doc/src/sgml/ref/drop_seqam.sgml
+PostgreSQL documentation
+-->
+
+<refentry id="SQL-DROPSEQAM">
+ <indexterm zone="sql-dropseqam">
+  <primary>DROP ACCESS METHOD FOR SEQUENCES</primary>
+ </indexterm>
+
+ <refmeta>
+  <refentrytitle>DROP ACCESS METHOD FOR SEQUENCES</refentrytitle>
+  <manvolnum>7</manvolnum>
+  <refmiscinfo>SQL - Language Statements</refmiscinfo>
+ </refmeta>
+
+ <refnamediv>
+  <refname>DROP ACCESS METHOD FOR SEQUENCES</refname>
+  <refpurpose>remove a custom sequence access method</refpurpose>
+ </refnamediv>
+
+ <refsynopsisdiv>
+<synopsis>
+DROP ACCESS METHOD FOR SEQUENCES [ IF EXISTS ] <replaceable class="parameter">name</replaceable>
+</synopsis>
+ </refsynopsisdiv>
+
+ <refsect1>
+  <title>Description</title>
+
+  <para>
+   <command>DROP ACCESS METHOD FOR SEQUENCES</command> drop an existing
+   sequence access method.
+  </para>
+
+  <para>
+   You must be a superuser to use the
+   <command>DROP ACCESS METHOD FOR SEQUENCES</command>.
+  </para>
+ </refsect1>
+
+ <refsect1>
+  <title>Parameters</title>
+
+  <variablelist>
+
+   <varlistentry>
+    <term><literal>IF EXISTS</literal></term>
+    <listitem>
+     <para>
+      Do not throw an error if the sequence access method does not exist.
+      A notice is issued in this case.
+     </para>
+    </listitem>
+   </varlistentry>
+
+   <varlistentry>
+    <term><replaceable class="parameter">name</replaceable></term>
+    <listitem>
+     <para>
+      The name of an existing sequence access method to be removed.
+     </para>
+    </listitem>
+   </varlistentry>
+
+  </variablelist>
+
+ </refsect1>
+
+ <refsect1>
+  <title>Compatibility</title>
+
+  <para>
+   There is no
+   <command>DDROP ACCESS METHOD FOR SEQUENCES</command> statement in the SQL
+   standard.
+  </para>
+ </refsect1>
+
+ <refsect1>
+  <title>See Also</title>
+
+  <simplelist type="inline">
+   <member><xref linkend="sql-createseqam"></member>
+  </simplelist>
+ </refsect1>
+</refentry>
diff --git a/doc/src/sgml/reference.sgml b/doc/src/sgml/reference.sgml
index 10c9a6d..aeff87e 100644
--- a/doc/src/sgml/reference.sgml
+++ b/doc/src/sgml/reference.sgml
@@ -102,6 +102,7 @@
    &createRole;
    &createRule;
    &createSchema;
+   &createSeqAM;
    &createSequence;
    &createServer;
    &createTable;
@@ -144,6 +145,7 @@
    &dropRole;
    &dropRule;
    &dropSchema;
+   &dropSeqAM;
    &dropSequence;
    &dropServer;
    &dropTable;
diff --git a/src/backend/access/sequence/seqam.c b/src/backend/access/sequence/seqam.c
index 6292a1b..d332190 100644
--- a/src/backend/access/sequence/seqam.c
+++ b/src/backend/access/sequence/seqam.c
@@ -67,8 +67,20 @@
 #include "access/relscan.h"
 #include "access/transam.h"
 #include "access/xact.h"
+#include "catalog/dependency.h"
+#include "catalog/objectaccess.h"
+#include "catalog/objectaddress.h"
+#include "catalog/indexing.h"
+#include "catalog/pg_proc.h"
 #include "catalog/pg_seqam.h"
+#include "catalog/pg_type.h"
+#include "commands/defrem.h"
+#include "miscadmin.h"
+#include "parser/parse_func.h"
+#include "parser/parse_type.h"
+#include "utils/builtins.h"
 #include "utils/guc.h"
+#include "utils/lsyscache.h"
 #include "utils/rel.h"
 #include "utils/syscache.h"
 
@@ -348,6 +360,307 @@ check_serial_seqam(char **newval, void **extra, GucSource source)
 
 
 /*
+ * Find seqam function by name and validate it.
+ */
+static Datum
+get_seqam_func(DefElem *defel, int attnum)
+{
+	List	   *funcName = defGetQualifiedName(defel);
+	Oid			typeId[6];
+	Oid			retTypeId;
+	int			nargs;
+	Oid			procOid;
+
+	typeId[0] = INTERNALOID;
+
+	switch (attnum)
+	{
+		case Anum_pg_seqam_seqamreloptions:
+			nargs = 2;
+			typeId[1] = BOOLOID;
+			retTypeId = BYTEAOID;
+			break;
+
+		case Anum_pg_seqam_seqaminit:
+			nargs = 5;
+			typeId[0] = OIDOID;
+			typeId[1] = INTERNALOID;
+			typeId[2] = BYTEAOID;
+			typeId[3] = INTERNALOID;
+			typeId[4] = INTERNALOID;
+			retTypeId = VOIDOID;
+			break;
+
+		case Anum_pg_seqam_seqamalloc:
+			nargs = 4;
+			typeId[1] = INTERNALOID;
+			typeId[2] = INT8OID;
+			typeId[3] = INTERNALOID;
+			retTypeId = INT8OID;
+			break;
+
+		case Anum_pg_seqam_seqamsetval:
+			nargs = 3;
+			typeId[1] = INTERNALOID;
+			typeId[2] = INT8OID;
+			retTypeId = VOIDOID;
+			break;
+
+		case Anum_pg_seqam_seqamgetstate:
+			nargs = 4;
+			typeId[1] = INTERNALOID;
+			typeId[2] = INTERNALOID;
+			typeId[3] = INTERNALOID;
+			retTypeId = INT4OID;
+			break;
+
+		case Anum_pg_seqam_seqamsetstate:
+			nargs = 5;
+			typeId[1] = INTERNALOID;
+			typeId[2] = INTERNALOID;
+			typeId[3] = INTERNALOID;
+			typeId[4] = INT4OID;
+			retTypeId = VOIDOID;
+			break;
+
+		default:
+			/* should not be here */
+			elog(ERROR, "unrecognized attribute for sequence access method: %d",
+				 attnum);
+			nargs = 0;			/* keep compiler quiet */
+	}
+
+	procOid = LookupFuncName(funcName, nargs, typeId, false);
+	if (get_func_rettype(procOid) != retTypeId)
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+				 errmsg("function %s should return type %s",
+						func_signature_string(funcName, nargs, NIL, typeId),
+						format_type_be(retTypeId))));
+
+	return ObjectIdGetDatum(procOid);
+}
+
+
+/*
+ * make pg_depend entries for a new pg_seqam entry
+ */
+static void
+makeSeqAMDependencies(HeapTuple tuple)
+{
+	Form_pg_seqam	seqam = (Form_pg_seqam) GETSTRUCT(tuple);
+	ObjectAddress	myself,
+					referenced;
+
+
+	myself.classId = SeqAccessMethodRelationId;
+	myself.objectId = HeapTupleGetOid(tuple);
+	myself.objectSubId = 0;
+
+	/* Dependency on extension. */
+	recordDependencyOnCurrentExtension(&myself, false);
+
+	/* Dependencies on functions. */
+	referenced.classId = ProcedureRelationId;
+	referenced.objectSubId = 0;
+
+	referenced.objectId = seqam->seqamreloptions;
+	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
+	referenced.objectId = seqam->seqaminit;
+	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
+	referenced.objectId = seqam->seqamalloc;
+	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
+	referenced.objectId = seqam->seqamsetval;
+	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
+	referenced.objectId = seqam->seqamgetstate;
+	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+
+	referenced.objectId = seqam->seqamsetstate;
+	recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
+}
+
+/*
+ * Create a sequence access method record in pg_seqam catalog.
+ *
+ * Only superusers can create a sequence access methods.
+ */
+Oid
+DefineSeqAM(List *names, List* definition)
+{
+	char	   *seqamname = strVal(linitial(names));
+	Oid			seqamoid;
+	ListCell   *pl;
+	Relation	rel;
+	Datum		values[Natts_pg_seqam];
+	bool		nulls[Natts_pg_seqam];
+	HeapTuple	tuple;
+
+	/* Must be super user. */
+	if (!superuser())
+		ereport(ERROR,
+				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+				 errmsg("permission denied to create sequence access method \"%s\"",
+						seqamname),
+				 errhint("Must be superuser to create a sequence access method.")));
+
+	/* Must not already exist. */
+	seqamoid = get_seqam_oid(seqamname, true);
+	if (OidIsValid(seqamoid))
+		ereport(ERROR,
+				(errcode(ERRCODE_UNDEFINED_OBJECT),
+				 errmsg("sequence access method \"%s\" already exists",
+						seqamname)));
+
+	/* Initialize the values. */
+	memset(values, 0, sizeof(values));
+	memset(nulls, false, sizeof(nulls));
+
+	values[Anum_pg_seqam_seqamname - 1] =
+		DirectFunctionCall1(namein, CStringGetDatum(seqamname));
+
+	/*
+	 * Loop over the definition list and extract the information we need.
+	 */
+	foreach(pl, definition)
+	{
+		DefElem    *defel = (DefElem *) lfirst(pl);
+
+		if (pg_strcasecmp(defel->defname, "reloptions") == 0)
+		{
+			values[Anum_pg_seqam_seqamreloptions - 1] =
+				get_seqam_func(defel, Anum_pg_seqam_seqamreloptions);
+		}
+		else if (pg_strcasecmp(defel->defname, "init") == 0)
+		{
+			values[Anum_pg_seqam_seqaminit - 1] =
+				get_seqam_func(defel, Anum_pg_seqam_seqaminit);
+		}
+		else if (pg_strcasecmp(defel->defname, "alloc") == 0)
+		{
+			values[Anum_pg_seqam_seqamalloc - 1] =
+				get_seqam_func(defel, Anum_pg_seqam_seqamalloc);
+		}
+		else if (pg_strcasecmp(defel->defname, "setval") == 0)
+		{
+			values[Anum_pg_seqam_seqamsetval - 1] =
+				get_seqam_func(defel, Anum_pg_seqam_seqamsetval);
+		}
+		else if (pg_strcasecmp(defel->defname, "getstate") == 0)
+		{
+			values[Anum_pg_seqam_seqamgetstate - 1] =
+				get_seqam_func(defel, Anum_pg_seqam_seqamgetstate);
+		}
+		else if (pg_strcasecmp(defel->defname, "setstate") == 0)
+		{
+			values[Anum_pg_seqam_seqamsetstate - 1] =
+				get_seqam_func(defel, Anum_pg_seqam_seqamsetstate);
+		}
+		else
+			ereport(ERROR,
+					(errcode(ERRCODE_SYNTAX_ERROR),
+				 errmsg("sequence access method parameter \"%s\" not recognized",
+						defel->defname)));
+	}
+
+	/*
+	 * Validation.
+	 */
+	if (!OidIsValid(DatumGetObjectId(values[Anum_pg_seqam_seqamreloptions - 1])))
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+				 errmsg("sequence access method reloptions function is required")));
+
+	if (!OidIsValid(DatumGetObjectId(values[Anum_pg_seqam_seqaminit - 1])))
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+				 errmsg("sequence access method init function is required")));
+
+	if (!OidIsValid(DatumGetObjectId(values[Anum_pg_seqam_seqamalloc - 1])))
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+				 errmsg("sequence access method alloc function is required")));
+
+	if (!OidIsValid(DatumGetObjectId(values[Anum_pg_seqam_seqamsetval - 1])))
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+				 errmsg("sequence access method setval function is required")));
+
+	if (!OidIsValid(DatumGetObjectId(values[Anum_pg_seqam_seqamgetstate - 1])))
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+				 errmsg("sequence access method getstate function is required")));
+
+	if (!OidIsValid(DatumGetObjectId(values[Anum_pg_seqam_seqamsetstate - 1])))
+		ereport(ERROR,
+				(errcode(ERRCODE_INVALID_OBJECT_DEFINITION),
+				 errmsg("sequence access method setstate function is required")));
+
+	/*
+	 * Insert tuple into pg_seqam.
+	 */
+	rel = heap_open(SeqAccessMethodRelationId, RowExclusiveLock);
+
+	tuple = heap_form_tuple(rel->rd_att, values, nulls);
+
+	seqamoid = simple_heap_insert(rel, tuple);
+
+	CatalogUpdateIndexes(rel, tuple);
+
+	makeSeqAMDependencies(tuple);
+
+	heap_freetuple(tuple);
+
+	/* Post creation hook */
+	InvokeObjectPostCreateHook(SeqAccessMethodRelationId, seqamoid, 0);
+
+	heap_close(rel, RowExclusiveLock);
+
+	return seqamoid;
+}
+
+/*
+ * Drop a sequence access method.
+ */
+void
+RemoveSeqAMById(Oid seqamoid)
+{
+	Relation	rel;
+	HeapTuple	tuple;
+	Form_pg_seqam seqam;
+
+	/*
+	 * Find the target tuple
+	 */
+	rel = heap_open(SeqAccessMethodRelationId, RowExclusiveLock);
+
+	tuple = SearchSysCache1(SEQAMOID, ObjectIdGetDatum(seqamoid));
+	if (!HeapTupleIsValid(tuple))
+		elog(ERROR, "cache lookup failed for sequence access method %u",
+			 seqamoid);
+
+	seqam = (Form_pg_seqam) GETSTRUCT(tuple);
+	/* Can't drop builtin local sequence access method. */
+	if (seqamoid == LOCAL_SEQAM_OID)
+		ereport(ERROR,
+				(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
+				 errmsg("permission denied for sequence access method %s",
+						NameStr(seqam->seqamname))));
+
+	/*
+	 * Remove the pg_seqam tuple (this will roll back if we fail below)
+	 */
+	simple_heap_delete(rel, &tuple->t_self);
+
+	ReleaseSysCache(tuple);
+
+	heap_close(rel, RowExclusiveLock);
+}
+
+/*
  * get_seqam_oid - given a sequence AM name, look up the OID
  *
  * If missing_ok is false, throw an error if SeqAM name not found.  If true,
diff --git a/src/backend/catalog/dependency.c b/src/backend/catalog/dependency.c
index bacb242..9340798 100644
--- a/src/backend/catalog/dependency.c
+++ b/src/backend/catalog/dependency.c
@@ -16,6 +16,7 @@
 
 #include "access/htup_details.h"
 #include "access/xact.h"
+#include "access/seqam.h"
 #include "catalog/dependency.h"
 #include "catalog/heap.h"
 #include "catalog/index.h"
@@ -157,7 +158,8 @@ static const Oid object_classes[MAX_OCLASS] = {
 	DefaultAclRelationId,		/* OCLASS_DEFACL */
 	ExtensionRelationId,		/* OCLASS_EXTENSION */
 	EventTriggerRelationId,		/* OCLASS_EVENT_TRIGGER */
-	PolicyRelationId			/* OCLASS_POLICY */
+	PolicyRelationId,			/* OCLASS_POLICY */
+	SeqAccessMethodRelationId	/* OCLASS_SEQAM */
 };
 
 
@@ -1265,6 +1267,10 @@ doDeletion(const ObjectAddress *object, int flags)
 			RemovePolicyById(object->objectId);
 			break;
 
+		case OCLASS_SEQAM:
+			RemoveSeqAMById(object->objectId);
+			break;
+
 		default:
 			elog(ERROR, "unrecognized object class: %u",
 				 object->classId);
@@ -2373,6 +2379,9 @@ getObjectClass(const ObjectAddress *object)
 
 		case PolicyRelationId:
 			return OCLASS_POLICY;
+
+		case SeqAccessMethodRelationId:
+			return OCLASS_SEQAM;
 	}
 
 	/* shouldn't get here */
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
index 2412a24..decbd12 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -430,6 +430,18 @@ static const ObjectPropertyType ObjectProperty[] =
 		Anum_pg_type_typacl,
 		ACL_KIND_TYPE,
 		true
+	},
+	{
+		SeqAccessMethodRelationId,
+		SeqAMOidIndexId,
+		SEQAMOID,
+		SEQAMNAME,
+		Anum_pg_seqam_seqamname,
+		InvalidAttrNumber,
+		InvalidAttrNumber,
+		InvalidAttrNumber,
+		-1,
+		true
 	}
 };
 
@@ -529,7 +541,9 @@ ObjectTypeMap[] =
 	/* OCLASS_EVENT_TRIGGER */
 	{ "event trigger", OBJECT_EVENT_TRIGGER },
 	/* OCLASS_POLICY */
-	{ "policy", OBJECT_POLICY }
+	{ "policy", OBJECT_POLICY },
+	/* OCLASS_SEQAM */
+	{ "sequence access method", OBJECT_SEQAM }
 };
 
 
@@ -671,6 +685,7 @@ get_object_address(ObjectType objtype, List *objname, List *objargs,
 			case OBJECT_FDW:
 			case OBJECT_FOREIGN_SERVER:
 			case OBJECT_EVENT_TRIGGER:
+			case OBJECT_SEQAM:
 				address = get_object_address_unqualified(objtype,
 														 objname, missing_ok);
 				break;
@@ -897,6 +912,9 @@ get_object_address_unqualified(ObjectType objtype,
 			case OBJECT_EVENT_TRIGGER:
 				msg = gettext_noop("event trigger name cannot be qualified");
 				break;
+			case OBJECT_SEQAM:
+				msg = gettext_noop("sequence access method name cannot be qualified");
+				break;
 			default:
 				elog(ERROR, "unrecognized objtype: %d", (int) objtype);
 				msg = NULL;		/* placate compiler */
@@ -957,6 +975,11 @@ get_object_address_unqualified(ObjectType objtype,
 			address.objectId = get_event_trigger_oid(name, missing_ok);
 			address.objectSubId = 0;
 			break;
+		case OBJECT_SEQAM:
+			address.classId = SeqAccessMethodRelationId;
+			address.objectId = get_seqam_oid(name, missing_ok);
+			address.objectSubId = 0;
+			break;
 		default:
 			elog(ERROR, "unrecognized objtype: %d", (int) objtype);
 			/* placate compiler, which doesn't know elog won't return */
@@ -1721,6 +1744,7 @@ check_object_ownership(Oid roleid, ObjectType objtype, ObjectAddress address,
 			break;
 		case OBJECT_TSPARSER:
 		case OBJECT_TSTEMPLATE:
+		case OBJECT_SEQAM:
 			/* We treat these object types as being owned by superusers */
 			if (!superuser_arg(roleid))
 				ereport(ERROR,
@@ -2655,6 +2679,21 @@ getObjectDescription(const ObjectAddress *object)
 				break;
 			}
 
+		case OCLASS_SEQAM:
+			{
+				HeapTuple	tup;
+
+				tup = SearchSysCache1(SEQAMOID,
+									  ObjectIdGetDatum(object->objectId));
+				if (!HeapTupleIsValid(tup))
+					elog(ERROR, "cache lookup failed for sequence access method %u",
+						 object->objectId);
+				appendStringInfo(&buffer, _("sequence access method %s"),
+						NameStr(((Form_pg_seqam) GETSTRUCT(tup))->seqamname));
+				ReleaseSysCache(tup);
+				break;
+			}
+
 		default:
 			appendStringInfo(&buffer, "unrecognized object %u %u %d",
 							 object->classId,
@@ -3132,6 +3171,10 @@ getObjectTypeDescription(const ObjectAddress *object)
 			appendStringInfoString(&buffer, "policy");
 			break;
 
+		case OCLASS_SEQAM:
+			appendStringInfoString(&buffer, "sequence access method");
+			break;
+
 		default:
 			appendStringInfo(&buffer, "unrecognized %u", object->classId);
 			break;
@@ -4026,6 +4069,27 @@ getObjectIdentityParts(const ObjectAddress *object,
 				break;
 			}
 
+		case OCLASS_SEQAM:
+			{
+				char	   *seqamname;
+				HeapTuple	tup;
+				Form_pg_seqam seqamForm;
+
+				tup = SearchSysCache1(SEQAMOID,
+									  ObjectIdGetDatum(object->objectId));
+				if (!HeapTupleIsValid(tup))
+					elog(ERROR, "cache lookup failed for sequence access method %u",
+						 object->objectId);
+				seqamForm = (Form_pg_seqam) GETSTRUCT(tup);
+				seqamname = pstrdup(NameStr(seqamForm->seqamname));
+				ReleaseSysCache(tup);
+				appendStringInfoString(&buffer,
+							   quote_identifier(seqamname));
+				if (objname)
+					*objname = list_make1(seqamname);
+				break;
+			}
+
 		default:
 			appendStringInfo(&buffer, "unrecognized object %u %u %d",
 							 object->classId,
diff --git a/src/backend/commands/dropcmds.c b/src/backend/commands/dropcmds.c
index e5185ba..01d772a 100644
--- a/src/backend/commands/dropcmds.c
+++ b/src/backend/commands/dropcmds.c
@@ -421,6 +421,10 @@ does_not_exist_skipping(ObjectType objtype, List *objname, List *objargs)
 				args = strVal(linitial(objargs));
 			}
 			break;
+		case OBJECT_SEQAM:
+			msg = gettext_noop("sequence access method \"%s\" does not exist, skipping");
+			name = NameListToString(objname);
+			break;
 		default:
 			elog(ERROR, "unexpected object type (%d)", (int) objtype);
 			break;
diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c
index a33a5ad..0c4d63e 100644
--- a/src/backend/commands/event_trigger.c
+++ b/src/backend/commands/event_trigger.c
@@ -72,6 +72,7 @@ typedef enum
 } event_trigger_command_tag_check_result;
 
 static event_trigger_support_data event_trigger_support[] = {
+	{"ACCESS METHOD FOR SEQUENCES", true},
 	{"AGGREGATE", true},
 	{"CAST", true},
 	{"CONSTRAINT", true},
@@ -1075,6 +1076,7 @@ EventTriggerSupportsObjectType(ObjectType obtype)
 		case OBJECT_POLICY:
 		case OBJECT_RULE:
 		case OBJECT_SCHEMA:
+		case OBJECT_SEQAM:
 		case OBJECT_SEQUENCE:
 		case OBJECT_TABCONSTRAINT:
 		case OBJECT_TABLE:
@@ -1134,6 +1136,7 @@ EventTriggerSupportsObjectClass(ObjectClass objclass)
 		case OCLASS_DEFACL:
 		case OCLASS_EXTENSION:
 		case OCLASS_POLICY:
+		case OCLASS_SEQAM:
 			return true;
 
 		case MAX_OCLASS:
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c
index bfa42da..8521edd 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -1618,9 +1618,26 @@ seqrel_update_relam(Oid seqoid, Oid seqamid)
 
 	if (pgcform->relam != seqamid)
 	{
+		ObjectAddress	myself,
+						referenced;
+
 		pgcform->relam = seqamid;
 		simple_heap_update(rd, &ctup->t_self, ctup);
 		CatalogUpdateIndexes(rd, ctup);
+
+		/* Remove dependency on previous SeqAM */
+		deleteDependencyRecordsForClass(RelationRelationId, seqoid,
+										SeqAccessMethodRelationId,
+										DEPENDENCY_NORMAL);
+
+		/* Record dependency on new SeqAM */
+		myself.classId = RelationRelationId;
+		myself.objectId = seqoid;
+		myself.objectSubId = 0;
+		referenced.classId = SeqAccessMethodRelationId;
+		referenced.objectId = seqamid;
+		referenced.objectSubId = 0;
+		recordDependencyOn(&myself, &referenced, DEPENDENCY_NORMAL);
 	}
 
 	heap_freetuple(ctup);
diff --git a/src/backend/parser/gram.y b/src/backend/parser/gram.y
index 8d6a402..d5cab3c 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -586,7 +586,8 @@ 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
@@ -5167,6 +5168,14 @@ DefineStmt:
 					n->definition = list_make1(makeDefElem("from", (Node *) $5));
 					$$ = (Node *)n;
 				}
+			| CREATE ACCESS METHOD FOR SEQUENCES name AS definition
+				{
+					DefineStmt *n = makeNode(DefineStmt);
+					n->kind = OBJECT_SEQAM;
+					n->defnames = list_make1(makeString($6));
+					n->definition = $8;
+					$$ = (Node *)n;
+				}
 		;
 
 definition: '(' def_list ')'						{ $$ = $2; }
@@ -5625,6 +5634,7 @@ drop_type:	TABLE									{ $$ = OBJECT_TABLE; }
 			| TEXT_P SEARCH DICTIONARY				{ $$ = OBJECT_TSDICTIONARY; }
 			| TEXT_P SEARCH TEMPLATE				{ $$ = OBJECT_TSTEMPLATE; }
 			| TEXT_P SEARCH CONFIGURATION			{ $$ = OBJECT_TSCONFIGURATION; }
+			| ACCESS METHOD FOR SEQUENCES 			{ $$ = OBJECT_SEQAM; }
 		;
 
 any_name_list:
@@ -13356,6 +13366,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 3533cfa..447be02 100644
--- a/src/backend/tcop/utility.c
+++ b/src/backend/tcop/utility.c
@@ -18,6 +18,7 @@
 
 #include "access/htup_details.h"
 #include "access/reloptions.h"
+#include "access/seqam.h"
 #include "access/twophase.h"
 #include "access/xact.h"
 #include "access/xlog.h"
@@ -1106,6 +1107,11 @@ ProcessUtilitySlow(Node *parsetree,
 							Assert(stmt->args == NIL);
 							DefineCollation(stmt->defnames, stmt->definition);
 							break;
+						case OBJECT_SEQAM:
+							Assert(list_length(stmt->defnames) == 1);
+							Assert(stmt->args == NIL);
+							DefineSeqAM(stmt->defnames, stmt->definition);
+							break;
 						default:
 							elog(ERROR, "unrecognized define stmt type: %d",
 								 (int) stmt->kind);
@@ -1960,6 +1966,9 @@ CreateCommandTag(Node *parsetree)
 				case OBJECT_POLICY:
 					tag = "DROP POLICY";
 					break;
+				case OBJECT_SEQAM:
+					tag = "DROP ACCESS METHOD FOR SEQUENCES";
+					break;
 				default:
 					tag = "???";
 			}
@@ -2056,6 +2065,9 @@ CreateCommandTag(Node *parsetree)
 				case OBJECT_COLLATION:
 					tag = "CREATE COLLATION";
 					break;
+				case OBJECT_SEQAM:
+					tag = "CREATE ACCESS METHOD FOR SEQUENCES";
+					break;
 				default:
 					tag = "???";
 			}
diff --git a/src/bin/pg_dump/common.c b/src/bin/pg_dump/common.c
index 1a0a587..7f272de 100644
--- a/src/bin/pg_dump/common.c
+++ b/src/bin/pg_dump/common.c
@@ -103,6 +103,7 @@ getSchemaData(Archive *fout, DumpOptions *dopt, int *numTablesPtr)
 	int			numForeignServers;
 	int			numDefaultACLs;
 	int			numEventTriggers;
+	int			numSeqAMs;
 
 	if (g_verbose)
 		write_msg(NULL, "reading schemas\n");
@@ -251,6 +252,10 @@ getSchemaData(Archive *fout, DumpOptions *dopt, int *numTablesPtr)
 		write_msg(NULL, "reading policies\n");
 	getPolicies(fout, tblinfo, numTables);
 
+	if (g_verbose)
+		write_msg(NULL, "reading sequence access methods\n");
+	getSeqAMs(fout, &numSeqAMs);
+
 	*numTablesPtr = numTables;
 	return tblinfo;
 }
diff --git a/src/bin/pg_dump/pg_dump.c b/src/bin/pg_dump/pg_dump.c
index f759fc5..3757767 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -178,6 +178,7 @@ static void dumpEventTrigger(Archive *fout, DumpOptions *dopt, EventTriggerInfo
 static void dumpTable(Archive *fout, DumpOptions *dopt, TableInfo *tbinfo);
 static void dumpTableSchema(Archive *fout, DumpOptions *dopt, TableInfo *tbinfo);
 static void dumpAttrDef(Archive *fout, DumpOptions *dopt, AttrDefInfo *adinfo);
+static void dumpSeqAM(Archive *fout, DumpOptions *dopt, SeqAMInfo *tbinfo);
 static void dumpSequence(Archive *fout, DumpOptions *dopt, TableInfo *tbinfo);
 static void dumpSequenceData(Archive *fout, TableDataInfo *tdinfo);
 static void dumpIndex(Archive *fout, DumpOptions *dopt, IndxInfo *indxinfo);
@@ -6035,6 +6036,71 @@ getRules(Archive *fout, int *numRules)
 }
 
 /*
+ * getSeqAMs:
+ *	  read all sequence access methods in the system catalogs and return them
+ *	  in the SeqAMInfo* structure
+ *
+ *	numSeqAMs is set to the number of access methods read in
+ */
+SeqAMInfo *
+getSeqAMs(Archive *fout, int *numSeqAMs)
+{
+	PGresult   *res;
+	int			ntups;
+	int			i;
+	PQExpBuffer query;
+	SeqAMInfo  *seqminfo;
+	int			i_tableoid,
+				i_oid,
+				i_seqamname;
+
+	/* Before 9.5, there were no sequence access methods */
+	if (fout->remoteVersion < 90500)
+	{
+		*numSeqAMs = 0;
+		return NULL;
+	}
+
+	query = createPQExpBuffer();
+
+	appendPQExpBuffer(query,
+					  "SELECT tableoid, oid, seqamname "
+					  "FROM pg_catalog.pg_seqam "
+					  "WHERE oid != '%u'::pg_catalog.oid",
+					  LOCAL_SEQAM_OID);
+
+	res = ExecuteSqlQuery(fout, query->data, PGRES_TUPLES_OK);
+
+	ntups = PQntuples(res);
+	*numSeqAMs = ntups;
+
+	seqminfo = (SeqAMInfo *) pg_malloc(ntups * sizeof(SeqAMInfo));
+
+	i_tableoid = PQfnumber(res, "tableoid");
+	i_oid = PQfnumber(res, "oid");
+	i_seqamname = PQfnumber(res, "seqamname");
+
+	for (i = 0; i < ntups; i++)
+	{
+		seqminfo[i].dobj.objType = DO_SEQAM;
+		seqminfo[i].dobj.catId.tableoid = atooid(PQgetvalue(res, i, i_tableoid));
+		seqminfo[i].dobj.catId.oid = atooid(PQgetvalue(res, i, i_oid));
+		AssignDumpId(&seqminfo[i].dobj);
+		seqminfo[i].dobj.name = pg_strdup(PQgetvalue(res, i, i_seqamname));
+		seqminfo[i].dobj.namespace = NULL;
+
+		/* Decide whether we want to dump it */
+		selectDumpableObject(&(seqminfo[i].dobj));
+	}
+
+	PQclear(res);
+
+	destroyPQExpBuffer(query);
+
+	return seqminfo;
+}
+
+/*
  * getTriggers
  *	  get information about every trigger on a dumpable table
  *
@@ -8285,6 +8351,9 @@ dumpDumpableObject(Archive *fout, DumpOptions *dopt, DumpableObject *dobj)
 		case DO_POLICY:
 			dumpPolicy(fout, dopt, (PolicyInfo *) dobj);
 			break;
+		case DO_SEQAM:
+			dumpSeqAM(fout, dopt, (SeqAMInfo *) dobj);
+			break;
 		case DO_PRE_DATA_BOUNDARY:
 		case DO_POST_DATA_BOUNDARY:
 			/* never dumped, nothing to do */
@@ -14578,6 +14647,90 @@ findLastBuiltinOid_V70(Archive *fout)
 }
 
 /*
+ * dumpSeqAM
+ *	  write the declaration of one user-defined sequence access method
+ */
+static void
+dumpSeqAM(Archive *fout, DumpOptions *dopt, SeqAMInfo *seqaminfo)
+{
+	PGresult   *res;
+	PQExpBuffer q;
+	PQExpBuffer delq;
+	PQExpBuffer labelq;
+	PQExpBuffer query;
+	char	   *seqamreloptions;
+	char	   *seqaminit;
+	char	   *seqamalloc;
+	char	   *seqamsetval;
+	char	   *seqamgetstate;
+	char	   *seqamsetstate;
+
+	/* Skip if not to be dumped */
+	if (!seqaminfo->dobj.dump || dopt->dataOnly)
+		return;
+
+	q = createPQExpBuffer();
+	delq = createPQExpBuffer();
+	labelq = createPQExpBuffer();
+	query = createPQExpBuffer();
+
+	appendPQExpBuffer(query, "SELECT seqamreloptions, seqaminit, "
+							 "seqamalloc, seqamsetval, "
+							 "seqamgetstate, seqamsetstate "
+							 "FROM pg_catalog.pg_seqam "
+							 "WHERE oid = '%u'::pg_catalog.oid",
+							 seqaminfo->dobj.catId.oid);
+
+	res = ExecuteSqlQueryForSingleRow(fout, query->data);
+
+	seqamreloptions = PQgetvalue(res, 0, PQfnumber(res, "seqamreloptions"));
+	seqaminit = PQgetvalue(res, 0, PQfnumber(res, "seqaminit"));
+	seqamalloc = PQgetvalue(res, 0, PQfnumber(res, "seqamalloc"));
+	seqamsetval = PQgetvalue(res, 0, PQfnumber(res, "seqamsetval"));
+	seqamgetstate = PQgetvalue(res, 0, PQfnumber(res, "seqamgetstate"));
+	seqamsetstate = PQgetvalue(res, 0, PQfnumber(res, "seqamsetstate"));
+
+	appendPQExpBuffer(q, "CREATE ACCESS METHOD FOR SEQUENCES %s AS (\n",
+					  fmtId(seqaminfo->dobj.name));
+
+	appendPQExpBuffer(q, "    RELOPTIONS = %s,\n", seqamreloptions);
+	appendPQExpBuffer(q, "    INIT = %s,\n", seqaminit);
+	appendPQExpBuffer(q, "    ALLOC = %s,\n", seqamalloc);
+	appendPQExpBuffer(q, "    SETVAL = %s,\n", seqamsetval);
+	appendPQExpBuffer(q, "    GETSTATE = %s,\n", seqamgetstate);
+	appendPQExpBuffer(q, "    SETSTATE = %s\n);\n", seqamsetstate);
+
+	appendPQExpBuffer(delq, "DROP CREATE ACCESS METHOD FOR SEQUENCES %s",
+					  fmtId(seqaminfo->dobj.name));
+
+	appendPQExpBuffer(labelq, "ACCESS METHOD FOR SEQUENCES %s",
+					  fmtId(seqaminfo->dobj.name));
+
+	if (dopt->binary_upgrade)
+		binary_upgrade_extension_member(q, &seqaminfo->dobj, labelq->data);
+
+	ArchiveEntry(fout, seqaminfo->dobj.catId, seqaminfo->dobj.dumpId,
+				 seqaminfo->dobj.name,
+				 NULL,
+				 NULL,
+				 "",
+				 false, "ACCESS METHOD FOR SEQUENCES", SECTION_PRE_DATA,
+				 q->data, delq->data, NULL,
+				 NULL, 0,
+				 NULL, NULL);
+
+	/* Dump Parser Comments */
+	dumpComment(fout, dopt, labelq->data,
+				NULL, "",
+				seqaminfo->dobj.catId, 0, seqaminfo->dobj.dumpId);
+
+	PQclear(res);
+	destroyPQExpBuffer(q);
+	destroyPQExpBuffer(delq);
+	destroyPQExpBuffer(labelq);
+}
+
+/*
  * dumpSequence
  *	  write the declaration (not data) of one user-defined sequence
  */
@@ -14679,8 +14832,8 @@ dumpSequence(Archive *fout, DumpOptions *dopt, TableInfo *tbinfo)
 	{
 		PGresult   *res2;
 
-		printfPQExpBuffer(query, "SELECT a.seqamname\n"
-								 "FROM pg_catalog.pg_seqam a, pg_catalog.pg_class c\n"
+		printfPQExpBuffer(query, "SELECT a.seqamname "
+								 "FROM pg_catalog.pg_seqam a, pg_catalog.pg_class c "
 								 "WHERE c.relam = a.oid AND c.oid = %u",
 						  tbinfo->dobj.catId.oid);
 
@@ -15705,6 +15858,7 @@ addBoundaryDependencies(DumpableObject **dobjs, int numObjs,
 			case DO_FDW:
 			case DO_FOREIGN_SERVER:
 			case DO_BLOB:
+			case DO_SEQAM:
 				/* Pre-data objects: must come before the pre-data boundary */
 				addObjectDependency(preDataBound, dobj->dumpId);
 				break;
diff --git a/src/bin/pg_dump/pg_dump.h b/src/bin/pg_dump/pg_dump.h
index 4b2ce46..dd78ca9 100644
--- a/src/bin/pg_dump/pg_dump.h
+++ b/src/bin/pg_dump/pg_dump.h
@@ -76,7 +76,8 @@ typedef enum
 	DO_POST_DATA_BOUNDARY,
 	DO_EVENT_TRIGGER,
 	DO_REFRESH_MATVIEW,
-	DO_POLICY
+	DO_POLICY,
+	DO_SEQAM
 } DumpableObjectType;
 
 typedef struct _dumpableObject
@@ -305,6 +306,11 @@ typedef struct _ruleInfo
 	/* reloptions is only set if we need to dump the options with the rule */
 } RuleInfo;
 
+typedef struct _seqamInfo
+{
+	DumpableObject dobj;
+} SeqAMInfo;
+
 typedef struct _triggerInfo
 {
 	DumpableObject dobj;
@@ -551,5 +557,6 @@ extern void getExtensionMembership(Archive *fout, DumpOptions *dopt, ExtensionIn
 					   int numExtensions);
 extern EventTriggerInfo *getEventTriggers(Archive *fout, int *numEventTriggers);
 extern void getPolicies(Archive *fout, TableInfo tblinfo[], int numTables);
+extern SeqAMInfo *getSeqAMs(Archive *fout, int *numSeqAMs);
 
 #endif   /* PG_DUMP_H */
diff --git a/src/bin/pg_dump/pg_dump_sort.c b/src/bin/pg_dump/pg_dump_sort.c
index 4b9bba0..9b431dc 100644
--- a/src/bin/pg_dump/pg_dump_sort.c
+++ b/src/bin/pg_dump/pg_dump_sort.c
@@ -73,7 +73,8 @@ static const int oldObjectTypePriority[] =
 	13,							/* DO_POST_DATA_BOUNDARY */
 	20,							/* DO_EVENT_TRIGGER */
 	15,							/* DO_REFRESH_MATVIEW */
-	21							/* DO_POLICY */
+	21,							/* DO_POLICY */
+	5							/* DO_SEQAM */
 };
 
 /*
@@ -122,7 +123,8 @@ static const int newObjectTypePriority[] =
 	25,							/* DO_POST_DATA_BOUNDARY */
 	32,							/* DO_EVENT_TRIGGER */
 	33,							/* DO_REFRESH_MATVIEW */
-	34							/* DO_POLICY */
+	34,							/* DO_POLICY */
+	17							/* DO_SEQAM */
 };
 
 static DumpId preDataBoundId;
@@ -1443,6 +1445,11 @@ describeDumpableObject(DumpableObject *obj, char *buf, int bufsize)
 					 "POLICY (ID %d OID %u)",
 					 obj->dumpId, obj->catId.oid);
 			return;
+		case DO_SEQAM:
+			snprintf(buf, bufsize,
+					 "ACCESS METHOD FOR SEQUENCES %s  (ID %d OID %u)",
+					 obj->name, obj->dumpId, obj->catId.oid);
+			return;
 		case DO_PRE_DATA_BOUNDARY:
 			snprintf(buf, bufsize,
 					 "PRE-DATA BOUNDARY  (ID %d)",
diff --git a/src/include/access/seqam.h b/src/include/access/seqam.h
index e53f1ab..436e78f 100644
--- a/src/include/access/seqam.h
+++ b/src/include/access/seqam.h
@@ -28,6 +28,9 @@ typedef struct SequenceHandle SequenceHandle;
 
 extern char *serial_seqam;
 
+extern Oid DefineSeqAM(List *names, List *definition);
+extern void RemoveSeqAMById(Oid seqamoid);
+
 extern void seqam_init(Oid seqamid, Oid seqrelid, List *seqparams,
 					   List *reloptions, Datum *values, bool *nulls);
 extern int64 seqam_alloc(Relation seqrel, SequenceHandle *seqh,
diff --git a/src/include/catalog/dependency.h b/src/include/catalog/dependency.h
index 6481ac8..9485d02 100644
--- a/src/include/catalog/dependency.h
+++ b/src/include/catalog/dependency.h
@@ -148,6 +148,7 @@ typedef enum ObjectClass
 	OCLASS_EXTENSION,			/* pg_extension */
 	OCLASS_EVENT_TRIGGER,		/* pg_event_trigger */
 	OCLASS_POLICY,				/* pg_policy */
+	OCLASS_SEQAM,				/* pg_seqam */
 	MAX_OCLASS					/* MUST BE LAST */
 } ObjectClass;
 
diff --git a/src/include/nodes/parsenodes.h b/src/include/nodes/parsenodes.h
index 5c82957..941adbc 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -1231,6 +1231,7 @@ typedef enum ObjectType
 	OBJECT_ROLE,
 	OBJECT_RULE,
 	OBJECT_SCHEMA,
+	OBJECT_SEQAM,
 	OBJECT_SEQUENCE,
 	OBJECT_TABCONSTRAINT,
 	OBJECT_TABLE,
diff --git a/src/include/parser/kwlist.h b/src/include/parser/kwlist.h
index 7c243ec..ece52b0 100644
--- a/src/include/parser/kwlist.h
+++ b/src/include/parser/kwlist.h
@@ -236,6 +236,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)
-- 
1.9.1

