PostgreSQL Source Code git master
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Pages
sequence.h File Reference
#include "access/xlogreader.h"
#include "catalog/objectaddress.h"
#include "fmgr.h"
#include "lib/stringinfo.h"
#include "nodes/parsenodes.h"
#include "parser/parse_node.h"
#include "storage/relfilelocator.h"
Include dependency graph for sequence.h:
This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Data Structures

struct  FormData_pg_sequence_data
 
struct  xl_seq_rec
 

Macros

#define SEQ_COL_LASTVAL   1
 
#define SEQ_COL_LOG   2
 
#define SEQ_COL_CALLED   3
 
#define SEQ_COL_FIRSTCOL   SEQ_COL_LASTVAL
 
#define SEQ_COL_LASTCOL   SEQ_COL_CALLED
 
#define XLOG_SEQ_LOG   0x00
 

Typedefs

typedef struct FormData_pg_sequence_data FormData_pg_sequence_data
 
typedef FormData_pg_sequence_dataForm_pg_sequence_data
 
typedef struct xl_seq_rec xl_seq_rec
 

Functions

int64 nextval_internal (Oid relid, bool check_permissions)
 
Datum nextval (PG_FUNCTION_ARGS)
 
Listsequence_options (Oid relid)
 
ObjectAddress DefineSequence (ParseState *pstate, CreateSeqStmt *seq)
 
ObjectAddress AlterSequence (ParseState *pstate, AlterSeqStmt *stmt)
 
void SequenceChangePersistence (Oid relid, char newrelpersistence)
 
void DeleteSequenceTuple (Oid relid)
 
void ResetSequence (Oid seq_relid)
 
void SetSequence (Oid relid, int64 next, bool is_called)
 
void ResetSequenceCaches (void)
 
void seq_redo (XLogReaderState *record)
 
void seq_desc (StringInfo buf, XLogReaderState *record)
 
const char * seq_identify (uint8 info)
 
void seq_mask (char *page, BlockNumber blkno)
 

Macro Definition Documentation

◆ SEQ_COL_CALLED

#define SEQ_COL_CALLED   3

Definition at line 40 of file sequence.h.

◆ SEQ_COL_FIRSTCOL

#define SEQ_COL_FIRSTCOL   SEQ_COL_LASTVAL

Definition at line 42 of file sequence.h.

◆ SEQ_COL_LASTCOL

#define SEQ_COL_LASTCOL   SEQ_COL_CALLED

Definition at line 43 of file sequence.h.

◆ SEQ_COL_LASTVAL

#define SEQ_COL_LASTVAL   1

Definition at line 38 of file sequence.h.

◆ SEQ_COL_LOG

#define SEQ_COL_LOG   2

Definition at line 39 of file sequence.h.

◆ XLOG_SEQ_LOG

#define XLOG_SEQ_LOG   0x00

Definition at line 46 of file sequence.h.

Typedef Documentation

◆ Form_pg_sequence_data

Definition at line 32 of file sequence.h.

◆ FormData_pg_sequence_data

◆ xl_seq_rec

typedef struct xl_seq_rec xl_seq_rec

Function Documentation

◆ AlterSequence()

ObjectAddress AlterSequence ( ParseState pstate,
AlterSeqStmt stmt 
)

Definition at line 440 of file sequence.c.

