PostgreSQL Source Code  git master
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/relfilenode.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 *stmt)
 
ObjectAddress AlterSequence (ParseState *pstate, AlterSeqStmt *stmt)
 
void SequenceChangePersistence (Oid relid, char newrelpersistence)
 
void DeleteSequenceTuple (Oid relid)
 
void ResetSequence (Oid seq_relid)
 
void ResetSequenceCaches (void)
 
void seq_redo (XLogReaderState *rptr)
 
void seq_desc (StringInfo buf, XLogReaderState *rptr)
 
const char * seq_identify (uint8 info)
 
void seq_mask (char *pagedata, 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 442 of file sequence.c.

443 {
444  Oid relid;
445  SeqTable elm;
446  Relation seqrel;
447  Buffer buf;
448  HeapTupleData datatuple;
449  Form_pg_sequence seqform;
450  Form_pg_sequence_data newdataform;
451  bool need_seq_rewrite;
452  List *owned_by;
453  ObjectAddress address;
454  Relation rel;
455  HeapTuple seqtuple;
456  HeapTuple newdatatuple;
457 
458  /* Open and lock sequence, and check for ownership along the way. */
459  relid = RangeVarGetRelidExtended(stmt->sequence,
461  stmt->missing_ok ? RVR_MISSING_OK : 0,
463  NULL);
464  if (relid == InvalidOid)
465  {
466  ereport(NOTICE,
467  (errmsg("relation \"%s\" does not exist, skipping",
468  stmt->sequence->relname)));
469  return InvalidObjectAddress;
470  }
471 
472  init_sequence(relid, &elm, &seqrel);
473 
474  rel = table_open(SequenceRelationId, RowExclusiveLock);
475  seqtuple = SearchSysCacheCopy1(SEQRELID,
476  ObjectIdGetDatum(relid));
477  if (!HeapTupleIsValid(seqtuple))
478  elog(ERROR, "cache lookup failed for sequence %u",
479  relid);
480 
481  seqform = (Form_pg_sequence) GETSTRUCT(seqtuple);
482 
483  /* lock page's buffer and read tuple into new sequence structure */
484  (void) read_seq_tuple(seqrel, &buf, &datatuple);
485 
486  /* copy the existing sequence data tuple, so it can be modified locally */
487  newdatatuple = heap_copytuple(&datatuple);
488  newdataform = (Form_pg_sequence_data) GETSTRUCT(newdatatuple);
489 
491 
492  /* Check and set new values */
493  init_params(pstate, stmt->options, stmt->for_identity, false,
494  seqform, newdataform,
495  &need_seq_rewrite, &owned_by);
496 
497  /* Clear local cache so that we don't think we have cached numbers */
498  /* Note that we do not change the currval() state */
499  elm->cached = elm->last;
500 
501  /* If needed, rewrite the sequence relation itself */
502  if (need_seq_rewrite)
503  {
504  /* check the comment above nextval_internal()'s equivalent call. */
505  if (RelationNeedsWAL(seqrel))
507 
508  /*
509  * Create a new storage file for the sequence, making the state
510  * changes transactional.
511  */
512  RelationSetNewRelfilenode(seqrel, seqrel->rd_rel->relpersistence);
513 
514  /*
515  * Ensure sequence's relfrozenxid is at 0, since it won't contain any
516  * unfrozen XIDs. Same with relminmxid, since a sequence will never
517  * contain multixacts.
518  */
519  Assert(seqrel->rd_rel->relfrozenxid == InvalidTransactionId);
520  Assert(seqrel->rd_rel->relminmxid == InvalidMultiXactId);
521 
522  /*
523  * Insert the modified tuple into the new storage file.
524  */
525  fill_seq_with_data(seqrel, newdatatuple);
526  }
527 
528  /* process OWNED BY if given */
529  if (owned_by)
530  process_owned_by(seqrel, owned_by, stmt->for_identity);
531 
532  /* update the pg_sequence tuple (we could skip this in some cases...) */
533  CatalogTupleUpdate(rel, &seqtuple->t_self, seqtuple);
534 
535  InvokeObjectPostAlterHook(RelationRelationId, relid, 0);
536 
537  ObjectAddressSet(address, RelationRelationId, relid);
538 
540  relation_close(seqrel, NoLock);
541 
542  return address;
543 }
int Buffer
Definition: buf.h:23
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:3938
int errmsg(const char *fmt,...)
Definition: elog.c:904
#define ERROR
Definition: elog.h:33
#define elog(elevel,...)
Definition: elog.h:218
#define NOTICE
Definition: elog.h:29
#define ereport(elevel,...)
Definition: elog.h:143
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:680
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:649
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:301
Assert(fmt[strlen(fmt) - 1] !='\n')
#define NoLock
Definition: lockdefs.h:34
#define ShareRowExclusiveLock
Definition: lockdefs.h:41
#define RowExclusiveLock
Definition: lockdefs.h:38
#define InvalidMultiXactId
Definition: multixact.h:24
Oid RangeVarGetRelidExtended(const RangeVar *relation, LOCKMODE lockmode, uint32 flags, RangeVarGetRelidCallback callback, void *callback_arg)
Definition: namespace.c:238
@ RVR_MISSING_OK
Definition: namespace.h:71
#define InvokeObjectPostAlterHook(classId, objectId, subId)
Definition: objectaccess.h:195
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:67
#define ObjectIdGetDatum(X)
Definition: postgres.h:551
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
#define RelationNeedsWAL(relation)
Definition: rel.h:613
void RelationSetNewRelfilenode(Relation relation, char persistence)
Definition: relcache.c:3700
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:1127
static Form_pg_sequence_data read_seq_tuple(Relation rel, Buffer *buf, HeapTuple seqdatatuple)
Definition: sequence.c:1194
static void process_owned_by(Relation seqrel, List *owned_by, bool for_identity)
Definition: sequence.c:1593
static void init_params(ParseState *pstate, List *options, bool for_identity, bool isInit, Form_pg_sequence seqform, Form_pg_sequence_data seqdataform, bool *need_seq_rewrite, List **owned_by)
Definition: sequence.c:1260
FormData_pg_sequence_data * Form_pg_sequence_data
Definition: sequence.h:32
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:206
List * options
Definition: parsenodes.h:3017
RangeVar * sequence
Definition: parsenodes.h:3016
bool for_identity
Definition: parsenodes.h:3018
ItemPointerData t_self
Definition: htup.h:65
Definition: pg_list.h:51
char * relname
Definition: primnodes.h:68
Form_pg_class rd_rel
Definition: rel.h:109
int64 cached
Definition: sequence.c:82
int64 last
Definition: sequence.c:81
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:179
@ SEQRELID
Definition: syscache.h:93
void table_close(Relation relation, LOCKMODE lockmode)
Definition: table.c:167
Relation table_open(Oid relationId, LOCKMODE lockmode)
Definition: table.c:39
void RangeVarCallbackOwnsRelation(const RangeVar *relation, Oid relId, Oid oldRelId, void *arg)
Definition: tablecmds.c:16979
#define InvalidTransactionId
Definition: transam.h:31
TransactionId GetTopTransactionId(void)
Definition: xact.c:413

References Assert(), buf, SeqTableData::cached, CatalogTupleUpdate(), elog, ereport, errmsg(), ERROR, fill_seq_with_data(), AlterSeqStmt::for_identity, GETSTRUCT, GetTopTransactionId(), heap_copytuple(), HeapTupleIsValid, init_params(), init_sequence(), InvalidMultiXactId, InvalidObjectAddress, InvalidOid, InvalidTransactionId, InvokeObjectPostAlterHook, SeqTableData::last, AlterSeqStmt::missing_ok, NoLock, NOTICE, ObjectAddressSet, ObjectIdGetDatum, AlterSeqStmt::options, process_owned_by(), RangeVarCallbackOwnsRelation(), RangeVarGetRelidExtended(), RelationData::rd_rel, read_seq_tuple(), relation_close(), RelationNeedsWAL, RelationSetNewRelfilenode(), RangeVar::relname, RowExclusiveLock, RVR_MISSING_OK, SearchSysCacheCopy1, SEQRELID, AlterSeqStmt::sequence, ShareRowExclusiveLock, HeapTupleData::t_self, table_close(), table_open(), and UnlockReleaseBuffer().

Referenced by ProcessUtilitySlow().

◆ DefineSequence()

ObjectAddress DefineSequence ( ParseState pstate,
CreateSeqStmt stmt 
)

Definition at line 120 of file sequence.c.

121 {
122  FormData_pg_sequence seqform;
123  FormData_pg_sequence_data seqdataform;
124  bool need_seq_rewrite;
125  List *owned_by;
126  CreateStmt *stmt = makeNode(CreateStmt);
127  Oid seqoid;
128  ObjectAddress address;
129  Relation rel;
130  HeapTuple tuple;
131  TupleDesc tupDesc;
133  bool null[SEQ_COL_LASTCOL];
134  Datum pgs_values[Natts_pg_sequence];
135  bool pgs_nulls[Natts_pg_sequence];
136  int i;
137 
138  /*
139  * If if_not_exists was given and a relation with the same name already
140  * exists, bail out. (Note: we needn't check this when not if_not_exists,
141  * because DefineRelation will complain anyway.)
142  */
143  if (seq->if_not_exists)
144  {
145  RangeVarGetAndCheckCreationNamespace(seq->sequence, NoLock, &seqoid);
146  if (OidIsValid(seqoid))
147  {
148  ereport(NOTICE,
149  (errcode(ERRCODE_DUPLICATE_TABLE),
150  errmsg("relation \"%s\" already exists, skipping",
151  seq->sequence->relname)));
152  return InvalidObjectAddress;
153  }
154  }
155 
156  /* Check and set all option values */
157  init_params(pstate, seq->options, seq->for_identity, true,
158  &seqform, &seqdataform,
159  &need_seq_rewrite, &owned_by);
160 
161  /*
162  * Create relation (and fill value[] and null[] for the tuple)
163  */
164  stmt->tableElts = NIL;
165  for (i = SEQ_COL_FIRSTCOL; i <= SEQ_COL_LASTCOL; i++)
166  {
167  ColumnDef *coldef = makeNode(ColumnDef);
168 
169  coldef->inhcount = 0;
170  coldef->is_local = true;
171  coldef->is_not_null = true;
172  coldef->is_from_type = false;
173  coldef->storage = 0;
174  coldef->raw_default = NULL;
175  coldef->cooked_default = NULL;
176  coldef->collClause = NULL;
177  coldef->collOid = InvalidOid;
178  coldef->constraints = NIL;
179  coldef->location = -1;
180 
181  null[i - 1] = false;
182 
183  switch (i)
184  {
185  case SEQ_COL_LASTVAL:
186  coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
187  coldef->colname = "last_value";
188  value[i - 1] = Int64GetDatumFast(seqdataform.last_value);
189  break;
190  case SEQ_COL_LOG:
191  coldef->typeName = makeTypeNameFromOid(INT8OID, -1);
192  coldef->colname = "log_cnt";
193  value[i - 1] = Int64GetDatum((int64) 0);
194  break;
195  case SEQ_COL_CALLED:
196  coldef->typeName = makeTypeNameFromOid(BOOLOID, -1);
197  coldef->colname = "is_called";
198  value[i - 1] = BoolGetDatum(false);
199  break;
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 = table_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 
227  table_close(rel, NoLock);
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 }
#define OidIsValid(objectId)
Definition: c.h:710
int errcode(int sqlerrcode)
Definition: elog.c:693
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:1683
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1020
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1338
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:221
static struct @151 value
int i
Definition: isn.c:73
List * lappend(List *list, void *datum)
Definition: list.c:336
#define AccessExclusiveLock
Definition: lockdefs.h:43
TypeName * makeTypeNameFromOid(Oid typeOid, int32 typmod)
Definition: makefuncs.c:473
Oid RangeVarGetAndCheckCreationNamespace(RangeVar *relation, LOCKMODE lockmode, Oid *existing_relation_id)
Definition: namespace.c:536
#define makeNode(_type_)
Definition: nodes.h:621
#define NIL
Definition: pg_list.h:65
FormData_pg_sequence
Definition: pg_sequence.h:33
#define Int64GetDatumFast(X)
Definition: postgres.h:804
uintptr_t Datum
Definition: postgres.h:411
#define BoolGetDatum(X)
Definition: postgres.h:446
@ ONCOMMIT_NOOP
Definition: primnodes.h:49
#define RelationGetDescr(relation)
Definition: rel.h:515
#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
bool is_not_null
Definition: parsenodes.h:682
CollateClause * collClause
Definition: parsenodes.h:691
int location
Definition: parsenodes.h:695
List * constraints
Definition: parsenodes.h:693
Node * cooked_default
Definition: parsenodes.h:686
int inhcount
Definition: parsenodes.h:680
char * colname
Definition: parsenodes.h:677
TypeName * typeName
Definition: parsenodes.h:678
bool is_from_type
Definition: parsenodes.h:683
Node * raw_default
Definition: parsenodes.h:685
char storage
Definition: parsenodes.h:684
Oid collOid
Definition: parsenodes.h:692
bool is_local
Definition: parsenodes.h:681
List * tableElts
Definition: parsenodes.h:2531
OnCommitAction oncommit
Definition: parsenodes.h:2539
List * options
Definition: parsenodes.h:2538
bool if_not_exists
Definition: parsenodes.h:2542
List * inhRelations
Definition: parsenodes.h:2532
RangeVar * relation
Definition: parsenodes.h:2530
char * tablespacename
Definition: parsenodes.h:2540
List * constraints
Definition: parsenodes.h:2537
ObjectAddress DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, ObjectAddress *typaddress, const char *queryString)
Definition: tablecmds.c:658

References AccessExclusiveLock, Assert(), BoolGetDatum, CatalogTupleInsert(), ColumnDef::collClause, ColumnDef::collOid, ColumnDef::colname, ColumnDef::constraints, CreateStmt::constraints, ColumnDef::cooked_default, DefineRelation(), ereport, errcode(), errmsg(), fill_seq_with_data(), CreateSeqStmt::for_identity, FormData_pg_sequence, heap_form_tuple(), heap_freetuple(), i, CreateStmt::if_not_exists, CreateSeqStmt::if_not_exists, ColumnDef::inhcount, CreateStmt::inhRelations, init_params(), Int64GetDatum(), Int64GetDatumFast, InvalidObjectAddress, InvalidOid, ColumnDef::is_from_type, ColumnDef::is_local, ColumnDef::is_not_null, lappend(), FormData_pg_sequence_data::last_value, ColumnDef::location, makeNode, makeTypeNameFromOid(), NIL, NoLock, NOTICE, ObjectAddress::objectId, ObjectIdGetDatum, OidIsValid, CreateStmt::oncommit, ONCOMMIT_NOOP, CreateStmt::options, CreateSeqStmt::options, CreateSeqStmt::ownerId, process_owned_by(), RangeVarGetAndCheckCreationNamespace(), ColumnDef::raw_default, CreateStmt::relation, RelationGetDescr, RangeVar::relname, RowExclusiveLock, SEQ_COL_CALLED, SEQ_COL_FIRSTCOL, SEQ_COL_LASTCOL, SEQ_COL_LASTVAL, SEQ_COL_LOG, CreateSeqStmt::sequence, ColumnDef::storage, table_close(), table_open(), CreateStmt::tableElts, CreateStmt::tablespacename, ColumnDef::typeName, and value.

Referenced by ProcessUtilitySlow().

◆ DeleteSequenceTuple()

void DeleteSequenceTuple ( Oid  relid)

Definition at line 568 of file sequence.c.

569 {
570  Relation rel;
571  HeapTuple tuple;
572 
573  rel = table_open(SequenceRelationId, RowExclusiveLock);
574 
575  tuple = SearchSysCache1(SEQRELID, ObjectIdGetDatum(relid));
576  if (!HeapTupleIsValid(tuple))
577  elog(ERROR, "cache lookup failed for sequence %u", relid);
578 
579  CatalogTupleDelete(rel, &tuple->t_self);
580 
581  ReleaseSysCache(tuple);
583 }
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:350
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:1221
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:1173

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

Referenced by doDeletion().

◆ nextval()

Datum nextval ( PG_FUNCTION_ARGS  )

Definition at line 591 of file sequence.c.

592 {
593  text *seqin = PG_GETARG_TEXT_PP(0);
594  RangeVar *sequence;
595  Oid relid;
596 
598 
599  /*
600  * XXX: This is not safe in the presence of concurrent DDL, but acquiring
601  * a lock here is more expensive than letting nextval_internal do it,
602  * since the latter maintains a cache that keeps us from hitting the lock
603  * manager more than once per transaction. It's not clear whether the
604  * performance penalty is material in practice, but for now, we do it this
605  * way.
606  */
607  relid = RangeVarGetRelid(sequence, NoLock, false);
608 
609  PG_RETURN_INT64(nextval_internal(relid, true));
610 }
#define PG_GETARG_TEXT_PP(n)
Definition: fmgr.h:309
#define PG_RETURN_INT64(x)
Definition: fmgr.h:368
RangeVar * makeRangeVarFromNameList(List *names)
Definition: namespace.c:3108
#define RangeVarGetRelid(relation, lockmode, missing_ok)
Definition: namespace.h:79
int64 nextval_internal(Oid relid, bool check_permissions)
Definition: sequence.c:621
Definition: c.h:622
List * textToQualifiedNameList(text *textval)
Definition: varlena.c:3657

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

Referenced by autoinc(), and ttdummy().

◆ nextval_internal()

int64 nextval_internal ( Oid  relid,
bool  check_permissions 
)

Definition at line 621 of file sequence.c.

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

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, FormData_pg_sequence_data::log_cnt, MarkBufferDirty(), next, xl_seq_rec::node, NoLock, ObjectIdGetDatum, PageGetLSN, PageSetLSN, pg_class_aclcheck(), PreventCommandIfParallelMode(), PreventCommandIfReadOnly(), RelationData::rd_islocaltemp, RelationData::rd_node, read_seq_tuple(), REGBUF_WILL_INIT, relation_close(), RelationGetRelationName, RelationNeedsWAL, ReleaseSysCache(), SeqTableData::relid, SearchSysCache1(), SEQ_LOG_VALS, SEQRELID, 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  RelationSetNewRelfilenode(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  relation_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(), relation_close(), RelationSetNewRelfilenode(), ReleaseSysCache(), SearchSysCache1(), SEQRELID, and UnlockReleaseBuffer().

Referenced by ExecuteTruncateGuts().

◆ ResetSequenceCaches()

void ResetSequenceCaches ( void  )

Definition at line 1889 of file sequence.c.

1890 {
1891  if (seqhashtab)
1892  {
1894  seqhashtab = NULL;
1895  }
1896 
1897  last_used_seq = NULL;
1898 }
void hash_destroy(HTAB *hashp)
Definition: dynahash.c:862
static HTAB * seqhashtab
Definition: sequence.c:90

References hash_destroy(), last_used_seq, and seqhashtab.

Referenced by DiscardAll(), and DiscardCommand().

◆ seq_desc()

void seq_desc ( StringInfo  buf,
XLogReaderState rptr 
)

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->node.spcNode, xlrec->node.dbNode,
30  xlrec->node.relNode);
31 }
unsigned char uint8
Definition: c.h:439
void appendStringInfo(StringInfo str, const char *fmt,...)
Definition: stringinfo.c:91
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:408
#define XLogRecGetData(decoder)
Definition: xlogreader.h:413
#define XLR_INFO_MASK
Definition: xlogrecord.h:62

References appendStringInfo(), buf, RelFileNode::dbNode, xl_seq_rec::node, RelFileNode::relNode, RelFileNode::spcNode, XLOG_SEQ_LOG, XLogRecGetData, XLogRecGetInfo, and XLR_INFO_MASK.

◆ 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 }

