Skip to content

Commit 737b025

Browse files
kelvicharssher
authored andcommitted
[PGPRO-4074] Sequence hooks for mm
(cherry picked from commit 259711d6d874cf13fceb566f07128f21b5a4e9dc) tags: multimaster (cherry picked from commit 5b18256fd471a9e40d11ed516531e1c5a3269939)
1 parent c9bcd7f commit 737b025

File tree

2 files changed

+147
-0
lines changed

2 files changed

+147
-0
lines changed

src/backend/commands/sequence.c

Lines changed: 142 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,8 @@ typedef struct SeqTableData
8686

8787
typedef SeqTableData *SeqTable;
8888

89+
seq_nextval_hook_t SeqNextvalHook;
90+
8991
static HTAB *seqhashtab = NULL; /* hash table for SeqTable items */
9092

9193
/*
@@ -628,6 +630,10 @@ nextval_internal(Oid relid, bool check_permissions)
628630
elm->last += elm->increment;
629631
relation_close(seqrel, NoLock);
630632
last_used_seq = elm;
633+
634+
if (SeqNextvalHook)
635+
SeqNextvalHook(relid, elm->last);
636+
631637
return elm->last;
632638
}
633639

@@ -823,6 +829,9 @@ nextval_internal(Oid relid, bool check_permissions)
823829

824830
relation_close(seqrel, NoLock);
825831

832+
if (SeqNextvalHook)
833+
SeqNextvalHook(relid, result);
834+
826835
return result;
827836
}
828837

@@ -892,6 +901,139 @@ lastval(PG_FUNCTION_ARGS)
892901
PG_RETURN_INT64(result);
893902
}
894903

904+
/*
905+
* Bump last value to next iff next > value.
906+
* Support routine for multimaster's monotonic sequences.
907+
*/
908+
void
909+
AdjustSequence(Oid relid, int64 next)
910+
{
911+
SeqTable elm;
912+
Relation seqrel;
913+
Buffer buf;
914+
HeapTupleData seqdatatuple;
915+
Form_pg_sequence_data seq;
916+
HeapTuple pgstuple;
917+
Form_pg_sequence pgsform;
918+
int64 maxv,
919+
minv,
920+
incby,
921+
cache;
922+
int64 last;
923+
924+
/* open and lock sequence */
925+
init_sequence(relid, &elm, &seqrel);
926+
927+
if (pg_class_aclcheck(elm->relid, GetUserId(), ACL_UPDATE) != ACLCHECK_OK)
928+
ereport(ERROR,
929+
(errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
930+
errmsg("permission denied for sequence %s",
931+
RelationGetRelationName(seqrel))));
932+
933+
pgstuple = SearchSysCache1(SEQRELID, ObjectIdGetDatum(relid));
934+
if (!HeapTupleIsValid(pgstuple))
935+
elog(ERROR, "cache lookup failed for sequence %u", relid);
936+
pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
937+
maxv = pgsform->seqmax;
938+
minv = pgsform->seqmin;
939+
incby = pgsform->seqincrement;
940+
cache = pgsform->seqcache;
941+
ReleaseSysCache(pgstuple);
942+
943+
/* cached number is greater than received */
944+
if (elm->last != cache && elm->last + incby > next)
945+
{
946+
relation_close(seqrel, NoLock);
947+
return;
948+
}
949+
950+
/* read-only transactions may only modify temp sequences */
951+
if (!seqrel->rd_islocaltemp)
952+
PreventCommandIfReadOnly("setval()");
953+
954+
/*
955+
* Forbid this during parallel operation because, to make it work, the
956+
* cooperating backends would need to share the backend-local cached
957+
* sequence information. Currently, we don't support that.
958+
*/
959+
PreventCommandIfParallelMode("setval()");
960+
961+
/* lock page' buffer and read tuple */
962+
seq = read_seq_tuple(seqrel, &buf, &seqdatatuple);
963+
964+
if ((next < minv) || (next > maxv))
965+
{
966+
char bufv[100],
967+
bufm[100],
968+
bufx[100];
969+
970+
snprintf(bufv, sizeof(bufv), INT64_FORMAT, next);
971+
snprintf(bufm, sizeof(bufm), INT64_FORMAT, minv);
972+
snprintf(bufx, sizeof(bufx), INT64_FORMAT, maxv);
973+
ereport(ERROR,
974+
(errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
975+
errmsg("setval: value %s is out of bounds for sequence \"%s\" (%s..%s)",
976+
bufv, RelationGetRelationName(seqrel),
977+
bufm, bufx)));
978+
}
979+
980+
last = seq->last_value;
981+
if (seq->is_called)
982+
{
983+
last += incby;
984+
}
985+
if (last <= next)
986+
{
987+
next = last + incby*((next - last + incby)/incby);
988+
989+
/* Set the currval() state only if iscalled = true */
990+
if (seq->is_called)
991+
{
992+
elm->last = next; /* last returned number */
993+
elm->last_valid = true;
994+
}
995+
996+
/* In any case, forget any future cached numbers */
997+
elm->cached = elm->last;
998+
999+
/* check the comment above nextval_internal()'s equivalent call. */
1000+
if (RelationNeedsWAL(seqrel))
1001+
GetTopTransactionId();
1002+
1003+
START_CRIT_SECTION();
1004+
1005+
seq->last_value = next; /* last fetched number */
1006+
seq->log_cnt = 0;
1007+
1008+
MarkBufferDirty(buf);
1009+
1010+
/* XLOG stuff */
1011+
if (RelationNeedsWAL(seqrel))
1012+
{
1013+
xl_seq_rec xlrec;
1014+
XLogRecPtr recptr;
1015+
Page page = BufferGetPage(buf);
1016+
1017+
XLogBeginInsert();
1018+
XLogRegisterBuffer(0, buf, REGBUF_WILL_INIT);
1019+
1020+
xlrec.node = seqrel->rd_node;
1021+
XLogRegisterData((char *) &xlrec, sizeof(xl_seq_rec));
1022+
XLogRegisterData((char *) seqdatatuple.t_data, seqdatatuple.t_len);
1023+
1024+
recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG);
1025+
1026+
PageSetLSN(page, recptr);
1027+
}
1028+
1029+
END_CRIT_SECTION();
1030+
}
1031+
1032+
UnlockReleaseBuffer(buf);
1033+
1034+
relation_close(seqrel, NoLock);
1035+
}
1036+
8951037
/*
8961038
* Main internal procedure that handles 2 & 3 arg forms of SETVAL.
8971039
*

src/include/commands/sequence.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,4 +66,9 @@ extern void seq_desc(StringInfo buf, XLogReaderState *rptr);
6666
extern const char *seq_identify(uint8 info);
6767
extern void seq_mask(char *pagedata, BlockNumber blkno);
6868

69+
typedef void (*seq_nextval_hook_t)(Oid seq_relid, int64 next);
70+
extern seq_nextval_hook_t SeqNextvalHook;
71+
72+
extern void AdjustSequence(Oid relid, int64 next);
73+
6974
#endif /* SEQUENCE_H */

0 commit comments

Comments
 (0)
pFad - Phonifier reborn

Pfad - The Proxy pFad of © 2024 Garber Painting. All rights reserved.

Note: This service is not intended for secure transactions such as banking, social media, email, or purchasing. Use at your own risk. We assume no liability whatsoever for broken pages.


Alternative Proxies:

Alternative Proxy

pFad Proxy

pFad v3 Proxy

pFad v4 Proxy