diff options
| author | Michael P | 2011-03-10 09:19:26 +0000 |
|---|---|---|
| committer | Pavan Deolasee | 2011-05-24 09:42:01 +0000 |
| commit | dbd5de39c35a19e086e4680271674dbaa4141b67 (patch) | |
| tree | 3f51ea818a7a720690cb499c3f2dc4d5dc22b018 /src | |
| parent | 56648b6ea8d0f36b33336fc6f36a4be9da2f07d2 (diff) | |
Fix for bug 3202643: Sequence error
For the following sequence:
create SEQUENCE seq;
select nextval('seq');
select currval('seq');
select nextval('seq');
XC was returning 1 -> 100 -> 100 -> 101
PostgreSQL was returning 1 -> 100 -> 1 -> 100
This is corrected.
We also check if nextval has been called once in a session
when using currval.
This is to correspond with PostgreSQL.
Diffstat (limited to 'src')
| -rw-r--r-- | src/backend/commands/sequence.c | 38 | ||||
| -rw-r--r-- | src/gtm/main/gtm_seq.c | 26 |
2 files changed, 29 insertions, 35 deletions
diff --git a/src/backend/commands/sequence.c b/src/backend/commands/sequence.c index a0be960859..5105200417 100644 --- a/src/backend/commands/sequence.c +++ b/src/backend/commands/sequence.c @@ -619,7 +619,13 @@ nextval_internal(Oid relid) /* Update the on-disk data */ seq->last_value = result; /* last fetched number */ seq->is_called = true; - } else + + /* save info in local cache */ + elm->last = result; /* last returned number */ + elm->cached = result; /* last fetched number */ + elm->last_valid = true; + } + else { #endif last = next = result = seq->last_value; @@ -798,21 +804,6 @@ currval_oid(PG_FUNCTION_ARGS) /* open and AccessShareLock sequence */ init_sequence(relid, &elm, &seqrel); -#ifdef PGXC - if (IS_PGXC_COORDINATOR) - { - char *seqname = GetGlobalSeqName(seqrel, NULL, NULL); - - result = (int64) GetCurrentValGTM(seqname); - if (result < 0) - ereport(ERROR, - (errcode(ERRCODE_CONNECTION_FAILURE), - errmsg("GTM error, could not obtain sequence value"))); - pfree(seqname); - } - else - { -#endif if (pg_class_aclcheck(elm->relid, GetUserId(), ACL_SELECT) != ACLCHECK_OK && pg_class_aclcheck(elm->relid, GetUserId(), ACL_USAGE) != ACLCHECK_OK) @@ -827,12 +818,21 @@ currval_oid(PG_FUNCTION_ARGS) errmsg("currval of sequence \"%s\" is not yet defined in this session", RelationGetRelationName(seqrel)))); - result = elm->last; - #ifdef PGXC + if (IS_PGXC_COORDINATOR) + { + char *seqname = GetGlobalSeqName(seqrel, NULL, NULL); + + result = (int64) GetCurrentValGTM(seqname); + if (result < 0) + ereport(ERROR, + (errcode(ERRCODE_CONNECTION_FAILURE), + errmsg("GTM error, could not obtain sequence value"))); + pfree(seqname); } +#else + result = elm->last; #endif - relation_close(seqrel, NoLock); PG_RETURN_INT64(result); diff --git a/src/gtm/main/gtm_seq.c b/src/gtm/main/gtm_seq.c index 570636be58..caccd35a2b 100644 --- a/src/gtm/main/gtm_seq.c +++ b/src/gtm/main/gtm_seq.c @@ -660,16 +660,8 @@ GTM_SeqGetCurrent(GTM_SequenceKey seqkey) GTM_RWLockAcquire(&seqinfo->gs_lock, GTM_LOCKMODE_WRITE); - /* - * If this is the first call to the sequence, set the value to the start - * value and mark the sequence as 'called' - */ - if (!SEQ_IS_CALLED(seqinfo)) - { - seqinfo->gs_value = seqinfo->gs_init_value; - seqinfo->gs_called = true; - } - value = seqinfo->gs_value; + value = seqinfo->gs_last_value; + GTM_RWLockRelease(&seqinfo->gs_lock); seq_release_seqinfo(seqinfo); return value; @@ -693,6 +685,8 @@ GTM_SeqSetVal(GTM_SequenceKey seqkey, GTM_Sequence nextval, bool iscalled) GTM_RWLockAcquire(&seqinfo->gs_lock, GTM_LOCKMODE_WRITE); + seqinfo->gs_last_value = seqinfo->gs_value; + if (seqinfo->gs_value != nextval) seqinfo->gs_value = nextval; @@ -734,7 +728,7 @@ GTM_SeqGetNext(GTM_SequenceKey seqkey) */ if (!SEQ_IS_CALLED(seqinfo)) { - value = seqinfo->gs_value = seqinfo->gs_init_value; + value = seqinfo->gs_last_value = seqinfo->gs_value = seqinfo->gs_init_value; seqinfo->gs_called = true; GTM_RWLockRelease(&seqinfo->gs_lock); seq_release_seqinfo(seqinfo); @@ -749,9 +743,9 @@ GTM_SeqGetNext(GTM_SequenceKey seqkey) * InvalidSequenceValue */ if (seqinfo->gs_max_value - seqinfo->gs_increment_by >= seqinfo->gs_value) - value = seqinfo->gs_value = seqinfo->gs_value + seqinfo->gs_increment_by; + value = seqinfo->gs_last_value = seqinfo->gs_value = seqinfo->gs_value + seqinfo->gs_increment_by; else if (SEQ_IS_CYCLE(seqinfo)) - value = seqinfo->gs_value = seqinfo->gs_min_value; + value = seqinfo->gs_last_value = seqinfo->gs_value = seqinfo->gs_min_value; else { GTM_RWLockRelease(&seqinfo->gs_lock); @@ -774,9 +768,9 @@ GTM_SeqGetNext(GTM_SequenceKey seqkey) * descending sequences. So we don't need special handling below */ if (seqinfo->gs_min_value - seqinfo->gs_increment_by <= seqinfo->gs_value) - value = seqinfo->gs_value = seqinfo->gs_value + seqinfo->gs_increment_by; + value = seqinfo->gs_value = seqinfo->gs_last_value = seqinfo->gs_value + seqinfo->gs_increment_by; else if (SEQ_IS_CYCLE(seqinfo)) - value = seqinfo->gs_value = seqinfo->gs_max_value; + value = seqinfo->gs_value = seqinfo->gs_last_value = seqinfo->gs_max_value; else { GTM_RWLockRelease(&seqinfo->gs_lock); @@ -810,7 +804,7 @@ GTM_SeqReset(GTM_SequenceKey seqkey) } GTM_RWLockAcquire(&seqinfo->gs_lock, GTM_LOCKMODE_WRITE); - seqinfo->gs_value = seqinfo->gs_init_value; + seqinfo->gs_value = seqinfo->gs_last_value = seqinfo->gs_init_value; GTM_RWLockRelease(&seqinfo->gs_lock); seq_release_seqinfo(seqinfo); |
