]> granicus.if.org Git - postgresql/commitdiff
Add pg_sequence system catalog
authorPeter Eisentraut <peter_e@gmx.net>
Tue, 20 Dec 2016 17:00:00 +0000 (12:00 -0500)
committerPeter Eisentraut <peter_e@gmx.net>
Tue, 20 Dec 2016 13:28:18 +0000 (08:28 -0500)
Move sequence metadata (start, increment, etc.) into a proper system
catalog instead of storing it in the sequence heap object.  This
separates the metadata from the sequence data.  Sequence metadata is now
operated on transactionally by DDL commands, whereas previously
rollbacks of sequence-related DDL commands would be ignored.

Reviewed-by: Andreas Karlsson <andreas@proxel.se>
19 files changed:
doc/src/sgml/catalogs.sgml
src/backend/catalog/Makefile
src/backend/catalog/dependency.c
src/backend/catalog/information_schema.sql
src/backend/catalog/system_views.sql
src/backend/commands/sequence.c
src/backend/utils/cache/syscache.c
src/bin/pg_dump/pg_dump.c
src/include/catalog/catversion.h
src/include/catalog/indexing.h
src/include/catalog/pg_sequence.h [new file with mode: 0644]
src/include/commands/sequence.h
src/include/utils/syscache.h
src/test/regress/expected/rules.out
src/test/regress/expected/sanity_check.out
src/test/regress/expected/sequence.out
src/test/regress/expected/updatable_views.out
src/test/regress/sql/sequence.sql
src/test/regress/sql/updatable_views.sql

index 11c201910686771863557374c61337266157508f..7a7bbde390b0887a5eb13fc1ef04c164c502c7db 100644 (file)
       <entry>security labels on database objects</entry>
      </row>
 
+     <row>
+      <entry><link linkend="catalog-pg-sequence"><structname>pg_sequence</structname></link></entry>
+      <entry>information about sequences</entry>
+     </row>
+
      <row>
       <entry><link linkend="catalog-pg-shdepend"><structname>pg_shdepend</structname></link></entry>
       <entry>dependencies on shared objects</entry>
    The catalog <structname>pg_class</structname> catalogs tables and most
    everything else that has columns or is otherwise similar to a
    table.  This includes indexes (but see also
-   <structname>pg_index</structname>), sequences, views, materialized
+   <structname>pg_index</structname>), sequences (but see also
+   <structname>pg_sequence</structname>), views, materialized
    views, composite types, and TOAST tables; see <structfield>relkind</>.
    Below, when we mean all of these
    kinds of objects we speak of <quote>relations</quote>.  Not all
   </table>
  </sect1>
 
+ <sect1 id="catalog-pg-sequence">
+  <title><structname>pg_sequence</structname></title>
+
+  <indexterm zone="catalog-pg-sequence">
+   <primary>pg_sequence</primary>
+  </indexterm>
+
+  <para>
+   The catalog <structname>pg_sequence</structname> contains information about
+   sequences.  Some of the information about sequences, such as the name and
+   the schema, is in <structname>pg_class</structname>.
+  </para>
+
+  <table>
+   <title><structname>pg_sequence</> Columns</title>
+
+   <tgroup cols="4">
+    <thead>
+     <row>
+      <entry>Name</entry>
+      <entry>Type</entry>
+      <entry>References</entry>
+      <entry>Description</entry>
+     </row>
+    </thead>
+
+    <tbody>
+     <row>
+      <entry><structfield>seqrelid</structfield></entry>
+      <entry><type>oid</type></entry>
+      <entry><literal><link linkend="catalog-pg-class"><structname>pg_class</structname></link>.oid</literal></entry>
+      <entry>The OID of the <structname>pg_class</> entry for this sequence</entry>
+     </row>
+
+     <row>
+      <entry><structfield>seqstart</structfield></entry>
+      <entry><type>int8</type></entry>
+      <entry></entry>
+      <entry>Start value of the sequence</entry>
+     </row>
+
+     <row>
+      <entry><structfield>seqincrement</structfield></entry>
+      <entry><type>int8</type></entry>
+      <entry></entry>
+      <entry>Increment value of the sequence</entry>
+     </row>
+
+     <row>
+      <entry><structfield>seqmax</structfield></entry>
+      <entry><type>int8</type></entry>
+      <entry></entry>
+      <entry>Maximum value of the sequence</entry>
+     </row>
+
+     <row>
+      <entry><structfield>seqmin</structfield></entry>
+      <entry><type>int8</type></entry>
+      <entry></entry>
+      <entry>Minimum value of the sequence</entry>
+     </row>
+
+     <row>
+      <entry><structfield>seqcache</structfield></entry>
+      <entry><type>int8</type></entry>
+      <entry></entry>
+      <entry>Cache size of the sequence</entry>
+     </row>
+
+     <row>
+      <entry><structfield>seqcycle</structfield></entry>
+      <entry><type>bool</type></entry>
+      <entry></entry>
+      <entry>Whether the sequence cycles</entry>
+     </row>
+    </tbody>
+   </tgroup>
+  </table>
+ </sect1>
+
  <sect1 id="catalog-pg-shdepend">
   <title><structname>pg_shdepend</structname></title>
 
index 2d5ac09bece554bdd9dee157e6dc1111dc2c67df..cd38c8ab3ff444a7406583267f8643e7760d81a4 100644 (file)
@@ -42,6 +42,7 @@ POSTGRES_BKI_SRCS = $(addprefix $(top_srcdir)/src/include/catalog/,\
        pg_foreign_table.h pg_policy.h pg_replication_origin.h \
        pg_default_acl.h pg_init_privs.h pg_seclabel.h pg_shseclabel.h \
        pg_collation.h pg_partitioned_table.h pg_range.h pg_transform.h \
+       pg_sequence.h \
        toasting.h indexing.h \
     )
 
index 0cdd1c5c6cb05a6122cdd49f5205b968e6dcdba7..18a14bf146d5190db8b92f9b4371194efd61fd7b 100644 (file)
@@ -66,6 +66,7 @@
 #include "commands/proclang.h"
 #include "commands/schemacmds.h"
 #include "commands/seclabel.h"
+#include "commands/sequence.h"
 #include "commands/trigger.h"
 #include "commands/typecmds.h"
 #include "nodes/nodeFuncs.h"
@@ -1114,6 +1115,11 @@ doDeletion(const ObjectAddress *object, int flags)
                                        else
                                                heap_drop_with_catalog(object->objectId);
                                }
+
+                               /* for a sequence, in addition to dropping the heap, also
+                                * delete pg_sequence tuple */
+                               if (relKind == RELKIND_SEQUENCE)
+                                       DeleteSequenceTuple(object->objectId);
                                break;
                        }
 
index 00550eb8044f2c410d5cf0d03ab84b0027102721..182d2d06746806de27d13e7b9fe5e013e8a99968 100644 (file)
@@ -1535,15 +1535,16 @@ CREATE VIEW sequences AS
            CAST(64 AS cardinal_number) AS numeric_precision,
            CAST(2 AS cardinal_number) AS numeric_precision_radix,
            CAST(0 AS cardinal_number) AS numeric_scale,
-           CAST(p.start_value AS character_data) AS start_value,
-           CAST(p.minimum_value AS character_data) AS minimum_value,
-           CAST(p.maximum_value AS character_data) AS maximum_value,
-           CAST(p.increment AS character_data) AS increment,
-           CAST(CASE WHEN p.cycle_option THEN 'YES' ELSE 'NO' END AS yes_or_no) AS cycle_option
-    FROM pg_namespace nc, pg_class c, LATERAL pg_sequence_parameters(c.oid) p
+           CAST(s.seqstart AS character_data) AS start_value,
+           CAST(s.seqmin AS character_data) AS minimum_value,
+           CAST(s.seqmax AS character_data) AS maximum_value,
+           CAST(s.seqincrement AS character_data) AS increment,
+           CAST(CASE WHEN s.seqcycle THEN 'YES' ELSE 'NO' END AS yes_or_no) AS cycle_option
+    FROM pg_namespace nc, pg_class c, pg_sequence s
     WHERE c.relnamespace = nc.oid
           AND c.relkind = 'S'
           AND (NOT pg_is_other_temp_schema(nc.oid))
