-<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.404 2007/10/23 20:46:11 tgl Exp $ -->
+<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.405 2007/10/25 18:54:03 tgl Exp $ -->
<chapter id="functions">
<title>Functions and Operators</title>
<listitem>
<para>
Reset the sequence object's counter value. The two-parameter
- form sets the sequence's <literal>last_value</literal> field to the specified
- value and sets its <literal>is_called</literal> field to <literal>true</literal>,
- meaning that the next <function>nextval</function> will advance the sequence
- before returning a value. In the three-parameter form,
- <literal>is_called</literal> can be set either <literal>true</literal> or
- <literal>false</literal>. If it's set to <literal>false</literal>,
- the next <function>nextval</function> will return exactly the specified
+ form sets the sequence's <literal>last_value</literal> field to the
+ specified value and sets its <literal>is_called</literal> field to
+ <literal>true</literal>, meaning that the next
+ <function>nextval</function> will advance the sequence before
+ returning a value. The value reported by <function>currval</> is
+ also set to the specified value. In the three-parameter form,
+ <literal>is_called</literal> can be set either <literal>true</literal>
+ or <literal>false</literal>. <literal>true</> has the same effect as
+ the two-parameter form. If it's set to <literal>false</literal>, the
+ next <function>nextval</function> will return exactly the specified
value, and sequence advancement commences with the following
- <function>nextval</function>. For example,
+ <function>nextval</function>. Furthermore, the value reported by
+ <function>currval</> is not changed in this case (this is a change
+ from pre-8.3 behavior). For example,
<screen>
SELECT setval('foo', 42); <lineannotation>Next <function>nextval</> will return 43</lineannotation>
<!--
-$PostgreSQL: pgsql/doc/src/sgml/ref/alter_sequence.sgml,v 1.18 2007/10/03 16:48:43 tgl Exp $
+$PostgreSQL: pgsql/doc/src/sgml/ref/alter_sequence.sgml,v 1.19 2007/10/25 18:54:03 tgl Exp $
PostgreSQL documentation
-->
<para>
The optional clause <literal>RESTART WITH <replaceable
class="parameter">start</replaceable></literal> changes the
- current value of the sequence.
+ 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</>.
</para>
</listitem>
</varlistentry>
immediately.
</para>
+ <para>
+ <command>ALTER SEQUENCE</command> does not affect the <function>currval</>
+ status for the sequence. (Before <productname>PostgreSQL</productname>
+ 8.3, it sometimes did.)
+ </para>
+
<para>
Some variants of <command>ALTER TABLE</command> can be used with
sequences as well; for example, to rename a sequence it is also
*
*
* IDENTIFICATION
- * $PostgreSQL: pgsql/src/backend/commands/sequence.c,v 1.146 2007/09/20 17:56:31 tgl Exp $
+ * $PostgreSQL: pgsql/src/backend/commands/sequence.c,v 1.147 2007/10/25 18:54:03 tgl Exp $
*
*-------------------------------------------------------------------------
*/
struct SeqTableData *next; /* link to next SeqTable object */
Oid relid; /* pg_class OID of this sequence */
LocalTransactionId lxid; /* xact in which we last did a seq op */
+ bool last_valid; /* do we have a valid "last" value? */
int64 last; /* value last returned by nextval */
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_info() */
} SeqTableData;
typedef SeqTableData *SeqTable;
/* Check and set new values */
init_params(stmt->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 */
+ elm->cached = elm->last;
+
/* Now okay to update the on-disk tuple */
memcpy(seq, &new, sizeof(FormData_pg_sequence));
- /* Clear local cache so that we don't think we have cached numbers */
- elm->last = new.last_value; /* last returned number */
- elm->cached = new.last_value; /* last cached number (forget cached
- * values) */
-
START_CRIT_SECTION();
MarkBufferDirty(buf);
if (elm->last != elm->cached) /* some numbers were cached */
{
- last_used_seq = elm;
+ Assert(elm->last_valid);
+ Assert(elm->increment != 0);
elm->last += elm->increment;
relation_close(seqrel, NoLock);
+ last_used_seq = elm;
return elm->last;
}
/* save info in local cache */
elm->last = result; /* last returned number */
elm->cached = last; /* last fetched number */
+ elm->last_valid = true;
last_used_seq = elm;
errmsg("permission denied for sequence %s",
RelationGetRelationName(seqrel))));
- if (elm->increment == 0) /* nextval/read_info were not called */
+ if (!elm->last_valid)
ereport(ERROR,
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
errmsg("currval of sequence \"%s\" is not yet defined in this session",
seqrel = open_share_lock(last_used_seq);
/* nextval() must have already been called for this sequence */
- Assert(last_used_seq->increment != 0);
+ Assert(last_used_seq->last_valid);
if (pg_class_aclcheck(last_used_seq->relid, GetUserId(), ACL_SELECT) != ACLCHECK_OK &&
pg_class_aclcheck(last_used_seq->relid, GetUserId(), ACL_USAGE) != ACLCHECK_OK)
bufm, bufx)));
}
- /* save info in local cache */
- elm->last = next; /* last returned number */
- elm->cached = next; /* last cached number (forget cached values) */
+ /* Set the currval() state only if iscalled = true */
+ if (iscalled)
+ {
+ elm->last = next; /* last returned number */
+ elm->last_valid = true;
+ }
+
+ /* In any case, forget any future cached numbers */
+ elm->cached = elm->last;
START_CRIT_SECTION();
errmsg("out of memory")));
elm->relid = relid;
elm->lxid = InvalidLocalTransactionId;
- /* increment is set to 0 until we do read_info (see currval) */
+ elm->last_valid = false;
elm->last = elm->cached = elm->increment = 0;
elm->next = seqtab;
seqtab = elm;
seq = (Form_pg_sequence) GETSTRUCT(&tuple);
+ /* this is a handy place to update our copy of the increment */
elm->increment = seq->increment_by;
return seq;