References XLOG_SEQ_LOG, and XLR_INFO_MASK.

◆ seq_mask()

void seq_mask ( char *  pagedata,
BlockNumber  blkno 
)

Definition at line 1904 of file sequence.c.

1905 {
1907 
1908  mask_unused_space(page);
1909 }
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 rptr)

Definition at line 1836 of file sequence.c.

1837 {
1838  XLogRecPtr lsn = record->EndRecPtr;
1839  uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
1840  Buffer buffer;
1841  Page page;
1842  Page localpage;
1843  char *item;
1844  Size itemsz;
1845  xl_seq_rec *xlrec = (xl_seq_rec *) XLogRecGetData(record);
1846  sequence_magic *sm;
1847 
1848  if (info != XLOG_SEQ_LOG)
1849  elog(PANIC, "seq_redo: unknown op code %u", info);
1850 
1851  buffer = XLogInitBufferForRedo(record, 0);
1852  page = (Page) BufferGetPage(buffer);
1853 
1854  /*
1855  * We always reinit the page. However, since this WAL record type is also
1856  * used for updating sequences, it's possible that a hot-standby backend
1857  * is examining the page concurrently; so we mustn't transiently trash the
1858  * buffer. The solution is to build the correct new page contents in
1859  * local workspace and then memcpy into the buffer. Then only bytes that
1860  * are supposed to change will change, even transiently. We must palloc
1861  * the local page for alignment reasons.
1862  */
1863  localpage = (Page) palloc(BufferGetPageSize(buffer));
1864 
1865  PageInit(localpage, BufferGetPageSize(buffer), sizeof(sequence_magic));
1866  sm = (sequence_magic *) PageGetSpecialPointer(localpage);
1867  sm->magic = SEQ_MAGIC;
1868 
1869  item = (char *) xlrec + sizeof(xl_seq_rec);
1870  itemsz = XLogRecGetDataLen(record) - sizeof(xl_seq_rec);
1871 
1872  if (PageAddItem(localpage, (Item) item, itemsz,
1873  FirstOffsetNumber, false, false) == InvalidOffsetNumber)
1874  elog(PANIC, "seq_redo: failed to add item to page");
1875 
1876  PageSetLSN(localpage, lsn);
1877 
1878  memcpy(page, localpage, BufferGetPageSize(buffer));
1879  MarkBufferDirty(buffer);
1880  UnlockReleaseBuffer(buffer);
1881 
1882  pfree(localpage);
1883 }
#define BufferGetPageSize(buffer)
Definition: bufmgr.h:156
void PageInit(Page page, Size pageSize, Size specialSize)
Definition: bufpage.c:42
#define PageGetSpecialPointer(page)
Definition: bufpage.h:325
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
Definition: bufpage.h:415
size_t Size
Definition: c.h:540
#define PANIC
Definition: elog.h:36
Pointer Item
Definition: item.h:17
void pfree(void *pointer)
Definition: mcxt.c:1175
void * palloc(Size size)
Definition: mcxt.c:1068
#define InvalidOffsetNumber
Definition: off.h:26
#define FirstOffsetNumber
Definition: off.h:27
#define SEQ_MAGIC
Definition: sequence.c:62
struct xl_seq_rec xl_seq_rec
uint32 magic
Definition: sequence.c:66
#define XLogRecGetDataLen(decoder)
Definition: xlogreader.h:414
Buffer XLogInitBufferForRedo(XLogReaderState *record, uint8 block_id)
Definition: xlogutils.c:328

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, XLogRecGetInfo, and XLR_INFO_MASK.