+          AND c.oid = s.seqrelid
           AND (pg_has_role(c.relowner, 'USAGE')
                OR has_sequence_privilege(c.oid, 'SELECT, UPDATE, USAGE') );
 
index 48e7c4b7f956b8fa63f12470fa7685057ce30158..649cef86c53bf56ab44fa49cbec1e78b387bd4fa 100644 (file)
@@ -169,15 +169,15 @@ CREATE OR REPLACE VIEW pg_sequences AS
         N.nspname AS schemaname,
         C.relname AS sequencename,
         pg_get_userbyid(C.relowner) AS sequenceowner,
-        p.start_value AS start_value,
-        p.minimum_value AS min_value,
-        p.maximum_value AS max_value,
-        p.increment AS increment_by,
-        p.cycle_option AS cycle,
-        p.cache_size AS cache_size,
+        S.seqstart AS start_value,
+        S.seqmin AS min_value,
+        S.seqmax AS max_value,
+        S.seqincrement AS increment_by,
+        S.seqcycle AS cycle,
+        S.seqcache AS cache_size,
         pg_sequence_last_value(C.oid) AS last_value
-    FROM pg_class C LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace),
-         LATERAL pg_sequence_parameters(C.oid) p
+    FROM pg_sequence S JOIN pg_class C ON (C.oid = S.seqrelid)
+         LEFT JOIN pg_namespace N ON (N.oid = C.relnamespace)
     WHERE NOT pg_is_other_temp_schema(N.oid)
           AND relkind = 'S';
 
index d953b4408bddf3a80e7b2807d3d939c1b1db1430..cdd32bc17e031ccf68414e5ed5e346397eecdbf0 100644 (file)
 #include "access/xloginsert.h"
 #include "access/xlogutils.h"
 #include "catalog/dependency.h"
+#include "catalog/indexing.h"
 #include "catalog/namespace.h"
 #include "catalog/objectaccess.h"
+#include "catalog/pg_sequence.h"
 #include "catalog/pg_type.h"
 #include "commands/defrem.h"
 #include "commands/sequence.h"
@@ -74,7 +76,7 @@ typedef struct SeqTableData
        int64           cached;                 /* last value already cached for nextval */
        /* if last != cached, we have not used up all the cached values */
        int64           increment;              /* copy of sequence's increment field */
-       /* note that increment is zero until we first do read_seq_tuple() */
+       /* note that increment is zero until we first do nextval_internal() */
 } SeqTableData;
 
 typedef SeqTableData *SeqTable;
@@ -92,10 +94,11 @@ static int64 nextval_internal(Oid relid);
 static Relation open_share_lock(SeqTable seq);
 static void create_seq_hashtable(void);
 static void init_sequence(Oid relid, SeqTable *p_elm, Relation *p_rel);
-static Form_pg_sequence read_seq_tuple(SeqTable elm, Relation rel,
-                          Buffer *buf, HeapTuple seqtuple);
+static Form_pg_sequence_data read_seq_tuple(Relation rel,
+                          Buffer *buf, HeapTuple seqdatatuple);
 static void init_params(ParseState *pstate, List *options, bool isInit,
-                       Form_pg_sequence new, List **owned_by);
+                                               Form_pg_sequence seqform,
+                                               Form_pg_sequence_data seqdataform, List **owned_by);
 static void do_setval(Oid relid, int64 next, bool iscalled);
 static void process_owned_by(Relation seqrel, List *owned_by);
 
@@ -107,7 +110,8 @@ static void process_owned_by(Relation seqrel, List *owned_by);
 ObjectAddress
 DefineSequence(ParseState *pstate, CreateSeqStmt *seq)
 {
-       FormData_pg_sequence new;
+       FormData_pg_sequence seqform;
+       FormData_pg_sequence_data seqdataform;
        List       *owned_by;
        CreateStmt *stmt = makeNode(CreateStmt);
        Oid                     seqoid;
@@ -117,8 +121,9 @@ DefineSequence(ParseState *pstate, CreateSeqStmt *seq)
        TupleDesc       tupDesc;
        Datum           value[SEQ_COL_LASTCOL];
        bool            null[SEQ_COL_LASTCOL];
+       Datum           pgs_values[Natts_pg_sequence];
+       bool            pgs_nulls[Natts_pg_sequence];
        int                     i;
-       NameData        name;
 
        /* Unlogged sequences are not implemented -- not clear if useful. */
        if (seq->sequence->relpersistence == RELPERSISTENCE_UNLOGGED)
@@ -145,7 +150,7 @@ DefineSequence(ParseState *pstate, CreateSeqStmt *seq)
        }
 
        /* Check and set all option values */
-       init_params(pstate, seq->options, true, &new, &owned_by);
+       init_params(pstate, seq->options, true, &seqform, &seqdataform, &owned_by);
 
        /*
         * Create relation (and fill value[] and null[] for the tuple)
@@ -171,52 +176,16 @@ DefineSequence(ParseState *pstate, CreateSeqStmt *seq)
 
                switch (i)
                {
-                       case SEQ_COL_NAME:
-                               coldef->typeName = makeTypeNameFromOid(NAMEOID, -1);
-                               coldef->colname = "sequence_name";
-                               namestrcpy(&name, seq->sequence->relname);
-                               value[i - 1] = NameGetDatum(&name);
-                               break;
                        case SEQ_COL_LASTVAL:
                                coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
                                coldef->colname = "last_value";
-                               value[i - 1] = Int64GetDatumFast(new.last_value);
-                               break;
-                       case SEQ_COL_STARTVAL:
-                               coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
-                               coldef->colname = "start_value";
-                               value[i - 1] = Int64GetDatumFast(new.start_value);
-                               break;
-                       case SEQ_COL_INCBY:
-                               coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
-                               coldef->colname = "increment_by";
-                               value[i - 1] = Int64GetDatumFast(new.increment_by);
-                               break;
-                       case SEQ_COL_MAXVALUE:
-                               coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
-                               coldef->colname = "max_value";
-                               value[i - 1] = Int64GetDatumFast(new.max_value);
-                               break;
-                       case SEQ_COL_MINVALUE:
-                               coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
-                               coldef->colname = "min_value";
-                               value[i - 1] = Int64GetDatumFast(new.min_value);
-                               break;
-                       case SEQ_COL_CACHE:
-                               coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
-                               coldef->colname = "cache_value";
-                               value[i - 1] = Int64GetDatumFast(new.cache_value);
+                               value[i - 1] = Int64GetDatumFast(seqdataform.last_value);
                                break;
                        case SEQ_COL_LOG:
                                coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
                                coldef->colname = "log_cnt";
                                value[i - 1] = Int64GetDatum((int64) 0);
                                break;
-                       case SEQ_COL_CYCLE:
-                               coldef->typeName = makeTypeNameFromOid(BOOLOID, -1);
-                               coldef->colname = "is_cycled";
-                               value[i - 1] = BoolGetDatum(new.is_cycled);
-                               break;
                        case SEQ_COL_CALLED:
                                coldef->typeName = makeTypeNameFromOid(BOOLOID, -1);
                                coldef->colname = "is_called";
@@ -251,6 +220,27 @@ DefineSequence(ParseState *pstate, CreateSeqStmt *seq)
 
        heap_close(rel, NoLock);
 
+       /* fill in pg_sequence */
+       rel = heap_open(SequenceRelationId, RowExclusiveLock);
+       tupDesc = RelationGetDescr(rel);
+
+       memset(pgs_nulls, 0, sizeof(pgs_nulls));
+
+       pgs_values[Anum_pg_sequence_seqrelid - 1] = ObjectIdGetDatum(seqoid);
+       pgs_values[Anum_pg_sequence_seqstart - 1] = Int64GetDatumFast(seqform.seqstart);
+       pgs_values[Anum_pg_sequence_seqincrement - 1] = Int64GetDatumFast(seqform.seqincrement);
+       pgs_values[Anum_pg_sequence_seqmax - 1] = Int64GetDatumFast(seqform.seqmax);
+       pgs_values[Anum_pg_sequence_seqmin - 1] = Int64GetDatumFast(seqform.seqmin);
+       pgs_values[Anum_pg_sequence_seqcache - 1] = Int64GetDatumFast(seqform.seqcache);
+       pgs_values[Anum_pg_sequence_seqcycle - 1] = BoolGetDatum(seqform.seqcycle);
+
+       tuple = heap_form_tuple(tupDesc, pgs_values, pgs_nulls);
+       simple_heap_insert(rel, tuple);
+       CatalogUpdateIndexes(rel, tuple);
+
+       heap_freetuple(tuple);
+       heap_close(rel, RowExclusiveLock);
+
        return address;
 }
 