441{
442 Oid relid;
443 SeqTable elm;
444 Relation seqrel;
445 Buffer buf;
446 HeapTupleData datatuple;
447 Form_pg_sequence seqform;
448 Form_pg_sequence_data newdataform;
449 bool need_seq_rewrite;
450 List *owned_by;
451 ObjectAddress address;
452 Relation rel;
453 HeapTuple seqtuple;
454 bool reset_state = false;
455 bool is_called;
456 int64 last_value;
457 HeapTuple newdatatuple;
458
459 /* Open and lock sequence, and check for ownership along the way. */
460 relid = RangeVarGetRelidExtended(stmt->sequence,
462 stmt->missing_ok ? RVR_MISSING_OK : 0,
464 NULL);
465 if (relid == InvalidOid)
466 {
468 (errmsg("relation \"%s\" does not exist, skipping",
469 stmt->sequence->relname)));
471 }
472
473 init_sequence(relid, &elm, &seqrel);
474
475 rel = table_open(SequenceRelationId, RowExclusiveLock);
476 seqtuple = SearchSysCacheCopy1(SEQRELID,
477 ObjectIdGetDatum(relid));
478 if (!HeapTupleIsValid(seqtuple))
479 elog(ERROR, "cache lookup failed for sequence %u",
480 relid);
481
482 seqform = (Form_pg_sequence) GETSTRUCT(seqtuple);
483
484 /* lock page buffer and read tuple into new sequence structure */
485 (void) read_seq_tuple(seqrel, &buf, &datatuple);
486
487 /* copy the existing sequence data tuple, so it can be modified locally */
488 newdatatuple = heap_copytuple(&datatuple);
489 newdataform = (Form_pg_sequence_data) GETSTRUCT(newdatatuple);
490 last_value = newdataform->last_value;
491 is_called = newdataform->is_called;
492
494
495 /* Check and set new values */
496 init_params(pstate, stmt->options, stmt->for_identity, false,
497 seqform, &last_value, &reset_state, &is_called,
498 &need_seq_rewrite, &owned_by);
499
500 /* If needed, rewrite the sequence relation itself */
501 if (need_seq_rewrite)
502 {
503 /* check the comment above nextval_internal()'s equivalent call. */
504 if (RelationNeedsWAL(seqrel))
506
507 /*
508 * Create a new storage file for the sequence, making the state
509 * changes transactional.
510 */
511 RelationSetNewRelfilenumber(seqrel, seqrel->rd_rel->relpersistence);
512
513 /*
514 * Ensure sequence's relfrozenxid is at 0, since it won't contain any
515 * unfrozen XIDs. Same with relminmxid, since a sequence will never
516 * contain multixacts.
517 */
518 Assert(seqrel->rd_rel->relfrozenxid == InvalidTransactionId);
519 Assert(seqrel->rd_rel->relminmxid == InvalidMultiXactId);
520
521 /*
522 * Insert the modified tuple into the new storage file.
523 */
524 newdataform->last_value = last_value;
525 newdataform->is_called = is_called;
526 if (reset_state)
527 newdataform->log_cnt = 0;
528 fill_seq_with_data(seqrel, newdatatuple);
529 }
530
531 /* Clear local cache so that we don't think we have cached numbers */
532 /* Note that we do not change the currval() state */
533 elm->cached = elm->last;
534
535 /* process OWNED BY if given */
536 if (owned_by)
537 process_owned_by(seqrel, owned_by, stmt->for_identity);
538
539 /* update the pg_sequence tuple (we could skip this in some cases...) */
540 CatalogTupleUpdate(rel, &seqtuple->t_self, seqtuple);
541
542 InvokeObjectPostAlterHook(RelationRelationId, relid, 0);
543
544 ObjectAddressSet(address, RelationRelationId, relid);
545
547 sequence_close(seqrel, NoLock);
548
549 return address;
550}
void sequence_close(Relation relation, LOCKMODE lockmode)
Definition: sequence.c:58
int Buffer
Definition: buf.h:23
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:5383
int64_t int64
Definition: c.h:539
static void fill_seq_with_data(Relation rel, HeapTuple tuple)
Definition: sequence.c:342
static void init_sequence(Oid relid, SeqTable *p_elm, Relation *p_rel)
Definition: sequence.c:1141
static Form_pg_sequence_data read_seq_tuple(Relation rel, Buffer *buf, HeapTuple seqdatatuple)
Definition: sequence.c:1202
static void process_owned_by(Relation seqrel, List *owned_by, bool for_identity)
Definition: sequence.c:1609
static void init_params(ParseState *pstate, List *options, bool for_identity, bool isInit, Form_pg_sequence seqform, int64 *last_value, bool *reset_state, bool *is_called, bool *need_seq_rewrite, List **owned_by)
Definition: sequence.c:1271
FormData_pg_sequence_data * Form_pg_sequence_data
Definition: sequence.h:32
int errmsg(const char *fmt,...)
Definition: elog.c:1080
#define ERROR
Definition: elog.h:39
#define elog(elevel,...)
Definition: elog.h:226
#define NOTICE
Definition: elog.h:35
#define ereport(elevel,...)
Definition: elog.h:150
Assert(PointerIsAligned(start, uint64))
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:778
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
static void * GETSTRUCT(const HeapTupleData *tuple)
Definition: htup_details.h:728
#define stmt
Definition: indent_codes.h:59
void CatalogTupleUpdate(Relation heapRel, const ItemPointerData *otid, HeapTuple tup)
Definition: indexing.c:313
#define NoLock
Definition: lockdefs.h:34
#define ShareRowExclusiveLock
Definition: lockdefs.h:41
#define RowExclusiveLock
Definition: lockdefs.h:38
#define InvalidMultiXactId
Definition: multixact.h:25
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, uint32 flags, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:440
@ RVR_MISSING_OK
Definition: namespace.h:90
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:197
const ObjectAddress InvalidObjectAddress
#define ObjectAddressSet(addr, class_id, object_id)
Definition: objectaddress.h:40
FormData_pg_sequence * Form_pg_sequence
Definition: pg_sequence.h:40
static char * buf
Definition: pg_test_fsync.c:72
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:262
#define InvalidOid
Definition: postgres_ext.h:37
unsigned int Oid
Definition: postgres_ext.h:32
#define RelationNeedsWAL(relation)
Definition: rel.h:638
void RelationSetNewRelfilenumber(Relation relation, char persistence)
Definition: relcache.c:3773
ItemPointerData t_self
Definition: htup.h:65
Definition: pg_list.h:54
Form_pg_class rd_rel
Definition: rel.h:111
int64 cached
Definition: sequence.c:84
int64 last
Definition: sequence.c:83
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:91
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:126
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:40
void RangeVarCallbackOwnsRelation(const RangeVar *relation, Oid relId, Oid oldRelId, void *arg)
Definition: tablecmds.c:19544
#define InvalidTransactionId
Definition: transam.h:31
TransactionId GetTopTransactionId(void)
Definition: xact.c:427

References Assert(), buf, SeqTableData::cached, CatalogTupleUpdate(), elog, ereport, errmsg(), ERROR, fill_seq_with_data(), GETSTRUCT(), GetTopTransactionId(), heap_copytuple(), HeapTupleIsValid, init_params(), init_sequence(), InvalidMultiXactId, InvalidObjectAddress, InvalidOid, InvalidTransactionId, InvokeObjectPostAlterHook, FormData_pg_sequence_data::is_called, SeqTableData::last, FormData_pg_sequence_data::last_value, FormData_pg_sequence_data::log_cnt, NoLock, NOTICE, ObjectAddressSet, ObjectIdGetDatum(), process_owned_by(), RangeVarCallbackOwnsRelation(), RangeVarGetRelidExtended(), RelationData::rd_rel, read_seq_tuple(), RelationNeedsWAL, RelationSetNewRelfilenumber(), RowExclusiveLock, RVR_MISSING_OK, SearchSysCacheCopy1, sequence_close(), ShareRowExclusiveLock, stmt, HeapTupleData::t_self, table_close(), table_open(), and UnlockReleaseBuffer().

Referenced by ProcessUtilitySlow().

◆ DefineSequence()

ObjectAddress DefineSequence ( ParseState pstate,
CreateSeqStmt seq 
)

Definition at line 123 of file sequence.c.

