Location via proxy:   [ UP ]  
[Report a bug]   [Manage cookies]                
Skip to content

Commit 9ddfe03

Browse files
committed
Fix ALTER SEQUENCE so that it does not affect the value of currval() for
the sequence. Also, make setval() with is_called = false not affect the currval state, either. Per report from Kris Jurka that an implicit ALTER SEQUENCE OWNED BY unexpectedly caused currval() to become valid. Since this isn't 100% backwards compatible, it will go into HEAD only; I'll put a more limited patch into 8.2.
1 parent dbe4876 commit 9ddfe03

File tree

3 files changed

+49
-24
lines changed

3 files changed

+49
-24
lines changed

doc/src/sgml/func.sgml

+14-9
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.404 2007/10/23 20:46:11 tgl Exp $ -->
1+
<!-- $PostgreSQL: pgsql/doc/src/sgml/func.sgml,v 1.405 2007/10/25 18:54:03 tgl Exp $ -->
22

33
<chapter id="functions">
44
<title>Functions and Operators</title>
@@ -8733,15 +8733,20 @@ nextval('foo'::text) <lineannotation><literal>foo</literal> is looked up at
87338733
<listitem>
87348734
<para>
87358735
Reset the sequence object's counter value. The two-parameter
8736-
form sets the sequence's <literal>last_value</literal> field to the specified
8737-
value and sets its <literal>is_called</literal> field to <literal>true</literal>,
8738-
meaning that the next <function>nextval</function> will advance the sequence
8739-
before returning a value. In the three-parameter form,
8740-
<literal>is_called</literal> can be set either <literal>true</literal> or
8741-
<literal>false</literal>. If it's set to <literal>false</literal>,
8742-
the next <function>nextval</function> will return exactly the specified
8736+
form sets the sequence's <literal>last_value</literal> field to the
8737+
specified value and sets its <literal>is_called</literal> field to
8738+
<literal>true</literal>, meaning that the next
8739+
<function>nextval</function> will advance the sequence before
8740+
returning a value. The value reported by <function>currval</> is
8741+
also set to the specified value. In the three-parameter form,
8742+
<literal>is_called</literal> can be set either <literal>true</literal>
8743+
or <literal>false</literal>. <literal>true</> has the same effect as
8744+
the two-parameter form. If it's set to <literal>false</literal>, the
8745+
next <function>nextval</function> will return exactly the specified
87438746
value, and sequence advancement commences with the following
8744-
<function>nextval</function>. For example,
8747+
<function>nextval</function>. Furthermore, the value reported by
8748+
<function>currval</> is not changed in this case (this is a change
8749+
from pre-8.3 behavior). For example,
87458750

87468751
<screen>
87478752
SELECT setval('foo', 42); <lineannotation>Next <function>nextval</> will return 43</lineannotation>

doc/src/sgml/ref/alter_sequence.sgml

+11-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
<!--
2-
$PostgreSQL: pgsql/doc/src/sgml/ref/alter_sequence.sgml,v 1.18 2007/10/03 16:48:43 tgl Exp $
2+
$PostgreSQL: pgsql/doc/src/sgml/ref/alter_sequence.sgml,v 1.19 2007/10/25 18:54:03 tgl Exp $
33
PostgreSQL documentation
44
-->
55

@@ -114,7 +114,10 @@ ALTER SEQUENCE <replaceable class="parameter">name</replaceable> SET SCHEMA <rep
114114
<para>
115115
The optional clause <literal>RESTART WITH <replaceable
116116
class="parameter">start</replaceable></literal> changes the
117-
current value of the sequence.
117+
current value of the sequence. This is equivalent to calling the
118+
<function>setval</> function with <literal>is_called</literal> =
119+
<literal>false</>: the specified value will be returned by the
120+
<emphasis>next</> call of <function>nextval</>.
118121
</para>
119122
</listitem>
120123
</varlistentry>
@@ -226,6 +229,12 @@ ALTER SEQUENCE <replaceable class="parameter">name</replaceable> SET SCHEMA <rep
226229
immediately.
227230
</para>
228231

232+
<para>
233+
<command>ALTER SEQUENCE</command> does not affect the <function>currval</>
234+
status for the sequence. (Before <productname>PostgreSQL</productname>
235+
8.3, it sometimes did.)
236+
</para>
237+
229238
<para>
230239
Some variants of <command>ALTER TABLE</command> can be used with
231240
sequences as well; for example, to rename a sequence it is also

src/backend/commands/sequence.c

