0002-seqam-ddl-v5.patch
binary/octet-stream
Filename: 0002-seqam-ddl-v5.patch
Type: binary/octet-stream
Part: 1
Message:
Re: Sequence Access Method WIP
Patch
Format: unified
Series: patch v5-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 | 308 | 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/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 149d44f96a6da30024b23129b87363495e2736dc 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 v5
---
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 | 308 +++++++++++++++++++++++++++++++++++
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/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 +
20 files changed, 858 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 8faa87b..0a48cc8 100644
--- a/doc/src/sgml/catalogs.sgml
+++ b/doc/src/sgml/catalogs.sgml
@@ -5677,6 +5677,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 bf95453..2fef865 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">
@@ -117,6 +118,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 03020df..35c0c05 100644
--- a/doc/src/sgml/reference.sgml
+++ b/doc/src/sgml/reference.sgml
@@ -102,6 +102,7 @@
&createRole;
&createRule;
&createSchema;
+ &createSeqAM;
&createSequence;
&createServer;
&createTable;
@@ -145,6 +146,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 54d6e9d..bd9f2da 100644
--- a/src/backend/access/sequence/seqam.c
+++ b/src/backend/access/sequence/seqam.c
@@ -67,8 +67,20 @@
#include "access/seqam.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"
@@ -238,6 +250,302 @@ seqam_set_state(Relation seqrel, SequenceHandle *seqh, ArrayType *statearr)
/*
+ * 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[1] = INTERNALOID;
+ typeId[2] = INT8OID;
+ typeId[3] = BOOLOID;
+ typeId[4] = BOOLOID;
+ retTypeId = BYTEAOID;
+ 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 = 2;
+ typeId[1] = INTERNALOID;
+ retTypeId = TEXTARRAYOID;
+ break;
+
+ case Anum_pg_seqam_seqamsetstate:
+ nargs = 3;
+ typeId[1] = INTERNALOID;
+ typeId[2] = TEXTARRAYOID;
+ 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 ec4ba39..d268dc5 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"
@@ -158,7 +159,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 */
};
@@ -1270,6 +1272,10 @@ doDeletion(const ObjectAddress *object, int flags)
DropTransformById(object->objectId);
break;
+ case OCLASS_SEQAM:
+ RemoveSeqAMById(object->objectId);
+ break;
+
default:
elog(ERROR, "unrecognized object class: %u",
object->classId);
@@ -2399,6 +2405,9 @@ getObjectClass(const ObjectAddress *object)
case TransformRelationId:
return OCLASS_TRANSFORM;
+
+ case SeqAccessMethodRelationId:
+ return OCLASS_SEQAM;
}
/* shouldn't get here */
diff --git a/src/backend/catalog/objectaddress.c b/src/backend/catalog/objectaddress.c
index cbb0f5f..b3ddefc 100644
--- a/src/backend/catalog/objectaddress.c
+++ b/src/backend/catalog/objectaddress.c
@@ -437,6 +437,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
}
};
@@ -536,7 +548,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 =
@@ -691,6 +705,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;
@@ -942,6 +957,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 */
@@ -1002,6 +1020,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 */
@@ -2074,6 +2097,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,
@@ -3024,6 +3048,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,
@@ -3501,6 +3540,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;
@@ -4423,6 +4466,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 80a0eb6..1067ced 100644
--- a/src/backend/commands/dropcmds.c
+++ b/src/backend/commands/dropcmds.c
@@ -437,6 +437,10 @@ does_not_exist_skipping(ObjectType objtype, List *objname, List *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 7658c06..e7177c9 100644
--- a/src/backend/commands/event_trigger.c
+++ b/src/backend/commands/event_trigger.c
@@ -84,6 +84,7 @@ typedef enum
/* XXX merge this with ObjectTypeMap? */
static event_trigger_support_data event_trigger_support[] = {
+ {"ACCESS METHOD FOR SEQUENCES", true},
{"AGGREGATE", true},
{"CAST", true},
{"CONSTRAINT", true},
@@ -1102,6 +1103,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:
@@ -1164,6 +1166,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/parser/gram.y b/src/backend/parser/gram.y
index 60b855a..9e3734d 100644
--- a/src/backend/parser/gram.y
+++ b/src/backend/parser/gram.y
@@ -596,7 +596,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
@@ -5194,6 +5195,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; }
@@ -5648,6 +5657,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:
@@ -13634,6 +13644,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 ce712d8..630e28d 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"
@@ -1217,6 +1218,11 @@ ProcessUtilitySlow(Node *parsetree,
address = 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);
@@ -2154,6 +2160,9 @@ CreateCommandTag(Node *parsetree)
case OBJECT_TRANSFORM:
tag = "DROP TRANSFORM";
break;
+ case OBJECT_SEQAM:
+ tag = "DROP ACCESS METHOD FOR SEQUENCES";
+ break;
default:
tag = "???";
}
@@ -2250,6 +2259,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 d100514..fc76858 100644
--- a/src/bin/pg_dump/common.c
+++ b/src/bin/pg_dump/common.c
@@ -104,6 +104,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");
@@ -256,6 +257,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 b0ee6e5..3968f04 100644
--- a/src/bin/pg_dump/pg_dump.c
+++ b/src/bin/pg_dump/pg_dump.c
@@ -179,6 +179,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);
@@ -5996,6 +5997,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
*
@@ -8355,6 +8421,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 */
@@ -14812,6 +14881,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
*/
@@ -14913,8 +15066,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);
@@ -16019,6 +16172,7 @@ addBoundaryDependencies(DumpableObject **dobjs, int numObjs,
case DO_FOREIGN_SERVER:
case DO_TRANSFORM:
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 3d2b66a..141c684 100644
--- a/src/bin/pg_dump/pg_dump.h
+++ b/src/bin/pg_dump/pg_dump.h
@@ -77,7 +77,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;
@@ -561,5 +567,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 aa3e20a..ad81f0d 100644
--- a/src/bin/pg_dump/pg_dump_sort.c
+++ b/src/bin/pg_dump/pg_dump_sort.c
@@ -74,7 +74,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 */
};
/*
@@ -124,7 +125,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;
@@ -1469,6 +1471,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 7baa47c..b6e1474 100644
--- a/src/include/access/seqam.h
+++ b/src/include/access/seqam.h
@@ -26,6 +26,9 @@
struct SequenceHandle;
typedef struct SequenceHandle SequenceHandle;
+extern Oid DefineSeqAM(List *names, List *definition);
+extern void RemoveSeqAMById(Oid seqamoid);
+
extern HeapTuple seqam_init(Relation seqrel, HeapTuple tuple,
int64 restart_value, bool restart_requested,
bool is_init);
diff --git a/src/include/catalog/dependency.h b/src/include/catalog/dependency.h
index 5da18c2..42a2fa4 100644
--- a/src/include/catalog/dependency.h
+++ b/src/include/catalog/dependency.h
@@ -149,6 +149,7 @@ typedef enum ObjectClass
OCLASS_EVENT_TRIGGER, /* pg_event_trigger */
OCLASS_POLICY, /* pg_policy */
OCLASS_TRANSFORM, /* pg_transform */
+ 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 10e2a1e..e4d81a7 100644
--- a/src/include/nodes/parsenodes.h
+++ b/src/include/nodes/parsenodes.h
@@ -1298,6 +1298,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 faea991..0ec3cb3 100644
--- a/src/include/parser/kwlist.h
+++ b/src/include/parser/kwlist.h
@@ -237,6 +237,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