]> granicus.if.org Git - postgresql/commitdiff
Allow ALTER SEQUENCE START WITH to change the recorded start_value of a
authorTom Lane <tgl@sss.pgh.pa.us>
Sat, 17 May 2008 01:20:39 +0000 (01:20 +0000)
committerTom Lane <tgl@sss.pgh.pa.us>
Sat, 17 May 2008 01:20:39 +0000 (01:20 +0000)
sequence.  This seems an obvious extension to the recent patch, and it
makes the code noticeably cleaner and more orthogonal.

doc/src/sgml/ref/alter_sequence.sgml
src/backend/commands/sequence.c

index 31e64dac35d85948d4c817baf3fc2bfba17b48ae..7cf69e9ea3faadbeff36f49e6395f2d4093fe0a5 100644 (file)
@@ -1,5 +1,5 @@
 <!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/alter_sequence.sgml,v 1.20 2008/05/16 23:36:04 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/alter_sequence.sgml,v 1.21 2008/05/17 01:20:39 tgl Exp $
 PostgreSQL documentation
 -->
 
@@ -26,7 +26,9 @@ PostgreSQL documentation
   <synopsis>
 ALTER SEQUENCE <replaceable class="parameter">name</replaceable> [ INCREMENT [ BY ] <replaceable class="parameter">increment</replaceable> ]
     [ MINVALUE <replaceable class="parameter">minvalue</replaceable> | NO MINVALUE ] [ MAXVALUE <replaceable class="parameter">maxvalue</replaceable> | NO MAXVALUE ]
-    [ RESTART [ [ WITH ] <replaceable class="parameter">start</replaceable> ] ] [ CACHE <replaceable class="parameter">cache</replaceable> ] [ [ NO ] CYCLE ]
+    [ START [ WITH ] <replaceable class="parameter">start</replaceable> ]
+    [ RESTART [ [ WITH ] <replaceable class="parameter">restart</replaceable> ] ]
+    [ CACHE <replaceable class="parameter">cache</replaceable> ] [ [ NO ] CYCLE ]
     [ OWNED BY { <replaceable class="parameter">table</replaceable>.<replaceable class="parameter">column</replaceable> | NONE } ]
 ALTER SEQUENCE <replaceable class="parameter">name</replaceable> RENAME TO <replaceable class="parameter">new_name</replaceable>
 ALTER SEQUENCE <replaceable class="parameter">name</replaceable> SET SCHEMA <replaceable class="parameter">new_schema</replaceable>
@@ -110,17 +112,31 @@ ALTER SEQUENCE <replaceable class="parameter">name</replaceable> SET SCHEMA <rep
 
      <varlistentry>
       <term><replaceable class="parameter">start</replaceable></term>
+      <listitem>
+       <para>
+        The optional clause <literal>START WITH <replaceable
+        class="parameter">start</replaceable></literal> changes the
+        recorded start value of the sequence.  This has no effect on the
+        <emphasis>current</> sequence value; it simply sets the value
+        that future <command>ALTER SEQUENCE RESTART</> commands will use.
+       </para>
+      </listitem>
+     </varlistentry>
+
+     <varlistentry>
+      <term><replaceable class="parameter">restart</replaceable></term>
       <listitem>
        <para>
         The optional clause <literal>RESTART [ WITH <replaceable
-        class="parameter">start</replaceable> ]</literal> changes the
+        class="parameter">restart</replaceable> ]</literal> changes the
         current value of the sequence.  This is equivalent to calling the
         <function>setval</> function with <literal>is_called</literal> =
         <literal>false</>: the specified value will be returned by the
         <emphasis>next</> call of <function>nextval</>.
         Writing <literal>RESTART</> with no <replaceable
-        class="parameter">start</replaceable> value is equivalent to supplying
-        the start value used when the sequence was created.
+        class="parameter">restart</> value is equivalent to supplying
+        the start value that was recorded by <command>CREATE SEQUENCE</>
+        or last set by <command>ALTER SEQUENCE START WITH</>.
        </para>
       </listitem>
      </varlistentry>
@@ -261,7 +277,8 @@ ALTER SEQUENCE serial RESTART WITH 105;
 
   <para>
    <command>ALTER SEQUENCE</command> conforms to the <acronym>SQL</acronym>
-   standard, except for the <literal>OWNED BY</>, <literal>RENAME</>, and
+   standard, except for the <literal>START WITH</>,
+   <literal>OWNED BY</>, <literal>RENAME</>, and
    <literal>SET SCHEMA</literal> clauses, which are
    <productname>PostgreSQL</productname> extensions.
   </para>
index 748413ebed3843acc117bc4dfe7139e91d21b327..5d5a3a243c4c8bfe63d7414b4e4082dd6dd92a2a 100644 (file)
@@ -8,7 +8,7 @@
  *
  *
  * IDENTIFICATION
- *       $PostgreSQL: pgsql/src/backend/commands/sequence.c,v 1.151 2008/05/16 23:36:04 tgl Exp $
+ *       $PostgreSQL: pgsql/src/backend/commands/sequence.c,v 1.152 2008/05/17 01:20:39 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -91,7 +91,7 @@ static Relation open_share_lock(SeqTable seq);
 static void init_sequence(Oid relid, SeqTable *p_elm, Relation *p_rel);
 static Form_pg_sequence read_info(SeqTable elm, Relation rel, Buffer *buf);
 static void init_params(List *options, bool isInit,
-                       Form_pg_sequence new, Form_pg_sequence old, List **owned_by);
+                       Form_pg_sequence new, List **owned_by);
 static void do_setval(Oid relid, int64 next, bool iscalled);
 static void process_owned_by(Relation seqrel, List *owned_by);
 