124{
125 FormData_pg_sequence seqform;
126 int64 last_value;
127 bool reset_state;
128 bool is_called;
129 bool need_seq_rewrite;
130 List *owned_by;
132 Oid seqoid;
133 ObjectAddress address;
134 Relation rel;
135 HeapTuple tuple;
136 TupleDesc tupDesc;
138 bool null[SEQ_COL_LASTCOL];
139 Datum pgs_values[Natts_pg_sequence];
140 bool pgs_nulls[Natts_pg_sequence];
141 int i;
142
143 /*
144 * If if_not_exists was given and a relation with the same name already
145 * exists, bail out. (Note: we needn't check this when not if_not_exists,
146 * because DefineRelation will complain anyway.)
147 */
148 if (seq->if_not_exists)
149 {
151 if (OidIsValid(seqoid))
152 {
153 /*
154 * If we are in an extension script, insist that the pre-existing
155 * object be a member of the extension, to avoid security risks.
156 */
157 ObjectAddressSet(address, RelationRelationId, seqoid);
159
160 /* OK to skip */
162 (errcode(ERRCODE_DUPLICATE_TABLE),
163 errmsg("relation \"%s\" already exists, skipping",
164 seq->sequence->relname)));
166 }
167 }
168
169 /* Check and set all option values */
170 init_params(pstate, seq->options, seq->for_identity, true,
171 &seqform, &last_value, &reset_state, &is_called,
172 &need_seq_rewrite, &owned_by);
173
174 /*
175 * Create relation (and fill value[] and null[] for the tuple)
176 */
177 stmt->tableElts = NIL;
178 for (i = SEQ_COL_FIRSTCOL; i <= SEQ_COL_LASTCOL; i++)
179 {
180 ColumnDef *coldef = NULL;
181
182 switch (i)
183 {
184 case SEQ_COL_LASTVAL:
185 coldef = makeColumnDef("last_value", INT8OID, -1, InvalidOid);
186 value[i - 1] = Int64GetDatumFast(last_value);
187 break;
188 case SEQ_COL_LOG:
189 coldef = makeColumnDef("log_cnt", INT8OID, -1, InvalidOid);
190 value[i - 1] = Int64GetDatum((int64) 0);
191 break;
192 case SEQ_COL_CALLED:
193 coldef = makeColumnDef("is_called", BOOLOID, -1, InvalidOid);
194 value[i - 1] = BoolGetDatum(false);
195 break;
196 }
197
198 coldef->is_not_null = true;
199 null[i - 1] = false;
200
201 stmt->tableElts = lappend(stmt->tableElts, coldef);
202 }
203
204 stmt->relation = seq->sequence;
205 stmt->inhRelations = NIL;
206 stmt->constraints = NIL;
207 stmt->options = NIL;
208 stmt->oncommit = ONCOMMIT_NOOP;
209 stmt->tablespacename = NULL;
210 stmt->if_not_exists = seq->if_not_exists;
211
212 address = DefineRelation(stmt, RELKIND_SEQUENCE, seq->ownerId, NULL, NULL);
213 seqoid = address.objectId;
214 Assert(seqoid != InvalidOid);
215
216 rel = sequence_open(seqoid, AccessExclusiveLock);
217 tupDesc = RelationGetDescr(rel);
218
219 /* now initialize the sequence's data */
220 tuple = heap_form_tuple(tupDesc, value, null);
221 fill_seq_with_data(rel, tuple);
222
223 /* process OWNED BY if given */
224 if (owned_by)
225 process_owned_by(rel, owned_by, seq->for_identity);
226
228
229 /* fill in pg_sequence */
230 rel = table_open(SequenceRelationId, RowExclusiveLock);
231 tupDesc = RelationGetDescr(rel);
232
233 memset(pgs_nulls, 0, sizeof(pgs_nulls));
234
235 pgs_values[Anum_pg_sequence_seqrelid - 1] = ObjectIdGetDatum(seqoid);
236 pgs_values[Anum_pg_sequence_seqtypid - 1] = ObjectIdGetDatum(seqform.seqtypid);
237 pgs_values[Anum_pg_sequence_seqstart - 1] = Int64GetDatumFast(seqform.seqstart);
238 pgs_values[Anum_pg_sequence_seqincrement - 1] = Int64GetDatumFast(seqform.seqincrement);
239 pgs_values[Anum_pg_sequence_seqmax - 1] = Int64GetDatumFast(seqform.seqmax);
240 pgs_values[Anum_pg_sequence_seqmin - 1] = Int64GetDatumFast(seqform.seqmin);
241 pgs_values[Anum_pg_sequence_seqcache - 1] = Int64GetDatumFast(seqform.seqcache);
242 pgs_values[Anum_pg_sequence_seqcycle - 1] = BoolGetDatum(seqform.seqcycle);
243
244 tuple = heap_form_tuple(tupDesc, pgs_values, pgs_nulls);
245 CatalogTupleInsert(rel, tuple);
246
247 heap_freetuple(tuple);
249
250 return address;
251}
Relation sequence_open(Oid relationId, LOCKMODE lockmode)
Definition: sequence.c:37
#define OidIsValid(objectId)
Definition: c.h:778
#define SEQ_COL_LASTVAL
Definition: sequence.h:38
#define SEQ_COL_CALLED
Definition: sequence.h:40
#define SEQ_COL_LASTCOL
Definition: sequence.h:43
#define SEQ_COL_LOG
Definition: sequence.h:39
#define SEQ_COL_FIRSTCOL
Definition: sequence.h:42
int errcode(int sqlerrcode)
Definition: elog.c:863
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, const Datum *values, const bool *isnull)
Definition: heaptuple.c:1117
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1435
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:233
static struct @171 value
int i
Definition: isn.c:77
List * lappend(List *list, void *datum)
Definition: list.c:339
#define AccessExclusiveLock
Definition: lockdefs.h:43
ColumnDef * makeColumnDef(const char *colname, Oid typeOid, int32 typmod, Oid collOid)
Definition: makefuncs.c:565
Oid RangeVarGetAndCheckCreationNamespace(RangeVar *relation, LOCKMODE lockmode, Oid *existing_relation_id)
Definition: namespace.c:738
#define makeNode(_type_)
Definition: nodes.h:161
void checkMembershipInCurrentExtension(const ObjectAddress *object)
Definition: pg_depend.c:258
#define NIL
Definition: pg_list.h:68
FormData_pg_sequence
Definition: pg_sequence.h:33
static Datum Int64GetDatum(int64 X)
Definition: postgres.h:403
#define Int64GetDatumFast(X)
Definition: postgres.h:515
static Datum BoolGetDatum(bool X)
Definition: postgres.h:112
uint64_t Datum
Definition: postgres.h:70
@ ONCOMMIT_NOOP
Definition: primnodes.h:58
#define RelationGetDescr(relation)
Definition: rel.h:541
bool is_not_null
Definition: parsenodes.h:759
bool if_not_exists
Definition: parsenodes.h:3229
List * options
Definition: parsenodes.h:3226
RangeVar * sequence
Definition: parsenodes.h:3225
char * relname
Definition: primnodes.h:83
ObjectAddress DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, ObjectAddress *typaddress, const char *queryString)
Definition: tablecmds.c:764