@@ -271,10 +261,13 @@ ResetSequence(Oid seq_relid)
 {
        Relation        seq_rel;
        SeqTable        elm;
-       Form_pg_sequence seq;
+       Form_pg_sequence_data seq;
        Buffer          buf;
-       HeapTupleData seqtuple;
+       HeapTupleData seqdatatuple;
        HeapTuple       tuple;
+       HeapTuple       pgstuple;
+       Form_pg_sequence pgsform;
+       int64           startv;
 
        /*
         * Read the old sequence.  This does a bit more work than really
@@ -282,12 +275,19 @@ ResetSequence(Oid seq_relid)
         * indeed a sequence.
         */
        init_sequence(seq_relid, &elm, &seq_rel);
-       (void) read_seq_tuple(elm, seq_rel, &buf, &seqtuple);
+       (void) read_seq_tuple(seq_rel, &buf, &seqdatatuple);
+
+       pgstuple = SearchSysCache1(SEQRELID, ObjectIdGetDatum(seq_relid));
+       if (!HeapTupleIsValid(pgstuple))
+               elog(ERROR, "cache lookup failed for sequence %u", seq_relid);
+       pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
+       startv = pgsform->seqstart;
+       ReleaseSysCache(pgstuple);
 
        /*
         * Copy the existing sequence tuple.
         */
-       tuple = heap_copytuple(&seqtuple);
+       tuple = heap_copytuple(&seqdatatuple);
 
        /* Now we're done with the old page */
        UnlockReleaseBuffer(buf);
@@ -296,8 +296,8 @@ ResetSequence(Oid seq_relid)
         * Modify the copied tuple to execute the restart (compare the RESTART
         * action in AlterSequence)
         */
-       seq = (Form_pg_sequence) GETSTRUCT(tuple);
-       seq->last_value = seq->start_value;
+       seq = (Form_pg_sequence_data) GETSTRUCT(tuple);
+       seq->last_value = startv;
        seq->is_called = false;
        seq->log_cnt = 0;
 
@@ -410,11 +410,14 @@ AlterSequence(ParseState *pstate, AlterSeqStmt *stmt)
        SeqTable        elm;
        Relation        seqrel;
        Buffer          buf;
-       HeapTupleData seqtuple;
-       Form_pg_sequence seq;
-       FormData_pg_sequence new;
+       HeapTupleData seqdatatuple;
+       Form_pg_sequence seqform;
+       Form_pg_sequence_data seqdata;
+       FormData_pg_sequence_data newseqdata;
        List       *owned_by;
        ObjectAddress address;
+       Relation        rel;
+       HeapTuple       tuple;
 
        /* Open and lock sequence. */
        relid = RangeVarGetRelid(stmt->sequence, AccessShareLock, stmt->missing_ok);
@@ -434,13 +437,22 @@ AlterSequence(ParseState *pstate, AlterSeqStmt *stmt)
                                           stmt->sequence->relname);
 
        /* lock page' buffer and read tuple into new sequence structure */
-       seq = read_seq_tuple(elm, seqrel, &buf, &seqtuple);
+       seqdata = read_seq_tuple(seqrel, &buf, &seqdatatuple);
 
        /* Copy old values of options into workspace */
-       memcpy(&new, seq, sizeof(FormData_pg_sequence));
+       memcpy(&newseqdata, seqdata, sizeof(FormData_pg_sequence_data));
+
+       rel = heap_open(SequenceRelationId, RowExclusiveLock);
+       tuple = SearchSysCacheCopy1(SEQRELID,
+                                                               ObjectIdGetDatum(relid));
+       if (!HeapTupleIsValid(tuple))
+               elog(ERROR, "cache lookup failed for sequence %u",
+                        relid);
+
+       seqform = (Form_pg_sequence) GETSTRUCT(tuple);
 
        /* Check and set new values */
-       init_params(pstate, stmt->options, false, &new, &owned_by);
+       init_params(pstate, stmt->options, false, seqform, &newseqdata, &owned_by);
 
        /* Clear local cache so that we don't think we have cached numbers */
        /* Note that we do not change the currval() state */
@@ -453,7 +465,7 @@ AlterSequence(ParseState *pstate, AlterSeqStmt *stmt)
        /* Now okay to update the on-disk tuple */
        START_CRIT_SECTION();
 
-       memcpy(seq, &new, sizeof(FormData_pg_sequence));
+       memcpy(seqdata, &newseqdata, sizeof(FormData_pg_sequence_data));
 
        MarkBufferDirty(buf);
 
@@ -470,7 +482,7 @@ AlterSequence(ParseState *pstate, AlterSeqStmt *stmt)
                xlrec.node = seqrel->rd_node;
                XLogRegisterData((char *) &xlrec, sizeof(xl_seq_rec));
 
-               XLogRegisterData((char *) seqtuple.t_data, seqtuple.t_len);
+               XLogRegisterData((char *) seqdatatuple.t_data, seqdatatuple.t_len);
 
                recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG);
 
@@ -491,9 +503,30 @@ AlterSequence(ParseState *pstate, AlterSeqStmt *stmt)
 
        relation_close(seqrel, NoLock);
 
+       simple_heap_update(rel, &tuple->t_self, tuple);
+       CatalogUpdateIndexes(rel, tuple);
+       heap_close(rel, RowExclusiveLock);
+
        return address;
 }
 
+void
+DeleteSequenceTuple(Oid relid)
+{
+       Relation        rel;
+       HeapTuple       tuple;
+
+       rel = heap_open(SequenceRelationId, RowExclusiveLock);
+
+       tuple = SearchSysCache1(SEQRELID, ObjectIdGetDatum(relid));
+       if (!HeapTupleIsValid(tuple))
+               elog(ERROR, "cache lookup failed for sequence %u", relid);
+
+       simple_heap_delete(rel, &tuple->t_self);
+
+       ReleaseSysCache(tuple);
+       heap_close(rel, RowExclusiveLock);
+}
 
 /*
  * Note: nextval with a text argument is no longer exported as a pg_proc
@@ -537,8 +570,10 @@ nextval_internal(Oid relid)
        Relation        seqrel;
        Buffer          buf;
        Page            page;
-       HeapTupleData seqtuple;
-       Form_pg_sequence seq;
+       HeapTuple       pgstuple;
+       Form_pg_sequence pgsform;
+       HeapTupleData seqdatatuple;
+       Form_pg_sequence_data seq;
        int64           incby,
                                maxv,
                                minv,
@@ -549,6 +584,7 @@ nextval_internal(Oid relid)
        int64           result,
                                next,
                                rescnt = 0;
+       bool            cycle;
        bool            logit = false;
 
        /* open and AccessShareLock sequence */
@@ -582,15 +618,24 @@ nextval_internal(Oid relid)
                return elm->last;
        }
 