@@ -119,7 +119,7 @@ DefineSequence(CreateSeqStmt *seq)
        NameData        name;
 
        /* Check and set all option values */
-       init_params(seq->options, true, &new, NULL, &owned_by);
+       init_params(seq->options, true, &new, &owned_by);
 
        /*
         * Create relation (and fill value[] and null[] for the tuple)
@@ -357,8 +357,11 @@ AlterSequenceInternal(Oid relid, List *options)
        seq = read_info(elm, seqrel, &buf);
        page = BufferGetPage(buf);
 
-       /* Fill workspace with appropriate new info */
-       init_params(options, false, &new, seq, &owned_by);
+       /* Copy old values of options into workspace */
+       memcpy(&new, seq, sizeof(FormData_pg_sequence));
+
+       /* Check and set new values */
+       init_params(options, false, &new, &owned_by);
 
        /* Clear local cache so that we don't think we have cached numbers */
        /* Note that we do not change the currval() state */
@@ -989,9 +992,10 @@ read_info(SeqTable elm, Relation rel, Buffer *buf)
  */
 static void
 init_params(List *options, bool isInit,
-                       Form_pg_sequence new, Form_pg_sequence old, List **owned_by)
+                       Form_pg_sequence new, List **owned_by)
 {
-       DefElem    *last_value = NULL;
+       DefElem    *start_value = NULL;
+       DefElem    *restart_value = NULL;
        DefElem    *increment_by = NULL;
        DefElem    *max_value = NULL;
        DefElem    *min_value = NULL;
@@ -1001,12 +1005,6 @@ init_params(List *options, bool isInit,
 
        *owned_by = NIL;
 
-       /* Copy old values of options into workspace */
-       if (old != NULL)
-               memcpy(new, old, sizeof(FormData_pg_sequence));
-       else
-               memset(new, 0, sizeof(FormData_pg_sequence));
-
        foreach(option, options)
        {
                DefElem    *defel = (DefElem *) lfirst(option);
@@ -1021,27 +1019,19 @@ init_params(List *options, bool isInit,
                }
                else if (strcmp(defel->defname, "start") == 0)
                {
-                       if (!isInit)
-                               ereport(ERROR,
-                                               (errcode(ERRCODE_SYNTAX_ERROR),
-                                                errmsg("use RESTART not START in ALTER SEQUENCE")));
-                       if (last_value)
+                       if (start_value)
                                ereport(ERROR,
                                                (errcode(ERRCODE_SYNTAX_ERROR),
                                                 errmsg("conflicting or redundant options")));
-                       last_value = defel;
+                       start_value = defel;
                }
                else if (strcmp(defel->defname, "restart") == 0)
                {
-                       if (isInit)
-                               ereport(ERROR,
-                                               (errcode(ERRCODE_SYNTAX_ERROR),
-                                                errmsg("use START not RESTART in CREATE SEQUENCE")));
-                       if (last_value)
+                       if (restart_value)
                                ereport(ERROR,
                                                (errcode(ERRCODE_SYNTAX_ERROR),
                                                 errmsg("conflicting or redundant options")));
-                       last_value = defel;
+                       restart_value = defel;
                }
                else if (strcmp(defel->defname, "maxvalue") == 0)
                {
@@ -1145,30 +1135,15 @@ init_params(List *options, bool isInit,
                                                bufm, bufx)));
        }
 
-       /* START/RESTART [WITH] */
-       if (last_value != NULL)
-       {
-               if (last_value->arg != NULL)
-                       new->last_value = defGetInt64(last_value);
-               else
-               {
-                       Assert(old != NULL);
-                       new->last_value = old->start_value;
-               }
-               if (isInit)
-                       new->start_value = new->last_value;
-               new->is_called = false;
-               new->log_cnt = 1;
-       }
+       /* START WITH */
+       if (start_value != NULL)
+               new->start_value = defGetInt64(start_value);
        else if (isInit)
        {
                if (new->increment_by > 0)
                        new->start_value = new->min_value;      /* ascending seq */
                else
                        new->start_value = new->max_value;      /* descending seq */
-               new->last_value = new->start_value;
-               new->is_called = false;
-               new->log_cnt = 1;
        }
 
        /* crosscheck START */
@@ -1197,7 +1172,24 @@ init_params(List *options, bool isInit,
                                         bufs, bufm)));
        }
 
-       /* must crosscheck RESTART separately */
+       /* RESTART [WITH] */
+       if (restart_value != NULL)
+       {
+               if (restart_value->arg != NULL)
+                       new->last_value = defGetInt64(restart_value);
+               else
+                       new->last_value = new->start_value;
+               new->is_called = false;
+               new->log_cnt = 1;
+       }
+       else if (isInit)
+       {
+               new->last_value = new->start_value;
+               new->is_called = false;
+               new->log_cnt = 1;
+       }
+
+       /* crosscheck RESTART (or current value, if changing MIN/MAX) */
        if (new->last_value < new->min_value)
        {
                char            bufs[100],