◆ sequence_options()

List* sequence_options ( Oid  relid)

Definition at line 1707 of file sequence.c.

1708 {
1709  HeapTuple pgstuple;
1710  Form_pg_sequence pgsform;
1711  List *options = NIL;
1712 
1713  pgstuple = SearchSysCache1(SEQRELID, relid);
1714  if (!HeapTupleIsValid(pgstuple))
1715  elog(ERROR, "cache lookup failed for sequence %u", relid);
1716  pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
1717 
1718  /* Use makeFloat() for 64-bit integers, like gram.y does. */
1720  makeDefElem("cache", (Node *) makeFloat(psprintf(INT64_FORMAT, pgsform->seqcache)), -1));
1722  makeDefElem("cycle", (Node *) makeBoolean(pgsform->seqcycle), -1));
1724  makeDefElem("increment", (Node *) makeFloat(psprintf(INT64_FORMAT, pgsform->seqincrement)), -1));
1726  makeDefElem("maxvalue", (Node *) makeFloat(psprintf(INT64_FORMAT, pgsform->seqmax)), -1));
1728  makeDefElem("minvalue", (Node *) makeFloat(psprintf(INT64_FORMAT, pgsform->seqmin)), -1));
1730  makeDefElem("start", (Node *) makeFloat(psprintf(INT64_FORMAT, pgsform->seqstart)), -1));
1731 
1732  ReleaseSysCache(pgstuple);
1733 
1734  return options;
1735 }
#define INT64_FORMAT
Definition: c.h:483
DefElem * makeDefElem(char *name, Node *arg, int location)
Definition: makefuncs.c:547
static char ** options
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
Definition: nodes.h:574
Boolean * makeBoolean(bool val)
Definition: value.c:49
Float * makeFloat(char *numericStr)
Definition: value.c:37

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

Referenced by transformTableLikeClause().

◆ SequenceChangePersistence()

void SequenceChangePersistence ( Oid  relid,
char  newrelpersistence 
)

Definition at line 546 of file sequence.c.

547 {
548  SeqTable elm;
549  Relation seqrel;
550  Buffer buf;
551  HeapTupleData seqdatatuple;
552 
553  init_sequence(relid, &elm, &seqrel);
554 
555  /* check the comment above nextval_internal()'s equivalent call. */
556  if (RelationNeedsWAL(seqrel))
558 
559  (void) read_seq_tuple(seqrel, &buf, &seqdatatuple);
560  RelationSetNewRelfilenode(seqrel, newrelpersistence);
561  fill_seq_with_data(seqrel, &seqdatatuple);
563 
564  relation_close(seqrel, NoLock);
565 }

References buf, fill_seq_with_data(), GetTopTransactionId(), init_sequence(), NoLock, read_seq_tuple(), relation_close(), RelationNeedsWAL, RelationSetNewRelfilenode(), and UnlockReleaseBuffer().

Referenced by ATRewriteTables().