References AccessExclusiveLock, Assert(), BoolGetDatum(), CatalogTupleInsert(), checkMembershipInCurrentExtension(), DefineRelation(), ereport, errcode(), errmsg(), fill_seq_with_data(), CreateSeqStmt::for_identity, FormData_pg_sequence, heap_form_tuple(), heap_freetuple(), i, CreateSeqStmt::if_not_exists, init_params(), Int64GetDatum(), Int64GetDatumFast, InvalidObjectAddress, InvalidOid, ColumnDef::is_not_null, lappend(), makeColumnDef(), makeNode, NIL, NoLock, NOTICE, ObjectAddressSet, ObjectAddress::objectId, ObjectIdGetDatum(), OidIsValid, ONCOMMIT_NOOP, CreateSeqStmt::options, CreateSeqStmt::ownerId, process_owned_by(), RangeVarGetAndCheckCreationNamespace(), RelationGetDescr, RangeVar::relname, RowExclusiveLock, SEQ_COL_CALLED, SEQ_COL_FIRSTCOL, SEQ_COL_LASTCOL, SEQ_COL_LASTVAL, SEQ_COL_LOG, CreateSeqStmt::sequence, sequence_close(), sequence_open(), stmt, table_close(), table_open(), and value.

Referenced by ProcessUtilitySlow().

◆ DeleteSequenceTuple()

void DeleteSequenceTuple ( Oid  relid)

Definition at line 582 of file sequence.c.

583{
584 Relation rel;
585 HeapTuple tuple;
586
587 rel = table_open(SequenceRelationId, RowExclusiveLock);
588
589 tuple = SearchSysCache1(SEQRELID, ObjectIdGetDatum(relid));
590 if (!HeapTupleIsValid(tuple))
591 elog(ERROR, "cache lookup failed for sequence %u", relid);
592
593 CatalogTupleDelete(rel, &tuple->t_self);
594
595 ReleaseSysCache(tuple);
597}
void CatalogTupleDelete(Relation heapRel, const ItemPointerData *tid)
Definition: indexing.c:365
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:264
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:220

References CatalogTupleDelete(), elog, ERROR, HeapTupleIsValid, ObjectIdGetDatum(), ReleaseSysCache(), RowExclusiveLock, SearchSysCache1(), HeapTupleData::t_self, table_close(), and table_open().

Referenced by doDeletion().

◆ nextval()

Datum nextval ( PG_FUNCTION_ARGS  )

Definition at line 605 of file sequence.c.

606{
607 text *seqin = PG_GETARG_TEXT_PP(0);
608 RangeVar *sequence;
609 Oid relid;
610
612
613 /*
614 * XXX: This is not safe in the presence of concurrent DDL, but acquiring
615 * a lock here is more expensive than letting nextval_internal do it,
616 * since the latter maintains a cache that keeps us from hitting the lock
617 * manager more than once per transaction. It's not clear whether the
618 * performance penalty is material in practice, but for now, we do it this
619 * way.
620 */
621 relid = RangeVarGetRelid(sequence, NoLock, false);
622
623 PG_RETURN_INT64(nextval_internal(relid, true));
624}
int64 nextval_internal(Oid relid, bool check_permissions)
Definition: sequence.c:635
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
#define PG_RETURN_INT64(x)
Definition: fmgr.h:368
RangeVar * makeRangeVarFromNameList(const List *names)
Definition: namespace.c:3624
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition: namespace.h:98
Definition: c.h:696
List * textToQualifiedNameList(text *textval)
Definition: varlena.c:2686

References makeRangeVarFromNameList(), nextval_internal(), NoLock, PG_GETARG_TEXT_PP, PG_RETURN_INT64, RangeVarGetRelid, and textToQualifiedNameList().

Referenced by autoinc().

◆ nextval_internal()

int64 nextval_internal ( Oid  relid,
bool  check_permissions 
)

Definition at line 635 of file sequence.c.

