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],