0002-seqam-ddl-v4.patch
text/x-diff
Patch
Format: unified
Series: patch v4-0002
| File | + | − |
|---|---|---|
| doc/src/sgml/catalogs.sgml | 6 | 0 |
| doc/src/sgml/ref/allfiles.sgml | 2 | 0 |
| doc/src/sgml/ref/create_seqam.sgml | 163 | 0 |
| doc/src/sgml/ref/drop_seqam.sgml | 87 | 0 |
| doc/src/sgml/reference.sgml | 2 | 0 |
| src/backend/access/sequence/seqam.c | 313 | 0 |
| src/backend/catalog/dependency.c | 10 | 1 |
| src/backend/catalog/objectaddress.c | 65 | 1 |
| src/backend/commands/dropcmds.c | 4 | 0 |
| src/backend/commands/event_trigger.c | 3 | 0 |
| src/backend/commands/sequence.c | 17 | 0 |
| src/backend/parser/gram.y | 12 | 1 |
| src/backend/tcop/utility.c | 12 | 0 |
| src/bin/pg_dump/common.c | 5 | 0 |
| src/bin/pg_dump/pg_dump.c | 156 | 2 |
| src/bin/pg_dump/pg_dump.h | 8 | 1 |
| src/bin/pg_dump/pg_dump_sort.c | 9 | 2 |
| src/include/access/seqam.h | 3 | 0 |
| src/include/catalog/dependency.h | 1 | 0 |
| src/include/nodes/parsenodes.h | 1 | 0 |
| src/include/parser/kwlist.h | 1 | 0 |
>From 8c55371002da1ce15d9b93684feb83da17676af0 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/4] seqam ddl v4
---
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 a6605cc..7198d6a 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -5530,6 +5530,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 d400ad5..62654f8 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 }
};
const ObjectAddress InvalidObjectAddress =
@@ -681,6 +695,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;
@@ -915,6 +930,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 */
@@ -975,6 +993,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 */
@@ -1917,6 +1940,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,
@@ -2855,6 +2879,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,
@@ -3332,6 +3371,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;
@@ -4243,6 +4286,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 3fec57e..75ba415 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},
@@ -1084,6 +1085,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:
@@ -1144,6 +1146,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 1089e40..5855e6b 100644
--- a/src/backend/commands/sequence.c
+++ b/src/backend/commands/sequence.c
@@ -1637,9 +1637,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 775a4b7..993b4c0 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -590,7 +590,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
@@ -5164,6 +5165,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; }
@@ -5622,6 +5631,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:
@@ -13485,6 +13495,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 126e38d..9fcc076 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"
@@ -1135,6 +1136,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);
@@ -2003,6 +2009,9 @@ CreateCommandTag(Node *parsetree)
case OBJECT_POLICY:
tag = "DROP POLICY";
break;
+ case OBJECT_SEQAM:
+ tag = "DROP ACCESS METHOD FOR SEQUENCES";
+ break;
default:
tag = "???";
}
@@ -2099,6 +2108,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 2b88aab..a54d620 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);
@@ -5995,6 +5996,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
*
@@ -8245,6 +8311,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 */
@@ -14538,6 +14607,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 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
*/
@@ -14639,8 +14792,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);
@@ -15741,6 +15894,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 7eaee32..ee68b1d 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
@@ -304,6 +305,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;
@@ -550,5 +556,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 c5ed593..c79ac98 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;
@@ -1460,6 +1462,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 84b4ae3..d9183f6 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -1259,6 +1259,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