636{
637 SeqTable elm;
638 Relation seqrel;
639 Buffer buf;
640 Page page;
641 HeapTuple pgstuple;
642 Form_pg_sequence pgsform;
643 HeapTupleData seqdatatuple;
645 int64 incby,
646 maxv,
647 minv,
648 cache,
649 log,
650 fetch,
651 last;
652 int64 result,
653 next,
654 rescnt = 0;
655 bool cycle;
656 bool logit = false;
657
658 /* open and lock sequence */
659 init_sequence(relid, &elm, &seqrel);
660
661 if (check_permissions &&
665 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
666 errmsg("permission denied for sequence %s",
667 RelationGetRelationName(seqrel))));
668
669 /* read-only transactions may only modify temp sequences */
670 if (!seqrel->rd_islocaltemp)
671 PreventCommandIfReadOnly("nextval()");
672
673 /*
674 * Forbid this during parallel operation because, to make it work, the
675 * cooperating backends would need to share the backend-local cached
676 * sequence information. Currently, we don't support that.
677 */
678 PreventCommandIfParallelMode("nextval()");
679
680 if (elm->last != elm->cached) /* some numbers were cached */
681 {
682 Assert(elm->last_valid);
683 Assert(elm->increment != 0);
684 elm->last += elm->increment;
685 sequence_close(seqrel, NoLock);
686 last_used_seq = elm;
687 return elm->last;
688 }
689
690 pgstuple = SearchSysCache1(SEQRELID, ObjectIdGetDatum(relid));
691 if (!HeapTupleIsValid(pgstuple))
692 elog(ERROR, "cache lookup failed for sequence %u", relid);
693 pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
694 incby = pgsform->seqincrement;
695 maxv = pgsform->seqmax;
696 minv = pgsform->seqmin;
697 cache = pgsform->seqcache;
698 cycle = pgsform->seqcycle;
699 ReleaseSysCache(pgstuple);
700
701 /* lock page buffer and read tuple */
702 seq = read_seq_tuple(seqrel, &buf, &seqdatatuple);
703 page = BufferGetPage(buf);
704
705 last = next = result = seq->last_value;
706 fetch = cache;
707 log = seq->log_cnt;
708
709 if (!seq->is_called)
710 {
711 rescnt++; /* return last_value if not is_called */
712 fetch--;
713 }
714
715 /*
716 * Decide whether we should emit a WAL log record. If so, force up the
717 * fetch count to grab SEQ_LOG_VALS more values than we actually need to
718 * cache. (These will then be usable without logging.)
719 *
720 * If this is the first nextval after a checkpoint, we must force a new
721 * WAL record to be written anyway, else replay starting from the
722 * checkpoint would fail to advance the sequence past the logged values.
723 * In this case we may as well fetch extra values.
724 */
725 if (log < fetch || !seq->is_called)
726 {
727 /* forced log to satisfy local demand for values */
728 fetch = log = fetch + SEQ_LOG_VALS;
729 logit = true;
730 }
731 else
732 {
733 XLogRecPtr redoptr = GetRedoRecPtr();
734
735 if (PageGetLSN(page) <= redoptr)
736 {
737 /* last update of seq was before checkpoint */
738 fetch = log = fetch + SEQ_LOG_VALS;
739 logit = true;
740 }
741 }
742
743 while (fetch) /* try to fetch cache [+ log ] numbers */
744 {
745 /*
746 * Check MAXVALUE for ascending sequences and MINVALUE for descending
747 * sequences
748 */
749 if (incby > 0)
750 {
751 /* ascending sequence */
752 if ((maxv >= 0 && next > maxv - incby) ||
753 (maxv < 0 && next + incby > maxv))
754 {
755 if (rescnt > 0)
756 break; /* stop fetching */
757 if (!cycle)
759 (errcode(ERRCODE_SEQUENCE_GENERATOR_LIMIT_EXCEEDED),
760 errmsg("nextval: reached maximum value of sequence \"%s\" (%" PRId64 ")",
762 maxv)));
763 next = minv;
764 }
765 else
766 next += incby;
767 }
768 else
769 {
770 /* descending sequence */
771 if ((minv < 0 && next < minv - incby) ||
772 (minv >= 0 && next + incby < minv))
773 {
774 if (rescnt > 0)
775 break; /* stop fetching */
776 if (!cycle)
778 (errcode(ERRCODE_SEQUENCE_GENERATOR_LIMIT_EXCEEDED),
779 errmsg("nextval: reached minimum value of sequence \"%s\" (%" PRId64 ")",
781 minv)));
782 next = maxv;
783 }
784 else
785 next += incby;
786 }
787 fetch--;
788 if (rescnt < cache)
789 {
790 log--;
791 rescnt++;
792 last = next;
793 if (rescnt == 1) /* if it's first result - */
794 result = next; /* it's what to return */
795 }
796 }
797
798 log -= fetch; /* adjust for any unfetched numbers */
799 Assert(log >= 0);
800
801 /* save info in local cache */
802 elm->increment = incby;
803 elm->last = result; /* last returned number */
804 elm->cached = last; /* last fetched number */
805 elm->last_valid = true;
806
807 last_used_seq = elm;
808
809 /*
810 * If something needs to be WAL logged, acquire an xid, so this
811 * transaction's commit will trigger a WAL flush and wait for syncrep.
812 * It's sufficient to ensure the toplevel transaction has an xid, no need
813 * to assign xids subxacts, that'll already trigger an appropriate wait.
814 * (Have to do that here, so we're outside the critical section)
815 */
816 if (logit && RelationNeedsWAL(seqrel))
818
819 /* ready to change the on-disk (or really, in-buffer) tuple */
821
822 /*
823 * We must mark the buffer dirty before doing XLogInsert(); see notes in
824 * SyncOneBuffer(). However, we don't apply the desired changes just yet.
825 * This looks like a violation of the buffer update protocol, but it is in
826 * fact safe because we hold exclusive lock on the buffer. Any other
827 * process, including a checkpoint, that tries to examine the buffer
828 * contents will block until we release the lock, and then will see the
829 * final state that we install below.
830 */
832
833 /* XLOG stuff */
834 if (logit && RelationNeedsWAL(seqrel))
835 {
836 xl_seq_rec xlrec;
837 XLogRecPtr recptr;
838
839 /*
840 * We don't log the current state of the tuple, but rather the state
841 * as it would appear after "log" more fetches. This lets us skip
842 * that many future WAL records, at the cost that we lose those
843 * sequence values if we crash.
844 */
847
848 /* set values that will be saved in xlog */
849 seq->last_value = next;
850 seq->is_called = true;
851 seq->log_cnt = 0;
852
853 xlrec.locator = seqrel->rd_locator;
854
855 XLogRegisterData(&xlrec, sizeof(xl_seq_rec));
856 XLogRegisterData(seqdatatuple.t_data, seqdatatuple.t_len);
857
858 recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG);
859
860 PageSetLSN(page, recptr);
861 }
862
863 /* Now update sequence tuple to the intended final state */
864 seq->last_value = last; /* last fetched number */
865 seq->is_called = true;
866 seq->log_cnt = log; /* how much is logged */
867
869
871
872 sequence_close(seqrel, NoLock);
873
874 return result;
875}
@ ACLCHECK_OK
Definition: acl.h:183
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:4037
static int32 next
Definition: blutils.c:224
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:2943
static Page BufferGetPage(Buffer buffer)
Definition: bufmgr.h:425
static void PageSetLSN(Page page, XLogRecPtr lsn)
Definition: bufpage.h:390
PageData * Page
Definition: bufpage.h:81
static XLogRecPtr PageGetLSN(const PageData *page)
Definition: bufpage.h:385
static SeqTableData * last_used_seq
Definition: sequence.c:98
#define SEQ_LOG_VALS
Definition: sequence.c:59
#define XLOG_SEQ_LOG
Definition: sequence.h:46
#define START_CRIT_SECTION()
Definition: miscadmin.h:150
#define END_CRIT_SECTION()
Definition: miscadmin.h:152
Oid GetUserId(void)
Definition: miscinit.c:469
#define ACL_USAGE
Definition: parsenodes.h:84
#define ACL_UPDATE
Definition: parsenodes.h:78
#define RelationGetRelationName(relation)
Definition: rel.h:549
uint32 t_len
Definition: htup.h:64
HeapTupleHeader t_data
Definition: htup.h:68
bool rd_islocaltemp
Definition: rel.h:61
RelFileLocator rd_locator
Definition: rel.h:57
bool last_valid
Definition: sequence.c:82
int64 increment
Definition: sequence.c:86
RelFileLocator locator
Definition: sequence.h:50
void PreventCommandIfReadOnly(const char *cmdname)
Definition: utility.c:406
void PreventCommandIfParallelMode(const char *cmdname)
Definition: utility.c:424
XLogRecPtr GetRedoRecPtr(void)
Definition: xlog.c:6509
uint64 XLogRecPtr
Definition: xlogdefs.h:21
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:478
void XLogRegisterData(const void *data, uint32 len)
Definition: xloginsert.c:368
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:245
void XLogBeginInsert(void)
Definition: xloginsert.c:152
#define REGBUF_WILL_INIT
Definition: xloginsert.h:34

