|
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 | structSeqTableData*next;/* link to next SeqTable object */
|
66 | 66 | Oidrelid;/* pg_class OID of this sequence */
|
67 | 67 | LocalTransactionIdlxid;/* xact in which we last did a seq op */
|
| 68 | +boollast_valid;/* do we have a valid "last" value? */ |
68 | 69 | int64last;/* value last returned by nextval */
|
69 | 70 | int64cached;/* last value already cached for nextval */
|
70 | 71 | /* if last != cached, we have not used up all the cached values */
|
71 | 72 | int64increment;/* 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 | typedefSeqTableData*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 | returnelm->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 | returnseq;
|
|