|
8 | 8 | *
|
9 | 9 | *
|
10 | 10 | * 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 $ |
12 | 12 | *
|
13 | 13 | *-------------------------------------------------------------------------
|
14 | 14 | */
|
@@ -65,10 +65,12 @@ typedef struct SeqTableData
|
65 | 65 | struct SeqTableData *next; /* link to next SeqTable object */
|
66 | 66 | Oid relid; /* pg_class OID of this sequence */
|
67 | 67 | LocalTransactionId lxid; /* xact in which we last did a seq op */
|
| 68 | + bool last_valid; /* do we have a valid "last" value? */ |
68 | 69 | int64 last; /* value last returned by nextval */
|
69 | 70 | int64 cached; /* last value already cached for nextval */
|
70 | 71 | /* if last != cached, we have not used up all the cached values */
|
71 | 72 | int64 increment; /* copy of sequence's increment field */
|
| 73 | + /* note that increment is zero until we first do read_info() */ |
72 | 74 | } SeqTableData;
|
73 | 75 |
|
74 | 76 | typedef SeqTableData *SeqTable;
|
@@ -336,14 +338,13 @@ AlterSequence(AlterSeqStmt *stmt)
|
336 | 338 | /* Check and set new values */
|
337 | 339 | init_params(stmt->options, false, &new, &owned_by);
|
338 | 340 |
|
| 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 | + |
339 | 345 | /* Now okay to update the on-disk tuple */
|
340 | 346 | memcpy(seq, &new, sizeof(FormData_pg_sequence));
|
341 | 347 |
|
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 |
| - |
347 | 348 | START_CRIT_SECTION();
|
348 | 349 |
|
349 | 350 | MarkBufferDirty(buf);
|
@@ -443,9 +444,11 @@ nextval_internal(Oid relid)
|
443 | 444 |
|
444 | 445 | if (elm->last != elm->cached) /* some numbers were cached */
|
445 | 446 | {
|
446 |
| - last_used_seq = elm; |
| 447 | + Assert(elm->last_valid); |
| 448 | + Assert(elm->increment != 0); |
447 | 449 | elm->last += elm->increment;
|
448 | 450 | relation_close(seqrel, NoLock);
|
| 451 | + last_used_seq = elm; |
449 | 452 | return elm->last;
|
450 | 453 | }
|
451 | 454 |
|
@@ -564,6 +567,7 @@ nextval_internal(Oid relid)
|
564 | 567 | /* save info in local cache */
|
565 | 568 | elm->last = result; /* last returned number */
|
566 | 569 | elm->cached = last; /* last fetched number */
|
| 570 | + elm->last_valid = true; |
567 | 571 |
|
568 | 572 | last_used_seq = elm;
|
569 | 573 |
|
@@ -633,7 +637,7 @@ currval_oid(PG_FUNCTION_ARGS)
|
633 | 637 | errmsg("permission denied for sequence %s",
|
634 | 638 | RelationGetRelationName(seqrel))));
|
635 | 639 |
|
636 |
| - if (elm->increment == 0) /* nextval/read_info were not called */ |
| 640 | + if (!elm->last_valid) |
637 | 641 | ereport(ERROR,
|
638 | 642 | (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
|
639 | 643 | errmsg("currval of sequence \"%s\" is not yet defined in this session",
|
@@ -668,7 +672,7 @@ lastval(PG_FUNCTION_ARGS)
|
668 | 672 | seqrel = open_share_lock(last_used_seq);
|
669 | 673 |
|
670 | 674 | /* nextval() must have already been called for this sequence */
|
671 |
| - Assert(last_used_seq->increment != 0); |
| 675 | + Assert(last_used_seq->last_valid); |
672 | 676 |
|
673 | 677 | if (pg_class_aclcheck(last_used_seq->relid, GetUserId(), ACL_SELECT) != ACLCHECK_OK &&
|
674 | 678 | pg_class_aclcheck(last_used_seq->relid, GetUserId(), ACL_USAGE) != ACLCHECK_OK)
|
@@ -732,9 +736,15 @@ do_setval(Oid relid, int64 next, bool iscalled)
|
732 | 736 | bufm, bufx)));
|
733 | 737 | }
|
734 | 738 |
|
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; |
738 | 748 |
|
739 | 749 | START_CRIT_SECTION();
|
740 | 750 |
|
@@ -893,7 +903,7 @@ init_sequence(Oid relid, SeqTable *p_elm, Relation *p_rel)
|
893 | 903 | errmsg("out of memory")));
|
894 | 904 | elm->relid = relid;
|
895 | 905 | elm->lxid = InvalidLocalTransactionId;
|
896 |
| - /* increment is set to 0 until we do read_info (see currval) */ |
| 906 | + elm->last_valid = false; |
897 | 907 | elm->last = elm->cached = elm->increment = 0;
|
898 | 908 | elm->next = seqtab;
|
899 | 909 | seqtab = elm;
|
@@ -941,6 +951,7 @@ read_info(SeqTable elm, Relation rel, Buffer *buf)
|
941 | 951 |
|
942 | 952 | seq = (Form_pg_sequence) GETSTRUCT(&tuple);
|
943 | 953 |
|
| 954 | + /* this is a handy place to update our copy of the increment */ |
944 | 955 | elm->increment = seq->increment_by;
|
945 | 956 |
|
946 | 957 | return seq;
|
|
0 commit comments