References ACL_UPDATE, ACL_USAGE, ACLCHECK_OK, Assert(), buf, BufferGetPage(), SeqTableData::cached, elog, END_CRIT_SECTION, ereport, errcode(), errmsg(), ERROR, GetRedoRecPtr(), GETSTRUCT(), GetTopTransactionId(), GetUserId(), HeapTupleIsValid, SeqTableData::increment, init_sequence(), FormData_pg_sequence_data::is_called, SeqTableData::last, last_used_seq, SeqTableData::last_valid, FormData_pg_sequence_data::last_value, xl_seq_rec::locator, FormData_pg_sequence_data::log_cnt, MarkBufferDirty(), next, NoLock, ObjectIdGetDatum(), PageGetLSN(), PageSetLSN(), pg_class_aclcheck(), PreventCommandIfParallelMode(), PreventCommandIfReadOnly(), RelationData::rd_islocaltemp, RelationData::rd_locator, read_seq_tuple(), REGBUF_WILL_INIT, RelationGetRelationName, RelationNeedsWAL, ReleaseSysCache(), SeqTableData::relid, SearchSysCache1(), SEQ_LOG_VALS, sequence_close(), START_CRIT_SECTION, HeapTupleData::t_data, HeapTupleData::t_len, UnlockReleaseBuffer(), XLOG_SEQ_LOG, XLogBeginInsert(), XLogInsert(), XLogRegisterBuffer(), and XLogRegisterData().

Referenced by ExecEvalNextValueExpr(), nextval(), and nextval_oid().

◆ ResetSequence()

void ResetSequence ( Oid  seq_relid)

Definition at line 266 of file sequence.c.

267{
268 Relation seq_rel;
269 SeqTable elm;
271 Buffer buf;
272 HeapTupleData seqdatatuple;
273 HeapTuple tuple;
274 HeapTuple pgstuple;
275 Form_pg_sequence pgsform;
276 int64 startv;
277
278 /*
279 * Read the old sequence. This does a bit more work than really
280 * necessary, but it's simple, and we do want to double-check that it's
281 * indeed a sequence.
282 */
283 init_sequence(seq_relid, &elm, &seq_rel);
284 (void) read_seq_tuple(seq_rel, &buf, &seqdatatuple);
285
286 pgstuple = SearchSysCache1(SEQRELID, ObjectIdGetDatum(seq_relid));
287 if (!HeapTupleIsValid(pgstuple))
288 elog(ERROR, "cache lookup failed for sequence %u", seq_relid);
289 pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
290 startv = pgsform->seqstart;
291 ReleaseSysCache(pgstuple);
292
293 /*
294 * Copy the existing sequence tuple.
295 */
296 tuple = heap_copytuple(&seqdatatuple);
297
298 /* Now we're done with the old page */
300
301 /*
302 * Modify the copied tuple to execute the restart (compare the RESTART
303 * action in AlterSequence)
304 */
305 seq = (Form_pg_sequence_data) GETSTRUCT(tuple);
306 seq->last_value = startv;
307 seq->is_called = false;
308 seq->log_cnt = 0;
309
310 /*
311 * Create a new storage file for the sequence.
312 */
313 RelationSetNewRelfilenumber(seq_rel, seq_rel->rd_rel->relpersistence);
314
315 /*
316 * Ensure sequence's relfrozenxid is at 0, since it won't contain any
317 * unfrozen XIDs. Same with relminmxid, since a sequence will never
318 * contain multixacts.
319 */
320 Assert(seq_rel->rd_rel->relfrozenxid == InvalidTransactionId);
321 Assert(seq_rel->rd_rel->relminmxid == InvalidMultiXactId);
322
323 /*
324 * Insert the modified tuple into the new storage file.
325 */
326 fill_seq_with_data(seq_rel, tuple);
327
328 /* Clear local cache so that we don't think we have cached numbers */
329 /* Note that we do not change the currval() state */
330 elm->cached = elm->last;
331
332 sequence_close(seq_rel, NoLock);
333}

References Assert(), buf, SeqTableData::cached, elog, ERROR, fill_seq_with_data(), GETSTRUCT(), heap_copytuple(), HeapTupleIsValid, init_sequence(), InvalidMultiXactId, InvalidTransactionId, FormData_pg_sequence_data::is_called, SeqTableData::last, FormData_pg_sequence_data::last_value, FormData_pg_sequence_data::log_cnt, NoLock, ObjectIdGetDatum(), RelationData::rd_rel, read_seq_tuple(), RelationSetNewRelfilenumber(), ReleaseSysCache(), SearchSysCache1(), sequence_close(), and UnlockReleaseBuffer().

Referenced by ExecuteTruncateGuts().

◆ ResetSequenceCaches()

void ResetSequenceCaches ( void  )

Definition at line 1964 of file sequence.c.

1965{
1966 if (seqhashtab)
1967 {
1969 seqhashtab = NULL;
1970 }
1971
1972 last_used_seq = NULL;
1973}
static HTAB * seqhashtab
Definition: sequence.c:92
void hash_destroy(HTAB *hashp)
Definition: dynahash.c:865

References hash_destroy(), last_used_seq, and seqhashtab.

Referenced by DiscardAll(), and DiscardCommand().

◆ seq_desc()

void seq_desc ( StringInfo  buf,
XLogReaderState record 
)

Definition at line 21 of file seqdesc.c.

22{
23 char *rec = XLogRecGetData(record);
24 uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
25 xl_seq_rec *xlrec = (xl_seq_rec *) rec;
26
27 if (info == XLOG_SEQ_LOG)
28 appendStringInfo(buf, "rel %u/%u/%u",
29 xlrec->locator.spcOid, xlrec->locator.dbOid,
30 xlrec->locator.relNumber);
31}
uint8_t uint8
Definition: c.h:540
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:145
RelFileNumber relNumber
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:409
#define XLogRecGetData(decoder)
Definition: xlogreader.h:414

References appendStringInfo(), buf, RelFileLocator::dbOid, xl_seq_rec::locator, RelFileLocator::relNumber, RelFileLocator::spcOid, XLOG_SEQ_LOG, XLogRecGetData, and XLogRecGetInfo.