+24-13
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88
*
99
*
1010
* IDENTIFICATION
11-
* $PostgreSQL: pgsql/src/backend/commands/sequence.c,v 1.146 2007/09/20 17:56:31 tgl Exp $
11+
* $PostgreSQL: pgsql/src/backend/commands/sequence.c,v 1.147 2007/10/25 18:54:03 tgl Exp $
1212
*
1313
*-------------------------------------------------------------------------
1414
*/
@@ -65,10 +65,12 @@ typedef struct SeqTableData
6565
struct SeqTableData *next; /* link to next SeqTable object */
6666
Oid relid; /* pg_class OID of this sequence */
6767
LocalTransactionId lxid; /* xact in which we last did a seq op */
68+
bool last_valid; /* do we have a valid "last" value? */
6869
int64 last; /* value last returned by nextval */
6970
int64 cached; /* last value already cached for nextval */
7071
/* if last != cached, we have not used up all the cached values */
7172
int64 increment; /* copy of sequence's increment field */
73+
/* note that increment is zero until we first do read_info() */
7274
} SeqTableData;
7375

7476
typedef SeqTableData *SeqTable;
@@ -336,14 +338,13 @@ AlterSequence(AlterSeqStmt *stmt)
336338
/* Check and set new values */
337339
init_params(stmt->options, false, &new, &owned_by);
338340

341+
/* Clear local cache so that we don't think we have cached numbers */
342+
/* Note that we do not change the currval() state */
343+
elm->cached = elm->last;
344+
339345
/* Now okay to update the on-disk tuple */
340346
memcpy(seq, &new, sizeof(FormData_pg_sequence));
341347

342-
/* Clear local cache so that we don't think we have cached numbers */
343-
elm->last = new.last_value; /* last returned number */
344-
elm->cached = new.last_value; /* last cached number (forget cached
345-
* values) */
346-
347348
START_CRIT_SECTION();
348349

349350
MarkBufferDirty(buf);
@@ -443,9 +444,11 @@ nextval_internal(Oid relid)
443444

444445
if (elm->last != elm->cached) /* some numbers were cached */
445446
{
446-
last_used_seq = elm;
447+
Assert(elm->last_valid);
448+
Assert(elm->increment != 0);
447449
elm->last += elm->increment;
448450
relation_close(seqrel, NoLock);
451+
last_used_seq = elm;
449452
return elm->last;
450453
}
451454

@@ -564,6 +567,7 @@ nextval_internal(Oid relid)
564567
/* save info in local cache */
565568
elm->last = result; /* last returned number */
566569
elm->cached = last; /* last fetched number */
570+
elm->last_valid = true;
567571

568572
last_used_seq = elm;
569573

@@ -633,7 +637,7 @@ currval_oid(PG_FUNCTION_ARGS)
633637
errmsg("permission denied for sequence %s",
634638
RelationGetRelationName(seqrel))));
635639

636-
if (elm->increment == 0) /* nextval/read_info were not called */
640+
if (!elm->last_valid)
637641
ereport(ERROR,
638642
(errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
639643
errmsg("currval of sequence \"%s\" is not yet defined in this session",
@@ -668,7 +672,7 @@ lastval(PG_FUNCTION_ARGS)
668672
seqrel = open_share_lock(last_used_seq);
669673

670674
/* nextval() must have already been called for this sequence */
671-
Assert(last_used_seq->increment != 0);
675+
Assert(last_used_seq->last_valid);
672676

673677
if (pg_class_aclcheck(last_used_seq->relid, GetUserId(), ACL_SELECT) != ACLCHECK_OK &&
674678
pg_class_aclcheck(last_used_seq->relid, GetUserId(), ACL_USAGE) != ACLCHECK_OK)
@@ -732,9 +736,15 @@ do_setval(Oid relid, int64 next, bool iscalled)
732736
bufm, bufx)));
733737
}
734738

735-
/* save info in local cache */
736-
elm->last = next; /* last returned number */
737-
elm->cached = next; /* last cached number (forget cached values) */
739+
/* Set the currval() state only if iscalled = true */
740+
if (iscalled)
741+
{
742+
elm->last = next; /* last returned number */
743+
elm->last_valid = true;
744+
}
745+
746+
/* In any case, forget any future cached numbers */
747+
elm->cached = elm->last;
738748

739749
START_CRIT_SECTION();
740750

@@ -893,7 +903,7 @@ init_sequence(Oid relid, SeqTable *p_elm, Relation *p_rel)
893903
errmsg("out of memory")));
894904
elm->relid = relid;
895905
elm->lxid = InvalidLocalTransactionId;
896-
/* increment is set to 0 until we do read_info (see currval) */
906+
elm->last_valid = false;
897907
elm->last = elm->cached = elm->increment = 0;
898908
elm->next = seqtab;
899909
seqtab = elm;
@@ -941,6 +951,7 @@ read_info(SeqTable elm, Relation rel, Buffer *buf)
941951

942952
seq = (Form_pg_sequence) GETSTRUCT(&tuple);
943953

954+
/* this is a handy place to update our copy of the increment */
944955
elm->increment = seq->increment_by;
945956

946957
return seq;

0 commit comments

Comments
 (0)