+       pgstuple = SearchSysCache1(SEQRELID, ObjectIdGetDatum(relid));
+       if (!HeapTupleIsValid(pgstuple))
+               elog(ERROR, "cache lookup failed for sequence %u", relid);
+       pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
+       incby = pgsform->seqincrement;
+       maxv = pgsform->seqmax;
+       minv = pgsform->seqmin;
+       cache = pgsform->seqcache;
+       cycle = pgsform->seqcycle;
+       ReleaseSysCache(pgstuple);
+
        /* lock page' buffer and read tuple */
-       seq = read_seq_tuple(elm, seqrel, &buf, &seqtuple);
+       seq = read_seq_tuple(seqrel, &buf, &seqdatatuple);
        page = BufferGetPage(buf);
 
+       elm->increment = incby;
        last = next = result = seq->last_value;
-       incby = seq->increment_by;
-       maxv = seq->max_value;
-       minv = seq->min_value;
-       fetch = cache = seq->cache_value;
+       fetch = cache;
        log = seq->log_cnt;
 
        if (!seq->is_called)
@@ -641,7 +686,7 @@ nextval_internal(Oid relid)
                        {
                                if (rescnt > 0)
                                        break;          /* stop fetching */
-                               if (!seq->is_cycled)
+                               if (!cycle)
                                {
                                        char            buf[100];
 
@@ -664,7 +709,7 @@ nextval_internal(Oid relid)
                        {
                                if (rescnt > 0)
                                        break;          /* stop fetching */
-                               if (!seq->is_cycled)
+                               if (!cycle)
                                {
                                        char            buf[100];
 
@@ -747,7 +792,7 @@ nextval_internal(Oid relid)
                xlrec.node = seqrel->rd_node;
 
                XLogRegisterData((char *) &xlrec, sizeof(xl_seq_rec));
-               XLogRegisterData((char *) seqtuple.t_data, seqtuple.t_len);
+               XLogRegisterData((char *) seqdatatuple.t_data, seqdatatuple.t_len);
 
                recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG);
 
@@ -853,8 +898,12 @@ do_setval(Oid relid, int64 next, bool iscalled)
        SeqTable        elm;
        Relation        seqrel;
        Buffer          buf;
-       HeapTupleData seqtuple;
-       Form_pg_sequence seq;
+       HeapTupleData seqdatatuple;
+       Form_pg_sequence_data seq;
+       HeapTuple       pgstuple;
+       Form_pg_sequence pgsform;
+       int64           maxv,
+                               minv;
 
        /* open and AccessShareLock sequence */
        init_sequence(relid, &elm, &seqrel);
@@ -865,6 +914,14 @@ do_setval(Oid relid, int64 next, bool iscalled)
                                 errmsg("permission denied for sequence %s",
                                                RelationGetRelationName(seqrel))));
 
+       pgstuple = SearchSysCache1(SEQRELID, ObjectIdGetDatum(relid));
+       if (!HeapTupleIsValid(pgstuple))
+               elog(ERROR, "cache lookup failed for sequence %u", relid);
+       pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
+       maxv = pgsform->seqmax;
+       minv = pgsform->seqmin;
+       ReleaseSysCache(pgstuple);
+
        /* read-only transactions may only modify temp sequences */
        if (!seqrel->rd_islocaltemp)
                PreventCommandIfReadOnly("setval()");
@@ -877,17 +934,17 @@ do_setval(Oid relid, int64 next, bool iscalled)
        PreventCommandIfParallelMode("setval()");
 
        /* lock page' buffer and read tuple */
-       seq = read_seq_tuple(elm, seqrel, &buf, &seqtuple);
+       seq = read_seq_tuple(seqrel, &buf, &seqdatatuple);
 
-       if ((next < seq->min_value) || (next > seq->max_value))
+       if ((next < minv) || (next > maxv))
        {
                char            bufv[100],
                                        bufm[100],
                                        bufx[100];
 
                snprintf(bufv, sizeof(bufv), INT64_FORMAT, next);
-               snprintf(bufm, sizeof(bufm), INT64_FORMAT, seq->min_value);
-               snprintf(bufx, sizeof(bufx), INT64_FORMAT, seq->max_value);
+               snprintf(bufm, sizeof(bufm), INT64_FORMAT, minv);
+               snprintf(bufx, sizeof(bufx), INT64_FORMAT, maxv);
                ereport(ERROR,
                                (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
                                 errmsg("setval: value %s is out of bounds for sequence \"%s\" (%s..%s)",
@@ -930,7 +987,7 @@ do_setval(Oid relid, int64 next, bool iscalled)
 
                xlrec.node = seqrel->rd_node;
                XLogRegisterData((char *) &xlrec, sizeof(xl_seq_rec));
-               XLogRegisterData((char *) seqtuple.t_data, seqtuple.t_len);
+               XLogRegisterData((char *) seqdatatuple.t_data, seqdatatuple.t_len);
 
                recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG);
 
@@ -1064,7 +1121,7 @@ init_sequence(Oid relid, SeqTable *p_elm, Relation *p_rel)
                elm->filenode = InvalidOid;
                elm->lxid = InvalidLocalTransactionId;
                elm->last_valid = false;
-               elm->last = elm->cached = elm->increment = 0;
+               elm->last = elm->cached = 0;
        }
 
        /*
@@ -1099,18 +1156,18 @@ init_sequence(Oid relid, SeqTable *p_elm, Relation *p_rel)
  * Given an opened sequence relation, lock the page buffer and find the tuple
  *
  * *buf receives the reference to the pinned-and-ex-locked buffer
- * *seqtuple receives the reference to the sequence tuple proper
+ * *seqdatatuple receives the reference to the sequence tuple proper
  *             (this arg should point to a local variable of type HeapTupleData)
  *
  * Function's return value points to the data payload of the tuple
  */
-static Form_pg_sequence
-read_seq_tuple(SeqTable elm, Relation rel, Buffer *buf, HeapTuple seqtuple)
+static Form_pg_sequence_data
+read_seq_tuple(Relation rel, Buffer *buf, HeapTuple seqdatatuple)
 {
        Page            page;
        ItemId          lp;
        sequence_magic *sm;
-       Form_pg_sequence seq;
+       Form_pg_sequence_data seq;
 
        *buf = ReadBuffer(rel, 0);
        LockBuffer(*buf, BUFFER_LOCK_EXCLUSIVE);
@@ -1125,9 +1182,9 @@ read_seq_tuple(SeqTable elm, Relation rel, Buffer *buf, HeapTuple seqtuple)
        lp = PageGetItemId(page, FirstOffsetNumber);
        Assert(ItemIdIsNormal(lp));
 
-       /* Note we currently only bother to set these two fields of *seqtuple */
-       seqtuple->t_data = (HeapTupleHeader) PageGetItem(page, lp);
-       seqtuple->t_len = ItemIdGetLength(lp);
+       /* Note we currently only bother to set these two fields of *seqdatatuple */
+       seqdatatuple->t_data = (HeapTupleHeader) PageGetItem(page, lp);
+       seqdatatuple->t_len = ItemIdGetLength(lp);
 
        /*
         * Previous releases of Postgres neglected to prevent SELECT FOR UPDATE on
@@ -1137,19 +1194,16 @@ read_seq_tuple(SeqTable elm, Relation rel, Buffer *buf, HeapTuple seqtuple)
         * bit update, ie, don't bother to WAL-log it, since we can certainly do
         * this again if the update gets lost.
         */
-       Assert(!(seqtuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI));
-       if (HeapTupleHeaderGetRawXmax(seqtuple->t_data) != InvalidTransactionId)
+       Assert(!(seqdatatuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI));
+       if (HeapTupleHeaderGetRawXmax(seqdatatuple->t_data) != InvalidTransactionId)
        {
-               HeapTupleHeaderSetXmax(seqtuple->t_data, InvalidTransactionId);
-               seqtuple->t_data->t_infomask &= ~HEAP_XMAX_COMMITTED;
-               seqtuple->t_data->t_infomask |= HEAP_XMAX_INVALID;
+               HeapTupleHeaderSetXmax(seqdatatuple->t_data, InvalidTransactionId);
+               seqdatatuple->t_data->t_infomask &= ~HEAP_XMAX_COMMITTED;
+               seqdatatuple->t_data->t_infomask |= HEAP_XMAX_INVALID;
                MarkBufferDirtyHint(*buf, true);
        }
 
-       seq = (Form_pg_sequence) GETSTRUCT(seqtuple);
-
-       /* this is a handy place to update our copy of the increment */
-       elm->increment = seq->increment_by;
+       seq = (Form_pg_sequence_data) GETSTRUCT(seqdatatuple);
 
        return seq;
 }
@@ -1164,7 +1218,8 @@ read_seq_tuple(SeqTable elm, Relation rel, Buffer *buf, HeapTuple seqtuple)
  */
 static void
 init_params(ParseState *pstate, List *options, bool isInit,
-                       Form_pg_sequence new, List **owned_by)
+                       Form_pg_sequence seqform,
+                       Form_pg_sequence_data seqdataform, List **owned_by)
 {
        DefElem    *start_value = NULL;
        DefElem    *restart_value = NULL;
@@ -1263,69 +1318,69 @@ init_params(ParseState *pstate, List *options, bool isInit,
         * would affect future nextval allocations.
         */
        if (isInit)
-               new->log_cnt = 0;
+               seqdataform->log_cnt = 0;
 
        /* INCREMENT BY */
        if (increment_by != NULL)
        {
-               new->increment_by = defGetInt64(increment_by);
-               if (new->increment_by == 0)
+               seqform->seqincrement = defGetInt64(increment_by);
+               if (seqform->seqincrement == 0)
                        ereport(ERROR,
                                        (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                         errmsg("INCREMENT must not be zero")));
-               new->log_cnt = 0;
+               seqdataform->log_cnt = 0;
        }
        else if (isInit)
-               new->increment_by = 1;
+               seqform->seqincrement = 1;
 
        /* CYCLE */
        if (is_cycled != NULL)
        {
-               new->is_cycled = intVal(is_cycled->arg);
-               Assert(BoolIsValid(new->is_cycled));
-               new->log_cnt = 0;
+               seqform->seqcycle = intVal(is_cycled->arg);
+               Assert(BoolIsValid(seqform->seqcycle));
+               seqdataform->log_cnt = 0;
        }
        else if (isInit)
-               new->is_cycled = false;
+               seqform->seqcycle = false;
 
        /* MAXVALUE (null arg means NO MAXVALUE) */
        if (max_value != NULL && max_value->arg)
        {
-               new->max_value = defGetInt64(max_value);
-               new->log_cnt = 0;
+               seqform->seqmax = defGetInt64(max_value);
+               seqdataform->log_cnt = 0;
        }
        else if (isInit || max_value != NULL)
        {
-               if (new->increment_by > 0)
-                       new->max_value = SEQ_MAXVALUE;          /* ascending seq */
+               if (seqform->seqincrement > 0)
+                       seqform->seqmax = SEQ_MAXVALUE;         /* ascending seq */
                else
-                       new->max_value = -1;    /* descending seq */
-               new->log_cnt = 0;
+                       seqform->seqmax = -1;   /* descending seq */
+               seqdataform->log_cnt = 0;
        }
 
        /* MINVALUE (null arg means NO MINVALUE) */
        if (min_value != NULL && min_value->arg)
        {
-               new->min_value = defGetInt64(min_value);
-               new->log_cnt = 0;
+               seqform->seqmin = defGetInt64(min_value);
+               seqdataform->log_cnt = 0;
        }
        else if (isInit || min_value != NULL)
        {
-               if (new->increment_by > 0)
-                       new->min_value = 1; /* ascending seq */
+               if (seqform->seqincrement > 0)
+                       seqform->seqmin = 1; /* ascending seq */
                else
-                       new->min_value = SEQ_MINVALUE;          /* descending seq */
-               new->log_cnt = 0;
+                       seqform->seqmin = SEQ_MINVALUE;         /* descending seq */
+               seqdataform->log_cnt = 0;
        }
 
        /* crosscheck min/max */
-       if (new->min_value >= new->max_value)
+       if (seqform->seqmin >= seqform->seqmax)
        {
                char            bufm[100],
                                        bufx[100];
 
-               snprintf(bufm, sizeof(bufm), INT64_FORMAT, new->min_value);
-               snprintf(bufx, sizeof(bufx), INT64_FORMAT, new->max_value);
+               snprintf(bufm, sizeof(bufm), INT64_FORMAT, seqform->seqmin);
+               snprintf(bufx, sizeof(bufx), INT64_FORMAT, seqform->seqmax);
                ereport(ERROR,
                                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                 errmsg("MINVALUE (%s) must be less than MAXVALUE (%s)",
@@ -1334,35 +1389,35 @@ init_params(ParseState *pstate, List *options, bool isInit,
 
        /* START WITH */
        if (start_value != NULL)
-               new->start_value = defGetInt64(start_value);
+               seqform->seqstart = defGetInt64(start_value);
        else if (isInit)
        {
-               if (new->increment_by > 0)
-                       new->start_value = new->min_value;      /* ascending seq */
+               if (seqform->seqincrement > 0)
+                       seqform->seqstart = seqform->seqmin;    /* ascending seq */
                else
-                       new->start_value = new->max_value;      /* descending seq */
+                       seqform->seqstart = seqform->seqmax;    /* descending seq */
        }
 
        /* crosscheck START */
-       if (new->start_value < new->min_value)
+       if (seqform->seqstart < seqform->seqmin)
        {
                char            bufs[100],
                                        bufm[100];
 
-               snprintf(bufs, sizeof(bufs), INT64_FORMAT, new->start_value);
-               snprintf(bufm, sizeof(bufm), INT64_FORMAT, new->min_value);
+               snprintf(bufs, sizeof(bufs), INT64_FORMAT, seqform->seqstart);
+               snprintf(bufm, sizeof(bufm), INT64_FORMAT, seqform->seqmin);
                ereport(ERROR,
                                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                 errmsg("START value (%s) cannot be less than MINVALUE (%s)",
                                                bufs, bufm)));
        }
-       if (new->start_value > new->max_value)
+       if (seqform->seqstart > seqform->seqmax)
        {
                char            bufs[100],
                                        bufm[100];
 
-               snprintf(bufs, sizeof(bufs), INT64_FORMAT, new->start_value);
-               snprintf(bufm, sizeof(bufm), INT64_FORMAT, new->max_value);
+               snprintf(bufs, sizeof(bufs), INT64_FORMAT, seqform->seqstart);
+               snprintf(bufm, sizeof(bufm), INT64_FORMAT, seqform->seqmax);
                ereport(ERROR,
                                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                          errmsg("START value (%s) cannot be greater than MAXVALUE (%s)",
@@ -1373,38 +1428,38 @@ init_params(ParseState *pstate, List *options, bool isInit,
        if (restart_value != NULL)
        {
                if (restart_value->arg != NULL)
-                       new->last_value = defGetInt64(restart_value);
+                       seqdataform->last_value = defGetInt64(restart_value);
                else
-                       new->last_value = new->start_value;
-               new->is_called = false;
-               new->log_cnt = 0;
+                       seqdataform->last_value = seqform->seqstart;
+               seqdataform->is_called = false;
+               seqdataform->log_cnt = 0;
        }
        else if (isInit)
        {
-               new->last_value = new->start_value;
-               new->is_called = false;
+               seqdataform->last_value = seqform->seqstart;
+               seqdataform->is_called = false;
        }
 
        /* crosscheck RESTART (or current value, if changing MIN/MAX) */
-       if (new->last_value < new->min_value)
+       if (seqdataform->last_value < seqform->seqmin)
        {
                char            bufs[100],
                                        bufm[100];
 
-               snprintf(bufs, sizeof(bufs), INT64_FORMAT, new->last_value);
-               snprintf(bufm, sizeof(bufm), INT64_FORMAT, new->min_value);
+               snprintf(bufs, sizeof(bufs), INT64_FORMAT, seqdataform->last_value);
+               snprintf(bufm, sizeof(bufm), INT64_FORMAT, seqform->seqmin);
                ereport(ERROR,
                                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                           errmsg("RESTART value (%s) cannot be less than MINVALUE (%s)",
                                          bufs, bufm)));
        }
-       if (new->last_value > new->max_value)
+       if (seqdataform->last_value > seqform->seqmax)
        {
                char            bufs[100],
                                        bufm[100];
 
-               snprintf(bufs, sizeof(bufs), INT64_FORMAT, new->last_value);
-               snprintf(bufm, sizeof(bufm), INT64_FORMAT, new->max_value);
+               snprintf(bufs, sizeof(bufs), INT64_FORMAT, seqdataform->last_value);
+               snprintf(bufm, sizeof(bufm), INT64_FORMAT, seqform->seqmax);
                ereport(ERROR,
                                (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                        errmsg("RESTART value (%s) cannot be greater than MAXVALUE (%s)",
@@ -1414,21 +1469,21 @@ init_params(ParseState *pstate, List *options, bool isInit,
        /* CACHE */
        if (cache_value != NULL)
        {
-               new->cache_value = defGetInt64(cache_value);
-               if (new->cache_value <= 0)
+               seqform->seqcache = defGetInt64(cache_value);
+               if (seqform->seqcache <= 0)
                {
                        char            buf[100];
 
-                       snprintf(buf, sizeof(buf), INT64_FORMAT, new->cache_value);
+                       snprintf(buf, sizeof(buf), INT64_FORMAT, seqform->seqcache);
                        ereport(ERROR,
                                        (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
                                         errmsg("CACHE (%s) must be greater than zero",
                                                        buf)));
                }
-               new->log_cnt = 0;
+               seqdataform->log_cnt = 0;
        }
        else if (isInit)
-               new->cache_value = 1;
+               seqform->seqcache = 1;
 }
 
 /*
@@ -1528,7 +1583,7 @@ process_owned_by(Relation seqrel, List *owned_by)
 
 
 /*
- * Return sequence parameters, for use by information schema
+ * Return sequence parameters (formerly for use by information schema)
  */
 Datum
 pg_sequence_parameters(PG_FUNCTION_ARGS)
@@ -1537,20 +1592,14 @@ pg_sequence_parameters(PG_FUNCTION_ARGS)
        TupleDesc       tupdesc;
        Datum           values[6];
        bool            isnull[6];
-       SeqTable        elm;
-       Relation        seqrel;
-       Buffer          buf;
-       HeapTupleData seqtuple;
-       Form_pg_sequence seq;
-
-       /* open and AccessShareLock sequence */
-       init_sequence(relid, &elm, &seqrel);
+       HeapTuple       pgstuple;
+       Form_pg_sequence pgsform;
 
        if (pg_class_aclcheck(relid, GetUserId(), ACL_SELECT | ACL_UPDATE | ACL_USAGE) != ACLCHECK_OK)
                ereport(ERROR,
                                (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
                                 errmsg("permission denied for sequence %s",
-                                               RelationGetRelationName(seqrel))));
+                                               get_rel_name(relid))));
 
        tupdesc = CreateTemplateTupleDesc(6, false);
        TupleDescInitEntry(tupdesc, (AttrNumber) 1, "start_value",
@@ -1570,17 +1619,19 @@ pg_sequence_parameters(PG_FUNCTION_ARGS)
 
        memset(isnull, 0, sizeof(isnull));
 
-       seq = read_seq_tuple(elm, seqrel, &buf, &seqtuple);
+       pgstuple = SearchSysCache1(SEQRELID, relid);
+       if (!HeapTupleIsValid(pgstuple))
+               elog(ERROR, "cache lookup failed for sequence %u", relid);
+       pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
 
-       values[0] = Int64GetDatum(seq->start_value);
-       values[1] = Int64GetDatum(seq->min_value);
-       values[2] = Int64GetDatum(seq->max_value);
-       values[3] = Int64GetDatum(seq->increment_by);
-       values[4] = BoolGetDatum(seq->is_cycled);
-       values[5] = Int64GetDatum(seq->cache_value);
+       values[0] = Int64GetDatum(pgsform->seqstart);
+       values[1] = Int64GetDatum(pgsform->seqmin);
+       values[2] = Int64GetDatum(pgsform->seqmax);
+       values[3] = Int64GetDatum(pgsform->seqincrement);
+       values[4] = BoolGetDatum(pgsform->seqcycle);
+       values[5] = Int64GetDatum(pgsform->seqcache);
 
-       UnlockReleaseBuffer(buf);
-       relation_close(seqrel, NoLock);
+       ReleaseSysCache(pgstuple);
 
        return HeapTupleGetDatum(heap_form_tuple(tupdesc, values, isnull));
 }
@@ -1598,7 +1649,7 @@ pg_sequence_last_value(PG_FUNCTION_ARGS)
        Relation        seqrel;
        Buffer          buf;
        HeapTupleData seqtuple;
-       Form_pg_sequence seq;
+       Form_pg_sequence_data seq;
        bool            is_called;
        int64           result;
 
@@ -1611,7 +1662,7 @@ pg_sequence_last_value(PG_FUNCTION_ARGS)
                                 errmsg("permission denied for sequence %s",
                                                RelationGetRelationName(seqrel))));
 
-       seq = read_seq_tuple(elm, seqrel, &buf, &seqtuple);
+       seq = read_seq_tuple(seqrel, &buf, &seqtuple);
 
        is_called = seq->is_called;
        result = seq->last_value;
index a3e0517b9408dc4421f412606ec9c125e090407f..e87fe0ef548443814d0adf5c3baba1e1485bcc84 100644 (file)
@@ -53,6 +53,7 @@
 #include "catalog/pg_range.h"
 #include "catalog/pg_rewrite.h"
 #include "catalog/pg_seclabel.h"
+#include "catalog/pg_sequence.h"
 #include "catalog/pg_shdepend.h"
 #include "catalog/pg_shdescription.h"
 #include "catalog/pg_shseclabel.h"
@@ -668,6 +669,17 @@ static const struct cachedesc cacheinfo[] = {
                },
                8
        },
+       {SequenceRelationId,                    /* SEQRELID */
+               SequenceRelidIndexId,
+               1,
+               {
+                       Anum_pg_sequence_seqrelid,
+                       0,
+                       0,
+                       0
+               },
+               32
+       },
        {StatisticRelationId,           /* STATRELATTINH */
                StatisticRelidAttnumInhIndexId,
                3,
index 7949aad3670a8d2a818a06a12a1e284f732b28b4..c5adc9da3883d5f554143dd5d5ea1e3bb12520e8 100644 (file)
@@ -15351,7 +15351,27 @@ dumpSequence(Archive *fout, TableInfo *tbinfo)
        snprintf(bufm, sizeof(bufm), INT64_FORMAT, SEQ_MINVALUE);
        snprintf(bufx, sizeof(bufx), INT64_FORMAT, SEQ_MAXVALUE);
 
-       if (fout->remoteVersion >= 80400)
+       if (fout->remoteVersion >= 100000)
+       {
+               appendPQExpBuffer(query,
+                                                 "SELECT relname, "
+                                                 "seqstart, seqincrement, "
+                                                 "CASE WHEN seqincrement > 0 AND seqmax = %s THEN NULL "
+                                                 "     WHEN seqincrement < 0 AND seqmax = -1 THEN NULL "
+                                                 "     ELSE seqmax "
+                                                 "END AS seqmax, "
+                                                 "CASE WHEN seqincrement > 0 AND seqmin = 1 THEN NULL "
+                                                 "     WHEN seqincrement < 0 AND seqmin = %s THEN NULL "
+                                                 "     ELSE seqmin "
+                                                 "END AS seqmin, "
+                                                 "seqcache, seqcycle "
+                                                 "FROM pg_class c "
+                                                 "JOIN pg_sequence s ON (s.seqrelid = c.oid) "
+                                                 "WHERE relname = ",
+                                                 bufx, bufm);
+               appendStringLiteralAH(query, tbinfo->dobj.name, fout);
+       }
+       else if (fout->remoteVersion >= 80400)
        {
                appendPQExpBuffer(query,
                                                  "SELECT sequence_name, "
index e13e3991df8c28f7d822a2562d758c50b0ba6415..5779f0d617feb27aeea2d4d08f32030e5c253faa 100644 (file)
@@ -53,6 +53,6 @@
  */
 
 /*                                                     yyyymmddN */
-#define CATALOG_VERSION_NO     201612121
+#define CATALOG_VERSION_NO     201612201
 
 #endif
index 40f7576b7b6bd618d1d2a822b0614a9c34b82aac..293985db4ecbef94c753c8c654b3b5d6774dffa5 100644 (file)
@@ -209,6 +209,9 @@ DECLARE_UNIQUE_INDEX(pg_rewrite_oid_index, 2692, on pg_rewrite using btree(oid o
 DECLARE_UNIQUE_INDEX(pg_rewrite_rel_rulename_index, 2693, on pg_rewrite using btree(ev_class oid_ops, rulename name_ops));
 #define RewriteRelRulenameIndexId  2693
 
+DECLARE_UNIQUE_INDEX(pg_sequence_seqrelid_index, 5002, on pg_sequence using btree(seqrelid oid_ops));
+#define SequenceRelidIndexId   5002
+
 DECLARE_INDEX(pg_shdepend_depender_index, 1232, on pg_shdepend using btree(dbid oid_ops, classid oid_ops, objid oid_ops, objsubid int4_ops));
 #define SharedDependDependerIndexId            1232
 DECLARE_INDEX(pg_shdepend_reference_index, 1233, on pg_shdepend using btree(refclassid oid_ops, refobjid oid_ops));
diff --git a/src/include/catalog/pg_sequence.h b/src/include/catalog/pg_sequence.h
new file mode 100644 (file)
index 0000000..3bcda6b
--- /dev/null
@@ -0,0 +1,30 @@
+#ifndef PG_SEQUENCE_H
+#define PG_SEQUENCE_H
+
+#include "catalog/genbki.h"
+
+#define SequenceRelationId     2224
+
+CATALOG(pg_sequence,2224) BKI_WITHOUT_OIDS
+{
+       Oid                     seqrelid;
+       int64           seqstart;
+       int64           seqincrement;
+       int64           seqmax;
+       int64           seqmin;
+       int64           seqcache;
+       bool            seqcycle;
+} FormData_pg_sequence;
+
+typedef FormData_pg_sequence *Form_pg_sequence;
+
+#define Natts_pg_sequence                              7
+#define Anum_pg_sequence_seqrelid              1
+#define Anum_pg_sequence_seqstart              2
+#define Anum_pg_sequence_seqincrement  3
+#define Anum_pg_sequence_seqmax                        4
+#define Anum_pg_sequence_seqmin                        5
+#define Anum_pg_sequence_seqcache              6
+#define Anum_pg_sequence_seqcycle              7
+
+#endif /* PG_SEQUENCE_H */
index 6695bbe4c7accafe89915e02865d946ce43ce5a1..1fd75b216df549979c40659fb261a67bfe90b76d 100644 (file)
 #include "storage/relfilenode.h"
 
 
-typedef struct FormData_pg_sequence
+typedef struct FormData_pg_sequence_data
 {
-       NameData        sequence_name;
        int64           last_value;
-       int64           start_value;
-       int64           increment_by;
-       int64           max_value;
-       int64           min_value;
-       int64           cache_value;
        int64           log_cnt;
-       bool            is_cycled;
        bool            is_called;
-} FormData_pg_sequence;
+} FormData_pg_sequence_data;
 
-typedef FormData_pg_sequence *Form_pg_sequence;
+typedef FormData_pg_sequence_data *Form_pg_sequence_data;
 
 /*
  * Columns of a sequence relation
  */
 
-#define SEQ_COL_NAME                   1
-#define SEQ_COL_LASTVAL                        2
-#define SEQ_COL_STARTVAL               3
-#define SEQ_COL_INCBY                  4
-#define SEQ_COL_MAXVALUE               5
-#define SEQ_COL_MINVALUE               6
-#define SEQ_COL_CACHE                  7
-#define SEQ_COL_LOG                            8
-#define SEQ_COL_CYCLE                  9
-#define SEQ_COL_CALLED                 10
+#define SEQ_COL_LASTVAL                        1
+#define SEQ_COL_LOG                            2
+#define SEQ_COL_CALLED                 3
 
-#define SEQ_COL_FIRSTCOL               SEQ_COL_NAME
+#define SEQ_COL_FIRSTCOL               SEQ_COL_LASTVAL
 #define SEQ_COL_LASTCOL                        SEQ_COL_CALLED
 
 /* XLOG stuff */
@@ -77,6 +63,7 @@ extern Datum pg_sequence_last_value(PG_FUNCTION_ARGS);
 
 extern ObjectAddress DefineSequence(ParseState *pstate, CreateSeqStmt *stmt);
 extern ObjectAddress AlterSequence(ParseState *pstate, AlterSeqStmt *stmt);
+extern void DeleteSequenceTuple(Oid relid);
 extern void ResetSequence(Oid seq_relid);
 extern void ResetSequenceCaches(void);
 
index 39fe947d6e78a97e55741402b8ecd2bcc88407ad..4b7631e76345b87b351466905e5fc6131f532045 100644 (file)
@@ -81,6 +81,7 @@ enum SysCacheIdentifier
        REPLORIGIDENT,
        REPLORIGNAME,
        RULERELNAME,
+       SEQRELID,
        STATRELATTINH,
        TABLESPACEOID,
        TRFOID,
index 5314b9c207fdfd059c10f3fb18045c2939a82564..e9cfadbc0f15da2a638bc0bccaa6a743d11403f2 100644 (file)
@@ -1623,16 +1623,16 @@ UNION ALL
 pg_sequences| SELECT n.nspname AS schemaname,
     c.relname AS sequencename,
     pg_get_userbyid(c.relowner) AS sequenceowner,
-    p.start_value,
-    p.minimum_value AS min_value,
-    p.maximum_value AS max_value,
-    p.increment AS increment_by,
-    p.cycle_option AS cycle,
-    p.cache_size,
+    s.seqstart AS start_value,
+    s.seqmin AS min_value,
+    s.seqmax AS max_value,
+    s.seqincrement AS increment_by,
+    s.seqcycle AS cycle,
+    s.seqcache AS cache_size,
     pg_sequence_last_value((c.oid)::regclass) AS last_value
-   FROM (pg_class c
-     LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace))),
-    LATERAL pg_sequence_parameters(c.oid) p(start_value, minimum_value, maximum_value, increment, cycle_option, cache_size)
+   FROM ((pg_sequence s
+     JOIN pg_class c ON ((c.oid = s.seqrelid)))
+     LEFT JOIN pg_namespace n ON ((n.oid = c.relnamespace)))
   WHERE ((NOT pg_is_other_temp_schema(n.oid)) AND (c.relkind = 'S'::"char"));
 pg_settings| SELECT a.name,
     a.setting,
index 8fa929a6aa3016dd6c8c11beccd10a0bf8b123df..7ad68c745b0ead5d8e7d4fff50a129986a951ff0 100644 (file)
@@ -128,6 +128,7 @@ pg_range|t
 pg_replication_origin|t
 pg_rewrite|t
 pg_seclabel|t
+pg_sequence|t
 pg_shdepend|t
 pg_shdescription|t
 pg_shseclabel|t
index c5413e09f3b0e99b8629396d7342b58acba4ac2c..a2bdd3002b0fa110db541791c6311eec2a413973 100644 (file)
@@ -173,9 +173,9 @@ DROP SEQUENCE sequence_test;
 CREATE SEQUENCE foo_seq;
 ALTER TABLE foo_seq RENAME TO foo_seq_new;
 SELECT * FROM foo_seq_new;
sequence_name | last_value | start_value | increment_by |      max_value      | min_value | cache_value | log_cnt | is_cycled | is_called 
----------------+------------+-------------+--------------+---------------------+-----------+-------------+---------+-----------+-----------
foo_seq       |          1 |           1 |            1 | 9223372036854775807 |         1 |           1 |       0 | f         | f
last_value | log_cnt | is_called 
+------------+---------+-----------
         1 |       0 | f
 (1 row)
 
 SELECT nextval('foo_seq_new');
@@ -191,9 +191,9 @@ SELECT nextval('foo_seq_new');
 (1 row)
 
 SELECT * FROM foo_seq_new;
sequence_name | last_value | start_value | increment_by |      max_value      | min_value | cache_value | log_cnt | is_cycled | is_called 
----------------+------------+-------------+--------------+---------------------+-----------+-------------+---------+-----------+-----------
foo_seq       |          2 |           1 |            1 | 9223372036854775807 |         1 |           1 |      31 | f         | t
last_value | log_cnt | is_called 
+------------+---------+-----------
         2 |      31 | t
 (1 row)
 
 DROP SEQUENCE foo_seq_new;
@@ -536,3 +536,24 @@ SELECT * FROM information_schema.sequences WHERE sequence_name IN
 
 DROP USER regress_seq_user;
 DROP SEQUENCE seq;
+-- cache tests
+CREATE SEQUENCE test_seq1 CACHE 10;
+SELECT nextval('test_seq1');
+ nextval 
+---------
+       1
+(1 row)
+
+SELECT nextval('test_seq1');
+ nextval 
+---------
+       2
+(1 row)
+
+SELECT nextval('test_seq1');
+ nextval 
+---------
+       3
+(1 row)
+
+DROP SEQUENCE test_seq1;
index 79ddbdee4f7ed0ab3b6fb50cb4f16cf50b183fd9..8201d77a561395b99eda8b52bdbe0d175c63b9ca 100644 (file)
@@ -86,55 +86,48 @@ SELECT table_name, column_name, is_updatable
   FROM information_schema.columns
  WHERE table_name LIKE E'r_\\_view%'
  ORDER BY table_name, ordinal_position;
- table_name |  column_name  | is_updatable 
-------------+---------------+--------------
- ro_view1   | a             | NO
- ro_view1   | b             | NO
- ro_view10  | a             | NO
- ro_view11  | a             | NO
- ro_view11  | b             | NO
- ro_view12  | a             | NO
- ro_view13  | a             | NO
- ro_view13  | b             | NO
- ro_view17  | a             | NO
- ro_view17  | b             | NO
- ro_view18  | a             | NO
- ro_view19  | sequence_name | NO
- ro_view19  | last_value    | NO
- ro_view19  | start_value   | NO
- ro_view19  | increment_by  | NO
- ro_view19  | max_value     | NO
- ro_view19  | min_value     | NO
- ro_view19  | cache_value   | NO
- ro_view19  | log_cnt       | NO
- ro_view19  | is_cycled     | NO
- ro_view19  | is_called     | NO
- ro_view2   | a             | NO
- ro_view2   | b             | NO
- ro_view20  | a             | NO
- ro_view20  | b             | NO
- ro_view20  | g             | NO
- ro_view3   | ?column?      | NO
- ro_view4   | count         | NO
- ro_view5   | a             | NO
- ro_view5   | rank          | NO
- ro_view6   | a             | NO
- ro_view6   | b             | NO
- ro_view7   | a             | NO
- ro_view7   | b             | NO
- ro_view8   | a             | NO
- ro_view8   | b             | NO
- ro_view9   | a             | NO
- ro_view9   | b             | NO
- rw_view14  | ctid          | NO
- rw_view14  | a             | YES
- rw_view14  | b             | YES
- rw_view15  | a             | YES
- rw_view15  | upper         | NO
- rw_view16  | a             | YES
- rw_view16  | b             | YES
- rw_view16  | aa            | YES
-(46 rows)
+ table_name | column_name | is_updatable 
+------------+-------------+--------------
+ ro_view1   | a           | NO
+ ro_view1   | b           | NO
+ ro_view10  | a           | NO
+ ro_view11  | a           | NO
+ ro_view11  | b           | NO
+ ro_view12  | a           | NO
+ ro_view13  | a           | NO
+ ro_view13  | b           | NO
+ ro_view17  | a           | NO
+ ro_view17  | b           | NO
+ ro_view18  | a           | NO
+ ro_view19  | last_value  | NO
+ ro_view19  | log_cnt     | NO
+ ro_view19  | is_called   | NO
+ ro_view2   | a           | NO
+ ro_view2   | b           | NO
+ ro_view20  | a           | NO
+ ro_view20  | b           | NO
+ ro_view20  | g           | NO
+ ro_view3   | ?column?    | NO
+ ro_view4   | count       | NO
+ ro_view5   | a           | NO
+ ro_view5   | rank        | NO
+ ro_view6   | a           | NO
+ ro_view6   | b           | NO
+ ro_view7   | a           | NO
+ ro_view7   | b           | NO
+ ro_view8   | a           | NO
+ ro_view8   | b           | NO
+ ro_view9   | a           | NO
+ ro_view9   | b           | NO
+ rw_view14  | ctid        | NO
+ rw_view14  | a           | YES
+ rw_view14  | b           | YES
+ rw_view15  | a           | YES
+ rw_view15  | upper       | NO
+ rw_view16  | a           | YES
+ rw_view16  | b           | YES
+ rw_view16  | aa          | YES
+(39 rows)
 
 -- Read-only views
 DELETE FROM ro_view1;
@@ -327,7 +320,7 @@ DELETE FROM ro_view18;
 ERROR:  cannot delete from view "ro_view18"
 DETAIL:  Views that do not select from a single table or view are not automatically updatable.
 HINT:  To enable deleting from the view, provide an INSTEAD OF DELETE trigger or an unconditional ON DELETE DO INSTEAD rule.
-UPDATE ro_view19 SET max_value=1000;
+UPDATE ro_view19 SET last_value=1000;
 ERROR:  cannot update view "ro_view19"
 DETAIL:  Views that do not select from a single table or view are not automatically updatable.
 HINT:  To enable updating the view, provide an INSTEAD OF UPDATE trigger or an unconditional ON UPDATE DO INSTEAD rule.
index e2b6b6339305a0af59b53e778f6ec1f9d9b6e9e0..a79330e78043539ae8395981f6ab6de89e599cee 100644 (file)
@@ -273,3 +273,11 @@ SELECT * FROM information_schema.sequences WHERE sequence_name IN
 
 DROP USER regress_seq_user;
 DROP SEQUENCE seq;
+
+-- cache tests
+CREATE SEQUENCE test_seq1 CACHE 10;
+SELECT nextval('test_seq1');
+SELECT nextval('test_seq1');
+SELECT nextval('test_seq1');
+
+DROP SEQUENCE test_seq1;
index 03c3f9d35ebe3207cb5fbd78e0ce23874500f09f..f008479541644814f621b848e2cb96b4394b0ec2 100644 (file)
@@ -95,7 +95,7 @@ DELETE FROM rw_view16 WHERE a=-3; -- should be OK
 -- Read-only views
 INSERT INTO ro_view17 VALUES (3, 'ROW 3');
 DELETE FROM ro_view18;
-UPDATE ro_view19 SET max_value=1000;
+UPDATE ro_view19 SET last_value=1000;
 UPDATE ro_view20 SET b=upper(b);
 
 DROP TABLE base_tbl CASCADE;