◆ seq_identify()

const char * seq_identify ( uint8  info)

Definition at line 34 of file seqdesc.c.

35{
36 const char *id = NULL;
37
38 switch (info & ~XLR_INFO_MASK)
39 {
40 case XLOG_SEQ_LOG:
41 id = "LOG";
42 break;
43 }
44
45 return id;
46}
#define XLR_INFO_MASK
Definition: xlogrecord.h:62

References XLOG_SEQ_LOG, and XLR_INFO_MASK.

◆ seq_mask()

void seq_mask ( char *  page,
BlockNumber  blkno 
)

Definition at line 1979 of file sequence.c.

1980{
1982
1983 mask_unused_space(page);
1984}
void mask_page_lsn_and_checksum(Page page)
Definition: bufmask.c:31
void mask_unused_space(Page page)
Definition: bufmask.c:71

References mask_page_lsn_and_checksum(), and mask_unused_space().

◆ seq_redo()

void seq_redo ( XLogReaderState record)

Definition at line 1912 of file sequence.c.

1913{
1914 XLogRecPtr lsn = record->EndRecPtr;
1915 uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
1916 Buffer buffer;
1917 Page page;
1918 Page localpage;
1919 char *item;
1920 Size itemsz;
1921 xl_seq_rec *xlrec = (xl_seq_rec *) XLogRecGetData(record);
1922 sequence_magic *sm;
1923
1924 if (info != XLOG_SEQ_LOG)
1925 elog(PANIC, "seq_redo: unknown op code %u", info);
1926
1927 buffer = XLogInitBufferForRedo(record, 0);
1928 page = BufferGetPage(buffer);
1929
1930 /*
1931 * We always reinit the page. However, since this WAL record type is also
1932 * used for updating sequences, it's possible that a hot-standby backend
1933 * is examining the page concurrently; so we mustn't transiently trash the
1934 * buffer. The solution is to build the correct new page contents in
1935 * local workspace and then memcpy into the buffer. Then only bytes that
1936 * are supposed to change will change, even transiently. We must palloc
1937 * the local page for alignment reasons.
1938 */
1939 localpage = (Page) palloc(BufferGetPageSize(buffer));
1940
1941 PageInit(localpage, BufferGetPageSize(buffer), sizeof(sequence_magic));
1942 sm = (sequence_magic *) PageGetSpecialPointer(localpage);
1943 sm->magic = SEQ_MAGIC;
1944
1945 item = (char *) xlrec + sizeof(xl_seq_rec);
1946 itemsz = XLogRecGetDataLen(record) - sizeof(xl_seq_rec);
1947
1948 if (PageAddItem(localpage, item, itemsz, FirstOffsetNumber, false, false) == InvalidOffsetNumber)
1949 elog(PANIC, "seq_redo: failed to add item to page");
1950
1951 PageSetLSN(localpage, lsn);
1952
1953 memcpy(page, localpage, BufferGetPageSize(buffer));
1954 MarkBufferDirty(buffer);
1955 UnlockReleaseBuffer(buffer);
1956
1957 pfree(localpage);
1958}
static Size BufferGetPageSize(Buffer buffer)
Definition: bufmgr.h:414
void PageInit(Page page, Size pageSize, Size specialSize)
Definition: bufpage.c:42
#define PageGetSpecialPointer(page)
Definition: bufpage.h:338
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
Definition: bufpage.h:471
size_t Size
Definition: c.h:614
#define SEQ_MAGIC
Definition: sequence.c:64
struct xl_seq_rec xl_seq_rec
#define PANIC
Definition: elog.h:42
void pfree(void *pointer)
Definition: mcxt.c:1594
void * palloc(Size size)
Definition: mcxt.c:1365
#define InvalidOffsetNumber
Definition: off.h:26
#define FirstOffsetNumber
Definition: off.h:27
XLogRecPtr EndRecPtr
Definition: xlogreader.h:206
uint32 magic
Definition: sequence.c:68
#define XLogRecGetDataLen(decoder)
Definition: xlogreader.h:415
Buffer XLogInitBufferForRedo(XLogReaderState *record, uint8 block_id)
Definition: xlogutils.c:315

References BufferGetPage(), BufferGetPageSize(), elog, XLogReaderState::EndRecPtr, FirstOffsetNumber, InvalidOffsetNumber, sequence_magic::magic, MarkBufferDirty(), PageAddItem, PageGetSpecialPointer, PageInit(), PageSetLSN(), palloc(), PANIC, pfree(), SEQ_MAGIC, UnlockReleaseBuffer(), XLOG_SEQ_LOG, XLogInitBufferForRedo(), XLogRecGetData, XLogRecGetDataLen, and XLogRecGetInfo.

◆ sequence_options()

List * sequence_options ( Oid  relid)

Definition at line 1723 of file sequence.c.

1724{
1725 HeapTuple pgstuple;
1726 Form_pg_sequence pgsform;
1727 List *options = NIL;
1728
1729 pgstuple = SearchSysCache1(SEQRELID, ObjectIdGetDatum(relid));
1730 if (!HeapTupleIsValid(pgstuple))
1731 elog(ERROR, "cache lookup failed for sequence %u", relid);
1732 pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
1733
1734 /* Use makeFloat() for 64-bit integers, like gram.y does. */
1736 makeDefElem("cache", (Node *) makeFloat(psprintf(INT64_FORMAT, pgsform->seqcache)), -1));
1738 makeDefElem("cycle", (Node *) makeBoolean(pgsform->seqcycle), -1));
1740 makeDefElem("increment", (Node *) makeFloat(psprintf(INT64_FORMAT, pgsform->seqincrement)), -1));
1742 makeDefElem("maxvalue", (Node *) makeFloat(psprintf(INT64_FORMAT, pgsform->seqmax)), -1));
1744 makeDefElem("minvalue", (Node *) makeFloat(psprintf(INT64_FORMAT, pgsform->seqmin)), -1));
1746 makeDefElem("start", (Node *) makeFloat(psprintf(INT64_FORMAT, pgsform->seqstart)), -1));
1747
1748 ReleaseSysCache(pgstuple);
1749
1750 return options;
1751}
#define INT64_FORMAT
Definition: c.h:560
DefElem * makeDefElem(char *name, Node *arg, int location)
Definition: makefuncs.c:637
static char ** options
char * psprintf(const char *fmt,...)
Definition: psprintf.c:43
Definition: nodes.h:135
Float * makeFloat(char *numericStr)
Definition: value.c:37
Boolean * makeBoolean(bool val)
Definition: value.c:49

References elog, ERROR, GETSTRUCT(), HeapTupleIsValid, INT64_FORMAT, lappend(), makeBoolean(), makeDefElem(), makeFloat(), NIL, ObjectIdGetDatum(), options, psprintf(), ReleaseSysCache(), and SearchSysCache1().

Referenced by transformTableLikeClause().

◆ SequenceChangePersistence()

void SequenceChangePersistence ( Oid  relid,
char  newrelpersistence 
)

Definition at line 553 of file sequence.c.

554{
555 SeqTable elm;
556 Relation seqrel;
557 Buffer buf;
558 HeapTupleData seqdatatuple;
559
560 /*
561 * ALTER SEQUENCE acquires this lock earlier. If we're processing an
562 * owned sequence for ALTER TABLE, lock now. Without the lock, we'd
563 * discard increments from nextval() calls (in other sessions) between
564 * this function's buffer unlock and this transaction's commit.
565 */
567 init_sequence(relid, &elm, &seqrel);
568
569 /* check the comment above nextval_internal()'s equivalent call. */
570 if (RelationNeedsWAL(seqrel))
572
573 (void) read_seq_tuple(seqrel, &buf, &seqdatatuple);
574 RelationSetNewRelfilenumber(seqrel, newrelpersistence);
575 fill_seq_with_data(seqrel, &seqdatatuple);
577
578 sequence_close(seqrel, NoLock);
579}
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:107

References AccessExclusiveLock, buf, fill_seq_with_data(), GetTopTransactionId(), init_sequence(), LockRelationOid(), NoLock, read_seq_tuple(), RelationNeedsWAL, RelationSetNewRelfilenumber(), sequence_close(), and UnlockReleaseBuffer().

Referenced by ATRewriteTables().

◆ SetSequence()

void SetSequence ( Oid  relid,
int64  next,
bool  is_called 
)

Definition at line 957 of file sequence.c.

958{
959 SeqTable elm;
960 Relation seqrel;
961 Buffer buf;
962 HeapTupleData seqdatatuple;
964 HeapTuple pgstuple;
965 Form_pg_sequence pgsform;
966 int64 maxv,
967 minv;
968
969 /* open and lock sequence */
970 init_sequence(relid, &elm, &seqrel);
971
974 (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
975 errmsg("permission denied for sequence %s",
976 RelationGetRelationName(seqrel))));
977
978 pgstuple = SearchSysCache1(SEQRELID, ObjectIdGetDatum(relid));
979 if (!HeapTupleIsValid(pgstuple))
980 elog(ERROR, "cache lookup failed for sequence %u", relid);
981 pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
982 maxv = pgsform->seqmax;
983 minv = pgsform->seqmin;
984 ReleaseSysCache(pgstuple);
985
986 /* read-only transactions may only modify temp sequences */
987 if (!seqrel->rd_islocaltemp)
988 PreventCommandIfReadOnly("setval()");
989
990 /*
991 * Forbid this during parallel operation because, to make it work, the
992 * cooperating backends would need to share the backend-local cached
993 * sequence information. Currently, we don't support that.
994 */
996
997 /* lock page buffer and read tuple */
998 seq = read_seq_tuple(seqrel, &buf, &seqdatatuple);
999
1000 if ((next < minv) || (next > maxv))
1001 ereport(ERROR,
1002 (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
1003 errmsg("setval: value %" PRId64 " is out of bounds for sequence \"%s\" (%" PRId64 "..%" PRId64 ")",
1005 minv, maxv)));
1006
1007 /* Set the currval() state only if iscalled = true */
1008 if (iscalled)
1009 {
1010 elm->last = next; /* last returned number */
1011 elm->last_valid = true;
1012 }
1013
1014 /* In any case, forget any future cached numbers */
1015 elm->cached = elm->last;
1016
1017 /* check the comment above nextval_internal()'s equivalent call. */
1018 if (RelationNeedsWAL(seqrel))
1020
1021 /* ready to change the on-disk (or really, in-buffer) tuple */
1023
1024 seq->last_value = next; /* last fetched number */
1025 seq->is_called = iscalled;
1026 seq->log_cnt = 0;
1027
1029
1030 /* XLOG stuff */
1031 if (RelationNeedsWAL(seqrel))
1032 {
1033 xl_seq_rec xlrec;
1034 XLogRecPtr recptr;
1035 Page page = BufferGetPage(buf);
1036
1039
1040 xlrec.locator = seqrel->rd_locator;
1041 XLogRegisterData(&xlrec, sizeof(xl_seq_rec));
1042 XLogRegisterData(seqdatatuple.t_data, seqdatatuple.t_len);
1043
1044 recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG);
1045
1046 PageSetLSN(page, recptr);
1047 }
1048
1050
1052
1053 sequence_close(seqrel, NoLock);
1054}

References ACL_UPDATE, ACLCHECK_OK, buf, BufferGetPage(), SeqTableData::cached, elog, END_CRIT_SECTION, ereport, errcode(), errmsg(), ERROR, GETSTRUCT(), GetTopTransactionId(), GetUserId(), HeapTupleIsValid, init_sequence(), FormData_pg_sequence_data::is_called, SeqTableData::last, SeqTableData::last_valid, FormData_pg_sequence_data::last_value, xl_seq_rec::locator, FormData_pg_sequence_data::log_cnt, MarkBufferDirty(), next, NoLock, ObjectIdGetDatum(), PageSetLSN(), pg_class_aclcheck(), PreventCommandIfParallelMode(), PreventCommandIfReadOnly(), RelationData::rd_islocaltemp, RelationData::rd_locator, read_seq_tuple(), REGBUF_WILL_INIT, RelationGetRelationName, RelationNeedsWAL, ReleaseSysCache(), SeqTableData::relid, SearchSysCache1(), sequence_close(), START_CRIT_SECTION, HeapTupleData::t_data, HeapTupleData::t_len, UnlockReleaseBuffer(), XLOG_SEQ_LOG, XLogBeginInsert(), XLogInsert(), XLogRegisterBuffer(), and XLogRegisterData().

Referenced by copy_sequence(), setval3_oid(), and setval_oid().