PostgreSQL Source Code  git master
sequence.c File Reference
#include "postgres.h"
#include "access/bufmask.h"
#include "access/htup_details.h"
#include "access/multixact.h"
#include "access/relation.h"
#include "access/table.h"
#include "access/transam.h"
#include "access/xact.h"
#include "access/xlog.h"
#include "access/xloginsert.h"
#include "access/xlogutils.h"
#include "catalog/dependency.h"
#include "catalog/indexing.h"
#include "catalog/namespace.h"
#include "catalog/objectaccess.h"
#include "catalog/pg_sequence.h"
#include "catalog/pg_type.h"
#include "catalog/storage_xlog.h"
#include "commands/defrem.h"
#include "commands/sequence.h"
#include "commands/tablecmds.h"
#include "funcapi.h"
#include "miscadmin.h"
#include "nodes/makefuncs.h"
#include "parser/parse_type.h"
#include "storage/lmgr.h"
#include "storage/proc.h"
#include "storage/smgr.h"
#include "utils/acl.h"
#include "utils/builtins.h"
#include "utils/lsyscache.h"
#include "utils/resowner.h"
#include "utils/syscache.h"
#include "utils/varlena.h"
Include dependency graph for sequence.c:

Go to the source code of this file.

Data Structures

struct  sequence_magic
 
struct  SeqTableData
 

Macros

#define SEQ_LOG_VALS   32
 
#define SEQ_MAGIC   0x1717
 

Typedefs

typedef struct sequence_magic sequence_magic
 
typedef struct SeqTableData SeqTableData
 
typedef SeqTableDataSeqTable
 

Functions

static void fill_seq_with_data (Relation rel, HeapTuple tuple)
 
static void fill_seq_fork_with_data (Relation rel, HeapTuple tuple, ForkNumber forkNum)
 
static Relation lock_and_open_sequence (SeqTable seq)
 
static void create_seq_hashtable (void)
 
static void init_sequence (Oid relid, SeqTable *p_elm, Relation *p_rel)
 
static Form_pg_sequence_data read_seq_tuple (Relation rel, Buffer *buf, HeapTuple seqdatatuple)
 
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)
 
static void do_setval (Oid relid, int64 next, bool iscalled)
 
static void process_owned_by (Relation seqrel, List *owned_by, bool for_identity)
 
ObjectAddress DefineSequence (ParseState *pstate, CreateSeqStmt *seq)
 
void ResetSequence (Oid seq_relid)
 
ObjectAddress AlterSequence (ParseState *pstate, AlterSeqStmt *stmt)
 
void SequenceChangePersistence (Oid relid, char newrelpersistence)
 
void DeleteSequenceTuple (Oid relid)
 
Datum nextval (PG_FUNCTION_ARGS)
 
Datum nextval_oid (PG_FUNCTION_ARGS)
 
int64 nextval_internal (Oid relid, bool check_permissions)
 
Datum currval_oid (PG_FUNCTION_ARGS)
 
Datum lastval (PG_FUNCTION_ARGS)
 
Datum setval_oid (PG_FUNCTION_ARGS)
 
Datum setval3_oid (PG_FUNCTION_ARGS)
 
Listsequence_options (Oid relid)
 
Datum pg_sequence_parameters (PG_FUNCTION_ARGS)
 
Datum pg_sequence_last_value (PG_FUNCTION_ARGS)
 
void seq_redo (XLogReaderState *record)
 
void ResetSequenceCaches (void)
 
void seq_mask (char *page, BlockNumber blkno)
 

Variables

static HTABseqhashtab = NULL
 
static SeqTableDatalast_used_seq = NULL
 

Macro Definition Documentation

◆ SEQ_LOG_VALS

#define SEQ_LOG_VALS   32

Definition at line 57 of file sequence.c.

◆ SEQ_MAGIC

#define SEQ_MAGIC   0x1717

Definition at line 62 of file sequence.c.

Typedef Documentation

◆ SeqTable

Definition at line 88 of file sequence.c.

◆ SeqTableData

typedef struct SeqTableData SeqTableData

◆ sequence_magic

Function Documentation

◆ AlterSequence()

ObjectAddress AlterSequence ( ParseState pstate,
AlterSeqStmt stmt 
)

Definition at line 436 of file sequence.c.

437 {
438  Oid relid;
439  SeqTable elm;
440  Relation seqrel;
441  Buffer buf;
442  HeapTupleData datatuple;
443  Form_pg_sequence seqform;
444  Form_pg_sequence_data newdataform;
445  bool need_seq_rewrite;
446  List *owned_by;
447  ObjectAddress address;
448  Relation rel;
449  HeapTuple seqtuple;
450  HeapTuple newdatatuple;
451 
452  /* Open and lock sequence, and check for ownership along the way. */
453  relid = RangeVarGetRelidExtended(stmt->sequence,
455  stmt->missing_ok ? RVR_MISSING_OK : 0,
457  NULL);
458  if (relid == InvalidOid)
459  {
460  ereport(NOTICE,
461  (errmsg("relation \"%s\" does not exist, skipping",
462  stmt->sequence->relname)));
463  return InvalidObjectAddress;
464  }
465 
466  init_sequence(relid, &elm, &seqrel);
467 
468  rel = table_open(SequenceRelationId, RowExclusiveLock);
469  seqtuple = SearchSysCacheCopy1(SEQRELID,
470  ObjectIdGetDatum(relid));
471  if (!HeapTupleIsValid(seqtuple))
472  elog(ERROR, "cache lookup failed for sequence %u",
473  relid);
474 
475  seqform = (Form_pg_sequence) GETSTRUCT(seqtuple);
476 
477  /* lock page's buffer and read tuple into new sequence structure */
478  (void) read_seq_tuple(seqrel, &buf, &datatuple);
479 
480  /* copy the existing sequence data tuple, so it can be modified locally */
481  newdatatuple = heap_copytuple(&datatuple);
482  newdataform = (Form_pg_sequence_data) GETSTRUCT(newdatatuple);
483 
485 
486  /* Check and set new values */
487  init_params(pstate, stmt->options, stmt->for_identity, false,
488  seqform, newdataform,
489  &need_seq_rewrite, &owned_by);
490 
491  /* Clear local cache so that we don't think we have cached numbers */
492  /* Note that we do not change the currval() state */
493  elm->cached = elm->last;
494 
495  /* If needed, rewrite the sequence relation itself */
496  if (need_seq_rewrite)
497  {
498  /* check the comment above nextval_internal()'s equivalent call. */
499  if (RelationNeedsWAL(seqrel))
501 
502  /*
503  * Create a new storage file for the sequence, making the state
504  * changes transactional.
505  */
506  RelationSetNewRelfilenumber(seqrel, seqrel->rd_rel->relpersistence);
507 
508  /*
509  * Ensure sequence's relfrozenxid is at 0, since it won't contain any
510  * unfrozen XIDs. Same with relminmxid, since a sequence will never
511  * contain multixacts.
512  */
513  Assert(seqrel->rd_rel->relfrozenxid == InvalidTransactionId);
514  Assert(seqrel->rd_rel->relminmxid == InvalidMultiXactId);
515 
516  /*
517  * Insert the modified tuple into the new storage file.
518  */
519  fill_seq_with_data(seqrel, newdatatuple);
520  }
521 
522  /* process OWNED BY if given */
523  if (owned_by)
524  process_owned_by(seqrel, owned_by, stmt->for_identity);
525 
526  /* update the pg_sequence tuple (we could skip this in some cases...) */
527  CatalogTupleUpdate(rel, &seqtuple->t_self, seqtuple);
528 
529  InvokeObjectPostAlterHook(RelationRelationId, relid, 0);
530 
531  ObjectAddressSet(address, RelationRelationId, relid);
532 
534  relation_close(seqrel, NoLock);
535 
536  return address;
537 }
int Buffer
Definition: buf.h:23
void UnlockReleaseBuffer(Buffer buffer)
Definition: bufmgr.c:4497
int errmsg(const char *fmt,...)
Definition: elog.c:1069
#define ERROR
Definition: elog.h:39
#define NOTICE
Definition: elog.h:35
#define ereport(elevel,...)
Definition: elog.h:149
HeapTuple heap_copytuple(HeapTuple tuple)
Definition: heaptuple.c:768
#define HeapTupleIsValid(tuple)
Definition: htup.h:78
#define GETSTRUCT(TUP)
Definition: htup_details.h:653
#define stmt
Definition: indent_codes.h:59
void CatalogTupleUpdate(Relation heapRel, ItemPointer otid, HeapTuple tup)
Definition: indexing.c:313
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:221
@ RVR_MISSING_OK
Definition: namespace.h:71
#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:67
static Datum ObjectIdGetDatum(Oid X)
Definition: postgres.h:252
#define InvalidOid
Definition: postgres_ext.h:36
unsigned int Oid
Definition: postgres_ext.h:31
#define RelationNeedsWAL(relation)
Definition: rel.h:629
void RelationSetNewRelfilenumber(Relation relation, char persistence)
Definition: relcache.c:3710
static void fill_seq_with_data(Relation rel, HeapTuple tuple)
Definition: sequence.c:337
static void init_sequence(Oid relid, SeqTable *p_elm, Relation *p_rel)
Definition: sequence.c:1121
static Form_pg_sequence_data read_seq_tuple(Relation rel, Buffer *buf, HeapTuple seqdatatuple)
Definition: sequence.c:1188
static void process_owned_by(Relation seqrel, List *owned_by, bool for_identity)
Definition: sequence.c:1588
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:1255
FormData_pg_sequence_data * Form_pg_sequence_data
Definition: sequence.h:32
void relation_close(Relation relation, LOCKMODE lockmode)
Definition: relation.c:206
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:82
int64 last
Definition: sequence.c:81
#define SearchSysCacheCopy1(cacheId, key1)
Definition: syscache.h:182
@ SEQRELID
Definition: syscache.h:93
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:17755
#define InvalidTransactionId
Definition: transam.h:31
TransactionId GetTopTransactionId(void)
Definition: xact.c:417

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, SeqTableData::last, NoLock, NOTICE, ObjectAddressSet, ObjectIdGetDatum(), process_owned_by(), RangeVarCallbackOwnsRelation(), RangeVarGetRelidExtended(), RelationData::rd_rel, read_seq_tuple(), relation_close(), RelationNeedsWAL, RelationSetNewRelfilenumber(), RowExclusiveLock, RVR_MISSING_OK, SearchSysCacheCopy1, SEQRELID, ShareRowExclusiveLock, stmt, HeapTupleData::t_self, table_close(), table_open(), and UnlockReleaseBuffer().

Referenced by ProcessUtilitySlow().

◆ create_seq_hashtable()

static void create_seq_hashtable ( void  )
static

Definition at line 1105 of file sequence.c.

1106 {
1107  HASHCTL ctl;
1108 
1109  ctl.keysize = sizeof(Oid);
1110  ctl.entrysize = sizeof(SeqTableData);
1111 
1112  seqhashtab = hash_create("Sequence values", 16, &ctl,
1113  HASH_ELEM | HASH_BLOBS);
1114 }
HTAB * hash_create(const char *tabname, long nelem, const HASHCTL *info, int flags)
Definition: dynahash.c:350
#define HASH_ELEM
Definition: hsearch.h:95
#define HASH_BLOBS
Definition: hsearch.h:97
static HTAB * seqhashtab
Definition: sequence.c:90
struct SeqTableData SeqTableData
Size keysize
Definition: hsearch.h:75
Size entrysize
Definition: hsearch.h:76

References HASHCTL::entrysize, HASH_BLOBS, hash_create(), HASH_ELEM, HASHCTL::keysize, and seqhashtab.

Referenced by init_sequence().

◆ currval_oid()

Datum currval_oid ( PG_FUNCTION_ARGS  )

Definition at line 858 of file sequence.c.

859 {
860  Oid relid = PG_GETARG_OID(0);
861  int64 result;
862  SeqTable elm;
863  Relation seqrel;
864 
865  /* open and lock sequence */
866  init_sequence(relid, &elm, &seqrel);
867 
868  if (pg_class_aclcheck(elm->relid, GetUserId(),
870  ereport(ERROR,
871  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
872  errmsg("permission denied for sequence %s",
873  RelationGetRelationName(seqrel))));
874 
875  if (!elm->last_valid)
876  ereport(ERROR,
877  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
878  errmsg("currval of sequence \"%s\" is not yet defined in this session",
879  RelationGetRelationName(seqrel))));
880 
881  result = elm->last;
882 
883  relation_close(seqrel, NoLock);
884 
885  PG_RETURN_INT64(result);
886 }
@ ACLCHECK_OK
Definition: acl.h:182
AclResult pg_class_aclcheck(Oid table_oid, Oid roleid, AclMode mode)
Definition: aclchk.c:3908
int errcode(int sqlerrcode)
Definition: elog.c:858
#define PG_GETARG_OID(n)
Definition: fmgr.h:275
#define PG_RETURN_INT64(x)
Definition: fmgr.h:368
Oid GetUserId(void)
Definition: miscinit.c:509
#define ACL_USAGE
Definition: parsenodes.h:91
#define ACL_SELECT
Definition: parsenodes.h:84
#define RelationGetRelationName(relation)
Definition: rel.h:538
bool last_valid
Definition: sequence.c:80

References ACL_SELECT, ACL_USAGE, ACLCHECK_OK, ereport, errcode(), errmsg(), ERROR, GetUserId(), init_sequence(), SeqTableData::last, SeqTableData::last_valid, NoLock, pg_class_aclcheck(), PG_GETARG_OID, PG_RETURN_INT64, relation_close(), RelationGetRelationName, and SeqTableData::relid.

◆ DefineSequence()

ObjectAddress DefineSequence ( ParseState pstate,
CreateSeqStmt seq 
)

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;
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  {
146  if (OidIsValid(seqoid))
147  {
148  /*
149  * If we are in an extension script, insist that the pre-existing
150  * object be a member of the extension, to avoid security risks.
151  */
152  ObjectAddressSet(address, RelationRelationId, seqoid);
154 
155  /* OK to skip */
156  ereport(NOTICE,
157  (errcode(ERRCODE_DUPLICATE_TABLE),
158  errmsg("relation \"%s\" already exists, skipping",
159  seq->sequence->relname)));
160  return InvalidObjectAddress;
161  }
162  }
163 
164  /* Check and set all option values */
165  init_params(pstate, seq->options, seq->for_identity, true,
166  &seqform, &seqdataform,
167  &need_seq_rewrite, &owned_by);
168 
169  /*
170  * Create relation (and fill value[] and null[] for the tuple)
171  */
172  stmt->tableElts = NIL;
173  for (i = SEQ_COL_FIRSTCOL; i <= SEQ_COL_LASTCOL; i++)
174  {
175  ColumnDef *coldef = NULL;
176 
177  switch (i)
178  {
179  case SEQ_COL_LASTVAL:
180  coldef = makeColumnDef("last_value", INT8OID, -1, InvalidOid);
181  value[i - 1] = Int64GetDatumFast(seqdataform.last_value);
182  break;
183  case SEQ_COL_LOG:
184  coldef = makeColumnDef("log_cnt", INT8OID, -1, InvalidOid);
185  value[i - 1] = Int64GetDatum((int64) 0);
186  break;
187  case SEQ_COL_CALLED:
188  coldef = makeColumnDef("is_called", BOOLOID, -1, InvalidOid);
189  value[i - 1] = BoolGetDatum(false);
190  break;
191  }
192 
193  coldef->is_not_null = true;
194  null[i - 1] = false;
195 
196  stmt->tableElts = lappend(stmt->tableElts, coldef);
197  }
198 
199  stmt->relation = seq->sequence;
200  stmt->inhRelations = NIL;
201  stmt->constraints = NIL;
202  stmt->options = NIL;
203  stmt->oncommit = ONCOMMIT_NOOP;
204  stmt->tablespacename = NULL;
205  stmt->if_not_exists = seq->if_not_exists;
206 
207  address = DefineRelation(stmt, RELKIND_SEQUENCE, seq->ownerId, NULL, NULL);
208  seqoid = address.objectId;
209  Assert(seqoid != InvalidOid);
210 
211  rel = table_open(seqoid, AccessExclusiveLock);
212  tupDesc = RelationGetDescr(rel);
213 
214  /* now initialize the sequence's data */
215  tuple = heap_form_tuple(tupDesc, value, null);
216  fill_seq_with_data(rel, tuple);
217 
218  /* process OWNED BY if given */
219  if (owned_by)
220  process_owned_by(rel, owned_by, seq->for_identity);
221 
222  table_close(rel, NoLock);
223 
224  /* fill in pg_sequence */
225  rel = table_open(SequenceRelationId, RowExclusiveLock);
226  tupDesc = RelationGetDescr(rel);
227 
228  memset(pgs_nulls, 0, sizeof(pgs_nulls));
229 
230  pgs_values[Anum_pg_sequence_seqrelid - 1] = ObjectIdGetDatum(seqoid);
231  pgs_values[Anum_pg_sequence_seqtypid - 1] = ObjectIdGetDatum(seqform.seqtypid);
232  pgs_values[Anum_pg_sequence_seqstart - 1] = Int64GetDatumFast(seqform.seqstart);
233  pgs_values[Anum_pg_sequence_seqincrement - 1] = Int64GetDatumFast(seqform.seqincrement);
234  pgs_values[Anum_pg_sequence_seqmax - 1] = Int64GetDatumFast(seqform.seqmax);
235  pgs_values[Anum_pg_sequence_seqmin - 1] = Int64GetDatumFast(seqform.seqmin);
236  pgs_values[Anum_pg_sequence_seqcache - 1] = Int64GetDatumFast(seqform.seqcache);
237  pgs_values[Anum_pg_sequence_seqcycle - 1] = BoolGetDatum(seqform.seqcycle);
238 
239  tuple = heap_form_tuple(tupDesc, pgs_values, pgs_nulls);
240  CatalogTupleInsert(rel, tuple);
241 
242  heap_freetuple(tuple);
244 
245  return address;
246 }
#define OidIsValid(objectId)
Definition: c.h:764
Datum Int64GetDatum(int64 X)
Definition: fmgr.c:1790
HeapTuple heap_form_tuple(TupleDesc tupleDescriptor, Datum *values, bool *isnull)
Definition: heaptuple.c:1108
void heap_freetuple(HeapTuple htup)
Definition: heaptuple.c:1426
void CatalogTupleInsert(Relation heapRel, HeapTuple tup)
Definition: indexing.c:233
static struct @148 value
int i
Definition: isn.c:73
List * lappend(List *list, void *datum)
Definition: list.c:338
#define AccessExclusiveLock
Definition: lockdefs.h:43
ColumnDef * makeColumnDef(const char *colname, Oid typeOid, int32 typmod, Oid collOid)
Definition: makefuncs.c:493
Oid RangeVarGetAndCheckCreationNamespace(RangeVar *relation, LOCKMODE lockmode, Oid *existing_relation_id)
Definition: namespace.c:519
#define makeNode(_type_)
Definition: nodes.h:176
void checkMembershipInCurrentExtension(const ObjectAddress *object)
Definition: pg_depend.c:257
#define NIL
Definition: pg_list.h:68
FormData_pg_sequence
Definition: pg_sequence.h:33
#define Int64GetDatumFast(X)
Definition: postgres.h:554
uintptr_t Datum
Definition: postgres.h:64
static Datum BoolGetDatum(bool X)
Definition: postgres.h:102
@ ONCOMMIT_NOOP
Definition: primnodes.h:49
#define RelationGetDescr(relation)
Definition: rel.h:530
#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:725
bool if_not_exists
Definition: parsenodes.h:2998
List * options
Definition: parsenodes.h:2995
RangeVar * sequence
Definition: parsenodes.h:2994
char * relname
Definition: primnodes.h:74
ObjectAddress DefineRelation(CreateStmt *stmt, char relkind, Oid ownerId, ObjectAddress *typaddress, const char *queryString)
Definition: tablecmds.c:674

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(), FormData_pg_sequence_data::last_value, 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, stmt, table_close(), table_open(), and value.

Referenced by ProcessUtilitySlow().

◆ DeleteSequenceTuple()

void DeleteSequenceTuple ( Oid  relid)

Definition at line 562 of file sequence.c.

563 {
564  Relation rel;
565  HeapTuple tuple;
566 
567  rel = table_open(SequenceRelationId, RowExclusiveLock);
568 
569  tuple = SearchSysCache1(SEQRELID, ObjectIdGetDatum(relid));
570  if (!HeapTupleIsValid(tuple))
571  elog(ERROR, "cache lookup failed for sequence %u", relid);
572 
573  CatalogTupleDelete(rel, &tuple->t_self);
574 
575  ReleaseSysCache(tuple);
577 }
void CatalogTupleDelete(Relation heapRel, ItemPointer tid)
Definition: indexing.c:365
void ReleaseSysCache(HeapTuple tuple)
Definition: syscache.c:868
HeapTuple SearchSysCache1(int cacheId, Datum key1)
Definition: syscache.c:820

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

Referenced by doDeletion().

◆ do_setval()

static void do_setval ( Oid  relid,
int64  next,
bool  iscalled 
)
static

Definition at line 937 of file sequence.c.

938 {
939  SeqTable elm;
940  Relation seqrel;
941  Buffer buf;
942  HeapTupleData seqdatatuple;
944  HeapTuple pgstuple;
945  Form_pg_sequence pgsform;
946  int64 maxv,
947  minv;
948 
949  /* open and lock sequence */
950  init_sequence(relid, &elm, &seqrel);
951 
953  ereport(ERROR,
954  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
955  errmsg("permission denied for sequence %s",
956  RelationGetRelationName(seqrel))));
957 
958  pgstuple = SearchSysCache1(SEQRELID, ObjectIdGetDatum(relid));
959  if (!HeapTupleIsValid(pgstuple))
960  elog(ERROR, "cache lookup failed for sequence %u", relid);
961  pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
962  maxv = pgsform->seqmax;
963  minv = pgsform->seqmin;
964  ReleaseSysCache(pgstuple);
965 
966  /* read-only transactions may only modify temp sequences */
967  if (!seqrel->rd_islocaltemp)
968  PreventCommandIfReadOnly("setval()");
969 
970  /*
971  * Forbid this during parallel operation because, to make it work, the
972  * cooperating backends would need to share the backend-local cached
973  * sequence information. Currently, we don't support that.
974  */
975  PreventCommandIfParallelMode("setval()");
976 
977  /* lock page' buffer and read tuple */
978  seq = read_seq_tuple(seqrel, &buf, &seqdatatuple);
979 
980  if ((next < minv) || (next > maxv))
981  ereport(ERROR,
982  (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE),
983  errmsg("setval: value %lld is out of bounds for sequence \"%s\" (%lld..%lld)",
984  (long long) next, RelationGetRelationName(seqrel),
985  (long long) minv, (long long) maxv)));
986 
987  /* Set the currval() state only if iscalled = true */
988  if (iscalled)
989  {
990  elm->last = next; /* last returned number */
991  elm->last_valid = true;
992  }
993 
994  /* In any case, forget any future cached numbers */
995  elm->cached = elm->last;
996 
997  /* check the comment above nextval_internal()'s equivalent call. */
998  if (RelationNeedsWAL(seqrel))
1000 
1001  /* ready to change the on-disk (or really, in-buffer) tuple */
1003 
1004  seq->last_value = next; /* last fetched number */
1005  seq->is_called = iscalled;
1006  seq->log_cnt = 0;
1007 
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();
1019 
1020  xlrec.locator = seqrel->rd_locator;
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 
1032 
1033  relation_close(seqrel, NoLock);
1034 }
static int32 next
Definition: blutils.c:219
void MarkBufferDirty(Buffer buffer)
Definition: bufmgr.c:2111
static Page BufferGetPage(Buffer buffer)
Definition: bufmgr.h:350
Pointer Page
Definition: bufpage.h:78
static void PageSetLSN(Page page, XLogRecPtr lsn)
Definition: bufpage.h:388
#define START_CRIT_SECTION()
Definition: miscadmin.h:148
#define END_CRIT_SECTION()
Definition: miscadmin.h:150
#define ACL_UPDATE
Definition: parsenodes.h:85
#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:61
RelFileLocator rd_locator
Definition: rel.h:57
RelFileLocator locator
Definition: sequence.h:50
void PreventCommandIfReadOnly(const char *cmdname)
Definition: utility.c:411
void PreventCommandIfParallelMode(const char *cmdname)
Definition: utility.c:429
uint64 XLogRecPtr
Definition: xlogdefs.h:21
void XLogRegisterData(char *data, uint32 len)
Definition: xloginsert.c:351
XLogRecPtr XLogInsert(RmgrId rmid, uint8 info)
Definition: xloginsert.c:461
void XLogRegisterBuffer(uint8 block_id, Buffer buffer, uint8 flags)
Definition: xloginsert.c:243
void XLogBeginInsert(void)
Definition: xloginsert.c:150
#define REGBUF_WILL_INIT
Definition: xloginsert.h:33

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, relation_close(), RelationGetRelationName, RelationNeedsWAL, ReleaseSysCache(), SeqTableData::relid, SearchSysCache1(), SEQRELID, START_CRIT_SECTION, HeapTupleData::t_data, HeapTupleData::t_len, UnlockReleaseBuffer(), XLOG_SEQ_LOG, XLogBeginInsert(), XLogInsert(), XLogRegisterBuffer(), and XLogRegisterData().

Referenced by setval3_oid(), and setval_oid().

◆ fill_seq_fork_with_data()

static void fill_seq_fork_with_data ( Relation  rel,
HeapTuple  tuple,
ForkNumber  forkNum 
)
static

Definition at line 358 of file sequence.c.

359 {
360  Buffer buf;
361  Page page;
362  sequence_magic *sm;
363  OffsetNumber offnum;
364 
365  /* Initialize first page of relation with special magic number */
366 
367  buf = ExtendBufferedRel(BMR_REL(rel), forkNum, NULL,
370 
371  page = BufferGetPage(buf);
372 
373  PageInit(page, BufferGetPageSize(buf), sizeof(sequence_magic));
374  sm = (sequence_magic *) PageGetSpecialPointer(page);
375  sm->magic = SEQ_MAGIC;
376 
377  /* Now insert sequence tuple */
378 
379  /*
380  * Since VACUUM does not process sequences, we have to force the tuple to
381  * have xmin = FrozenTransactionId now. Otherwise it would become
382  * invisible to SELECTs after 2G transactions. It is okay to do this
383  * because if the current transaction aborts, no other xact will ever
384  * examine the sequence tuple anyway.
385  */
392 
393  /* check the comment above nextval_internal()'s equivalent call. */
394  if (RelationNeedsWAL(rel))
396 
398 
400 
401  offnum = PageAddItem(page, (Item) tuple->t_data, tuple->t_len,
402  InvalidOffsetNumber, false, false);
403  if (offnum != FirstOffsetNumber)
404  elog(ERROR, "failed to add sequence tuple to page");
405 
406  /* XLOG stuff */
407  if (RelationNeedsWAL(rel) || forkNum == INIT_FORKNUM)
408  {
409  xl_seq_rec xlrec;
410  XLogRecPtr recptr;
411 
412  XLogBeginInsert();
414 
415  xlrec.locator = rel->rd_locator;
416 
417  XLogRegisterData((char *) &xlrec, sizeof(xl_seq_rec));
418  XLogRegisterData((char *) tuple->t_data, tuple->t_len);
419 
420  recptr = XLogInsert(RM_SEQ_ID, XLOG_SEQ_LOG);
421 
422  PageSetLSN(page, recptr);
423  }
424 
426 
428 }
BlockNumber BufferGetBlockNumber(Buffer buffer)
Definition: bufmgr.c:3290
Buffer ExtendBufferedRel(BufferManagerRelation bmr, ForkNumber forkNum, BufferAccessStrategy strategy, uint32 flags)
Definition: bufmgr.c:812
static Size BufferGetPageSize(Buffer buffer)
Definition: bufmgr.h:339
@ EB_SKIP_EXTENSION_LOCK
Definition: bufmgr.h:73
@ EB_LOCK_FIRST
Definition: bufmgr.h:85
#define BMR_REL(p_rel)
Definition: bufmgr.h:106
void PageInit(Page page, Size pageSize, Size specialSize)
Definition: bufpage.c:42
static char * PageGetSpecialPointer(Page page)
Definition: bufpage.h:336
#define PageAddItem(page, item, size, offsetNumber, overwrite, is_heap)
Definition: bufpage.h:468
#define FirstCommandId
Definition: c.h:657
#define HeapTupleHeaderSetXminFrozen(tup)
Definition: htup_details.h:348
#define HeapTupleHeaderSetXmin(tup, xid)
Definition: htup_details.h:315
#define HeapTupleHeaderSetXmax(tup, xid)
Definition: htup_details.h:376
#define HeapTupleHeaderSetCmin(tup, cid)
Definition: htup_details.h:393
#define HEAP_XMAX_INVALID
Definition: htup_details.h:208
Pointer Item
Definition: item.h:17
static void ItemPointerSet(ItemPointerData *pointer, BlockNumber blockNumber, OffsetNumber offNum)
Definition: itemptr.h:135
#define InvalidOffsetNumber
Definition: off.h:26
uint16 OffsetNumber
Definition: off.h:24
#define FirstOffsetNumber
Definition: off.h:27
@ INIT_FORKNUM
Definition: relpath.h:53
#define SEQ_MAGIC
Definition: sequence.c:62
ItemPointerData t_ctid
Definition: htup_details.h:161
uint32 magic
Definition: sequence.c:66
#define FrozenTransactionId
Definition: transam.h:33

References Assert(), BMR_REL, buf, BufferGetBlockNumber(), BufferGetPage(), BufferGetPageSize(), EB_LOCK_FIRST, EB_SKIP_EXTENSION_LOCK, elog(), END_CRIT_SECTION, ERROR, ExtendBufferedRel(), FirstCommandId, FirstOffsetNumber, FrozenTransactionId, GetTopTransactionId(), HEAP_XMAX_INVALID, HeapTupleHeaderSetCmin, HeapTupleHeaderSetXmax, HeapTupleHeaderSetXmin, HeapTupleHeaderSetXminFrozen, INIT_FORKNUM, InvalidOffsetNumber, InvalidTransactionId, ItemPointerSet(), xl_seq_rec::locator, sequence_magic::magic, MarkBufferDirty(), PageAddItem, PageGetSpecialPointer(), PageInit(), PageSetLSN(), RelationData::rd_locator, REGBUF_WILL_INIT, RelationNeedsWAL, SEQ_MAGIC, START_CRIT_SECTION, HeapTupleHeaderData::t_ctid, HeapTupleData::t_data, HeapTupleHeaderData::t_infomask, HeapTupleData::t_len, UnlockReleaseBuffer(), XLOG_SEQ_LOG, XLogBeginInsert(), XLogInsert(), XLogRegisterBuffer(), and XLogRegisterData().

Referenced by fill_seq_with_data().

◆ fill_seq_with_data()

static void fill_seq_with_data ( Relation  rel,
HeapTuple  tuple 
)
static

Definition at line 337 of file sequence.c.

338 {
340 
341  if (rel->rd_rel->relpersistence == RELPERSISTENCE_UNLOGGED)
342  {
343  SMgrRelation srel;
344 
345  srel = smgropen(rel->rd_locator, InvalidBackendId);
346  smgrcreate(srel, INIT_FORKNUM, false);
350  smgrclose(srel);
351  }
352 }
#define InvalidBackendId
Definition: backendid.h:23
void FlushRelationBuffers(Relation rel)
Definition: bufmgr.c:4058
@ MAIN_FORKNUM
Definition: relpath.h:50
static void fill_seq_fork_with_data(Relation rel, HeapTuple tuple, ForkNumber forkNum)
Definition: sequence.c:358
void smgrcreate(SMgrRelation reln, ForkNumber forknum, bool isRedo)
Definition: smgr.c:374
void smgrclose(SMgrRelation reln)
Definition: smgr.c:260
SMgrRelation smgropen(RelFileLocator rlocator, BackendId backend)
Definition: smgr.c:150
void log_smgrcreate(const RelFileLocator *rlocator, ForkNumber forkNum)
Definition: storage.c:185

References fill_seq_fork_with_data(), FlushRelationBuffers(), INIT_FORKNUM, InvalidBackendId, log_smgrcreate(), MAIN_FORKNUM, RelationData::rd_locator, RelationData::rd_rel, smgrclose(), smgrcreate(), and smgropen().

Referenced by AlterSequence(), DefineSequence(), ResetSequence(), and SequenceChangePersistence().

◆ init_params()

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 
)
static

Definition at line 1255 of file sequence.c.

1261 {
1262  DefElem *as_type = NULL;
1263  DefElem *start_value = NULL;
1264  DefElem *restart_value = NULL;
1265  DefElem *increment_by = NULL;
1266  DefElem *max_value = NULL;
1267  DefElem *min_value = NULL;
1268  DefElem *cache_value = NULL;
1269  DefElem *is_cycled = NULL;
1270  ListCell *option;
1271  bool reset_max_value = false;
1272  bool reset_min_value = false;
1273 
1274  *need_seq_rewrite = false;
1275  *owned_by = NIL;
1276 
1277  foreach(option, options)
1278  {
1279  DefElem *defel = (DefElem *) lfirst(option);
1280 
1281  if (strcmp(defel->defname, "as") == 0)
1282  {
1283  if (as_type)
1284  errorConflictingDefElem(defel, pstate);
1285  as_type = defel;
1286  *need_seq_rewrite = true;
1287  }
1288  else if (strcmp(defel->defname, "increment") == 0)
1289  {
1290  if (increment_by)
1291  errorConflictingDefElem(defel, pstate);
1292  increment_by = defel;
1293  *need_seq_rewrite = true;
1294  }
1295  else if (strcmp(defel->defname, "start") == 0)
1296  {
1297  if (start_value)
1298  errorConflictingDefElem(defel, pstate);
1299  start_value = defel;
1300  *need_seq_rewrite = true;
1301  }
1302  else if (strcmp(defel->defname, "restart") == 0)
1303  {
1304  if (restart_value)
1305  errorConflictingDefElem(defel, pstate);
1306  restart_value = defel;
1307  *need_seq_rewrite = true;
1308  }
1309  else if (strcmp(defel->defname, "maxvalue") == 0)
1310  {
1311  if (max_value)
1312  errorConflictingDefElem(defel, pstate);
1313  max_value = defel;
1314  *need_seq_rewrite = true;
1315  }
1316  else if (strcmp(defel->defname, "minvalue") == 0)
1317  {
1318  if (min_value)
1319  errorConflictingDefElem(defel, pstate);
1320  min_value = defel;
1321  *need_seq_rewrite = true;
1322  }
1323  else if (strcmp(defel->defname, "cache") == 0)
1324  {
1325  if (cache_value)
1326  errorConflictingDefElem(defel, pstate);
1327  cache_value = defel;
1328  *need_seq_rewrite = true;
1329  }
1330  else if (strcmp(defel->defname, "cycle") == 0)
1331  {
1332  if (is_cycled)
1333  errorConflictingDefElem(defel, pstate);
1334  is_cycled = defel;
1335  *need_seq_rewrite = true;
1336  }
1337  else if (strcmp(defel->defname, "owned_by") == 0)
1338  {
1339  if (*owned_by)
1340  errorConflictingDefElem(defel, pstate);
1341  *owned_by = defGetQualifiedName(defel);
1342  }
1343  else if (strcmp(defel->defname, "sequence_name") == 0)
1344  {
1345  /*
1346  * The parser allows this, but it is only for identity columns, in
1347  * which case it is filtered out in parse_utilcmd.c. We only get
1348  * here if someone puts it into a CREATE SEQUENCE.
1349  */
1350  ereport(ERROR,
1351  (errcode(ERRCODE_SYNTAX_ERROR),
1352  errmsg("invalid sequence option SEQUENCE NAME"),
1353  parser_errposition(pstate, defel->location)));
1354  }
1355  else
1356  elog(ERROR, "option \"%s\" not recognized",
1357  defel->defname);
1358  }
1359 
1360  /*
1361  * We must reset log_cnt when isInit or when changing any parameters that
1362  * would affect future nextval allocations.
1363  */
1364  if (isInit)
1365  seqdataform->log_cnt = 0;
1366 
1367  /* AS type */
1368  if (as_type != NULL)
1369  {
1370  Oid newtypid = typenameTypeId(pstate, defGetTypeName(as_type));
1371 
1372  if (newtypid != INT2OID &&
1373  newtypid != INT4OID &&
1374  newtypid != INT8OID)
1375  ereport(ERROR,
1376  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1377  for_identity
1378  ? errmsg("identity column type must be smallint, integer, or bigint")
1379  : errmsg("sequence type must be smallint, integer, or bigint")));
1380 
1381  if (!isInit)
1382  {
1383  /*
1384  * When changing type and the old sequence min/max values were the
1385  * min/max of the old type, adjust sequence min/max values to
1386  * min/max of new type. (Otherwise, the user chose explicit
1387  * min/max values, which we'll leave alone.)
1388  */
1389  if ((seqform->seqtypid == INT2OID && seqform->seqmax == PG_INT16_MAX) ||
1390  (seqform->seqtypid == INT4OID && seqform->seqmax == PG_INT32_MAX) ||
1391  (seqform->seqtypid == INT8OID && seqform->seqmax == PG_INT64_MAX))
1392  reset_max_value = true;
1393  if ((seqform->seqtypid == INT2OID && seqform->seqmin == PG_INT16_MIN) ||
1394  (seqform->seqtypid == INT4OID && seqform->seqmin == PG_INT32_MIN) ||
1395  (seqform->seqtypid == INT8OID && seqform->seqmin == PG_INT64_MIN))
1396  reset_min_value = true;
1397  }
1398 
1399  seqform->seqtypid = newtypid;
1400  }
1401  else if (isInit)
1402  {
1403  seqform->seqtypid = INT8OID;
1404  }
1405 
1406  /* INCREMENT BY */
1407  if (increment_by != NULL)
1408  {
1409  seqform->seqincrement = defGetInt64(increment_by);
1410  if (seqform->seqincrement == 0)
1411  ereport(ERROR,
1412  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1413  errmsg("INCREMENT must not be zero")));
1414  seqdataform->log_cnt = 0;
1415  }
1416  else if (isInit)
1417  {
1418  seqform->seqincrement = 1;
1419  }
1420 
1421  /* CYCLE */
1422  if (is_cycled != NULL)
1423  {
1424  seqform->seqcycle = boolVal(is_cycled->arg);
1425  Assert(BoolIsValid(seqform->seqcycle));
1426  seqdataform->log_cnt = 0;
1427  }
1428  else if (isInit)
1429  {
1430  seqform->seqcycle = false;
1431  }
1432 
1433  /* MAXVALUE (null arg means NO MAXVALUE) */
1434  if (max_value != NULL && max_value->arg)
1435  {
1436  seqform->seqmax = defGetInt64(max_value);
1437  seqdataform->log_cnt = 0;
1438  }
1439  else if (isInit || max_value != NULL || reset_max_value)
1440  {
1441  if (seqform->seqincrement > 0 || reset_max_value)
1442  {
1443  /* ascending seq */
1444  if (seqform->seqtypid == INT2OID)
1445  seqform->seqmax = PG_INT16_MAX;
1446  else if (seqform->seqtypid == INT4OID)
1447  seqform->seqmax = PG_INT32_MAX;
1448  else
1449  seqform->seqmax = PG_INT64_MAX;
1450  }
1451  else
1452  seqform->seqmax = -1; /* descending seq */
1453  seqdataform->log_cnt = 0;
1454  }
1455 
1456  /* Validate maximum value. No need to check INT8 as seqmax is an int64 */
1457  if ((seqform->seqtypid == INT2OID && (seqform->seqmax < PG_INT16_MIN || seqform->seqmax > PG_INT16_MAX))
1458  || (seqform->seqtypid == INT4OID && (seqform->seqmax < PG_INT32_MIN || seqform->seqmax > PG_INT32_MAX)))
1459  ereport(ERROR,
1460  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1461  errmsg("MAXVALUE (%lld) is out of range for sequence data type %s",
1462  (long long) seqform->seqmax,
1463  format_type_be(seqform->seqtypid))));
1464 
1465  /* MINVALUE (null arg means NO MINVALUE) */
1466  if (min_value != NULL && min_value->arg)
1467  {
1468  seqform->seqmin = defGetInt64(min_value);
1469  seqdataform->log_cnt = 0;
1470  }
1471  else if (isInit || min_value != NULL || reset_min_value)
1472  {
1473  if (seqform->seqincrement < 0 || reset_min_value)
1474  {
1475  /* descending seq */
1476  if (seqform->seqtypid == INT2OID)
1477  seqform->seqmin = PG_INT16_MIN;
1478  else if (seqform->seqtypid == INT4OID)
1479  seqform->seqmin = PG_INT32_MIN;
1480  else
1481  seqform->seqmin = PG_INT64_MIN;
1482  }
1483  else
1484  seqform->seqmin = 1; /* ascending seq */
1485  seqdataform->log_cnt = 0;
1486  }
1487 
1488  /* Validate minimum value. No need to check INT8 as seqmin is an int64 */
1489  if ((seqform->seqtypid == INT2OID && (seqform->seqmin < PG_INT16_MIN || seqform->seqmin > PG_INT16_MAX))
1490  || (seqform->seqtypid == INT4OID && (seqform->seqmin < PG_INT32_MIN || seqform->seqmin > PG_INT32_MAX)))
1491  ereport(ERROR,
1492  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1493  errmsg("MINVALUE (%lld) is out of range for sequence data type %s",
1494  (long long) seqform->seqmin,
1495  format_type_be(seqform->seqtypid))));
1496 
1497  /* crosscheck min/max */
1498  if (seqform->seqmin >= seqform->seqmax)
1499  ereport(ERROR,
1500  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1501  errmsg("MINVALUE (%lld) must be less than MAXVALUE (%lld)",
1502  (long long) seqform->seqmin,
1503  (long long) seqform->seqmax)));
1504 
1505  /* START WITH */
1506  if (start_value != NULL)
1507  {
1508  seqform->seqstart = defGetInt64(start_value);
1509  }
1510  else if (isInit)
1511  {
1512  if (seqform->seqincrement > 0)
1513  seqform->seqstart = seqform->seqmin; /* ascending seq */
1514  else
1515  seqform->seqstart = seqform->seqmax; /* descending seq */
1516  }
1517 
1518  /* crosscheck START */
1519  if (seqform->seqstart < seqform->seqmin)
1520  ereport(ERROR,
1521  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1522  errmsg("START value (%lld) cannot be less than MINVALUE (%lld)",
1523  (long long) seqform->seqstart,
1524  (long long) seqform->seqmin)));
1525  if (seqform->seqstart > seqform->seqmax)
1526  ereport(ERROR,
1527  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1528  errmsg("START value (%lld) cannot be greater than MAXVALUE (%lld)",
1529  (long long) seqform->seqstart,
1530  (long long) seqform->seqmax)));
1531 
1532  /* RESTART [WITH] */
1533  if (restart_value != NULL)
1534  {
1535  if (restart_value->arg != NULL)
1536  seqdataform->last_value = defGetInt64(restart_value);
1537  else
1538  seqdataform->last_value = seqform->seqstart;
1539  seqdataform->is_called = false;
1540  seqdataform->log_cnt = 0;
1541  }
1542  else if (isInit)
1543  {
1544  seqdataform->last_value = seqform->seqstart;
1545  seqdataform->is_called = false;
1546  }
1547 
1548  /* crosscheck RESTART (or current value, if changing MIN/MAX) */
1549  if (seqdataform->last_value < seqform->seqmin)
1550  ereport(ERROR,
1551  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1552  errmsg("RESTART value (%lld) cannot be less than MINVALUE (%lld)",
1553  (long long) seqdataform->last_value,
1554  (long long) seqform->seqmin)));
1555  if (seqdataform->last_value > seqform->seqmax)
1556  ereport(ERROR,
1557  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1558  errmsg("RESTART value (%lld) cannot be greater than MAXVALUE (%lld)",
1559  (long long) seqdataform->last_value,
1560  (long long) seqform->seqmax)));
1561 
1562  /* CACHE */
1563  if (cache_value != NULL)
1564  {
1565  seqform->seqcache = defGetInt64(cache_value);
1566  if (seqform->seqcache <= 0)
1567  ereport(ERROR,
1568  (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
1569  errmsg("CACHE (%lld) must be greater than zero",
1570  (long long) seqform->seqcache)));
1571  seqdataform->log_cnt = 0;
1572  }
1573  else if (isInit)
1574  {
1575  seqform->seqcache = 1;
1576  }
1577 }
#define PG_INT32_MAX
Definition: c.h:578
#define BoolIsValid(boolean)
Definition: c.h:746
#define PG_INT16_MIN
Definition: c.h:574
#define PG_INT64_MAX
Definition: c.h:581
#define PG_INT64_MIN
Definition: c.h:580
#define PG_INT32_MIN
Definition: c.h:577
#define PG_INT16_MAX
Definition: c.h:575
List * defGetQualifiedName(DefElem *def)
Definition: define.c:253
int64 defGetInt64(DefElem *def)
Definition: define.c:187
void errorConflictingDefElem(DefElem *defel, ParseState *pstate)
Definition: define.c:385
TypeName * defGetTypeName(DefElem *def)
Definition: define.c:285
char * format_type_be(Oid type_oid)
Definition: format_type.c:343
int parser_errposition(ParseState *pstate, int location)
Definition: parse_node.c:111
Oid typenameTypeId(ParseState *pstate, const TypeName *typeName)
Definition: parse_type.c:291
#define lfirst(lc)
Definition: pg_list.h:172
char * defname
Definition: parsenodes.h:809
int location
Definition: parsenodes.h:813
Node * arg
Definition: parsenodes.h:810
#define boolVal(v)
Definition: value.h:81

References DefElem::arg, Assert(), BoolIsValid, boolVal, defGetInt64(), defGetQualifiedName(), defGetTypeName(), DefElem::defname, elog(), ereport, errcode(), errmsg(), ERROR, errorConflictingDefElem(), format_type_be(), FormData_pg_sequence_data::is_called, FormData_pg_sequence_data::last_value, lfirst, DefElem::location, FormData_pg_sequence_data::log_cnt, NIL, parser_errposition(), PG_INT16_MAX, PG_INT16_MIN, PG_INT32_MAX, PG_INT32_MIN, PG_INT64_MAX, PG_INT64_MIN, and typenameTypeId().

Referenced by AlterSequence(), and DefineSequence().

◆ init_sequence()

static void init_sequence ( Oid  relid,
SeqTable p_elm,
Relation p_rel 
)
static

Definition at line 1121 of file sequence.c.

1122 {
1123  SeqTable elm;
1124  Relation seqrel;
1125  bool found;
1126 
1127  /* Find or create a hash table entry for this sequence */
1128  if (seqhashtab == NULL)
1130 
1131  elm = (SeqTable) hash_search(seqhashtab, &relid, HASH_ENTER, &found);
1132 
1133  /*
1134  * Initialize the new hash table entry if it did not exist already.
1135  *
1136  * NOTE: seqhashtab entries are stored for the life of a backend (unless
1137  * explicitly discarded with DISCARD). If the sequence itself is deleted
1138  * then the entry becomes wasted memory, but it's small enough that this
1139  * should not matter.
1140  */
1141  if (!found)
1142  {
1143  /* relid already filled in */
1146  elm->last_valid = false;
1147  elm->last = elm->cached = 0;
1148  }
1149 
1150  /*
1151  * Open the sequence relation.
1152  */
1153  seqrel = lock_and_open_sequence(elm);
1154 
1155  if (seqrel->rd_rel->relkind != RELKIND_SEQUENCE)
1156  ereport(ERROR,
1157  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1158  errmsg("\"%s\" is not a sequence",
1159  RelationGetRelationName(seqrel))));
1160 
1161  /*
1162  * If the sequence has been transactionally replaced since we last saw it,
1163  * discard any cached-but-unissued values. We do not touch the currval()
1164  * state, however.
1165  */
1166  if (seqrel->rd_rel->relfilenode != elm->filenumber)
1167  {
1168  elm->filenumber = seqrel->rd_rel->relfilenode;
1169  elm->cached = elm->last;
1170  }
1171 
1172  /* Return results */
1173  *p_elm = elm;
1174  *p_rel = seqrel;
1175 }
void * hash_search(HTAB *hashp, const void *keyPtr, HASHACTION action, bool *foundPtr)
Definition: dynahash.c:953
@ HASH_ENTER
Definition: hsearch.h:114
#define InvalidLocalTransactionId
Definition: lock.h:65
#define InvalidRelFileNumber
Definition: relpath.h:26
SeqTableData * SeqTable
Definition: sequence.c:88
static void create_seq_hashtable(void)
Definition: sequence.c:1105
static Relation lock_and_open_sequence(SeqTable seq)
Definition: sequence.c:1077
RelFileNumber filenumber
Definition: sequence.c:78
LocalTransactionId lxid
Definition: sequence.c:79

References SeqTableData::cached, create_seq_hashtable(), ereport, errcode(), errmsg(), ERROR, SeqTableData::filenumber, HASH_ENTER, hash_search(), InvalidLocalTransactionId, InvalidRelFileNumber, SeqTableData::last, SeqTableData::last_valid, lock_and_open_sequence(), SeqTableData::lxid, RelationData::rd_rel, RelationGetRelationName, and seqhashtab.

Referenced by AlterSequence(), currval_oid(), do_setval(), nextval_internal(), pg_sequence_last_value(), ResetSequence(), and SequenceChangePersistence().

◆ lastval()

Datum lastval ( PG_FUNCTION_ARGS  )

Definition at line 889 of file sequence.c.

890 {
891  Relation seqrel;
892  int64 result;
893 
894  if (last_used_seq == NULL)
895  ereport(ERROR,
896  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
897  errmsg("lastval is not yet defined in this session")));
898 
899  /* Someone may have dropped the sequence since the last nextval() */
901  ereport(ERROR,
902  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
903  errmsg("lastval is not yet defined in this session")));
904 
906 
907  /* nextval() must have already been called for this sequence */
909 
912  ereport(ERROR,
913  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
914  errmsg("permission denied for sequence %s",
915  RelationGetRelationName(seqrel))));
916 
917  result = last_used_seq->last;
918  relation_close(seqrel, NoLock);
919 
920  PG_RETURN_INT64(result);
921 }
static SeqTableData * last_used_seq
Definition: sequence.c:96
@ RELOID
Definition: syscache.h:89
#define SearchSysCacheExists1(cacheId, key1)
Definition: syscache.h:191

References ACL_SELECT, ACL_USAGE, ACLCHECK_OK, Assert(), ereport, errcode(), errmsg(), ERROR, GetUserId(), SeqTableData::last, last_used_seq, SeqTableData::last_valid, lock_and_open_sequence(), NoLock, ObjectIdGetDatum(), pg_class_aclcheck(), PG_RETURN_INT64, relation_close(), RelationGetRelationName, SeqTableData::relid, RELOID, and SearchSysCacheExists1.

◆ lock_and_open_sequence()

static Relation lock_and_open_sequence ( SeqTable  seq)
static

Definition at line 1077 of file sequence.c.

1078 {
1079  LocalTransactionId thislxid = MyProc->lxid;
1080 
1081  /* Get the lock if not already held in this xact */
1082  if (seq->lxid != thislxid)
1083  {
1084  ResourceOwner currentOwner;
1085 
1086  currentOwner = CurrentResourceOwner;
1088 
1090 
1091  CurrentResourceOwner = currentOwner;
1092 
1093  /* Flag that we have a lock in the current xact */
1094  seq->lxid = thislxid;
1095  }
1096 
1097  /* We now know we have the lock, and can safely open the rel */
1098  return relation_open(seq->relid, NoLock);
1099 }
uint32 LocalTransactionId
Definition: c.h:643
void LockRelationOid(Oid relid, LOCKMODE lockmode)
Definition: lmgr.c:109
ResourceOwner TopTransactionResourceOwner
Definition: resowner.c:149
ResourceOwner CurrentResourceOwner
Definition: resowner.c:147
Relation relation_open(Oid relationId, LOCKMODE lockmode)
Definition: relation.c:48
PGPROC * MyProc
Definition: proc.c:66
LocalTransactionId lxid
Definition: proc.h:183

References CurrentResourceOwner, LockRelationOid(), SeqTableData::lxid, PGPROC::lxid, MyProc, NoLock, relation_open(), SeqTableData::relid, RowExclusiveLock, and TopTransactionResourceOwner.

Referenced by init_sequence(), and lastval().

◆ nextval()

Datum nextval ( PG_FUNCTION_ARGS  )

Definition at line 585 of file sequence.c.

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

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 615 of file sequence.c.

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

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, 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().

◆ nextval_oid()

Datum nextval_oid ( PG_FUNCTION_ARGS  )

Definition at line 607 of file sequence.c.

608 {
609  Oid relid = PG_GETARG_OID(0);
610 
611  PG_RETURN_INT64(nextval_internal(relid, true));
612 }

References nextval_internal(), PG_GETARG_OID, and PG_RETURN_INT64.

◆ pg_sequence_last_value()

Datum pg_sequence_last_value ( PG_FUNCTION_ARGS  )

Definition at line 1780 of file sequence.c.

1781 {
1782  Oid relid = PG_GETARG_OID(0);
1783  SeqTable elm;
1784  Relation seqrel;
1785  Buffer buf;
1786  HeapTupleData seqtuple;
1788  bool is_called;
1789  int64 result;
1790 
1791  /* open and lock sequence */
1792  init_sequence(relid, &elm, &seqrel);
1793 
1795  ereport(ERROR,
1796  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1797  errmsg("permission denied for sequence %s",
1798  RelationGetRelationName(seqrel))));
1799 
1800  seq = read_seq_tuple(seqrel, &buf, &seqtuple);
1801 
1802  is_called = seq->is_called;
1803  result = seq->last_value;
1804 
1806  relation_close(seqrel, NoLock);
1807 
1808  if (is_called)
1809  PG_RETURN_INT64(result);
1810  else
1811  PG_RETURN_NULL();
1812 }
#define PG_RETURN_NULL()
Definition: fmgr.h:345

References ACL_SELECT, ACL_USAGE, ACLCHECK_OK, buf, ereport, errcode(), errmsg(), ERROR, GetUserId(), init_sequence(), FormData_pg_sequence_data::is_called, FormData_pg_sequence_data::last_value, NoLock, pg_class_aclcheck(), PG_GETARG_OID, PG_RETURN_INT64, PG_RETURN_NULL, read_seq_tuple(), relation_close(), RelationGetRelationName, and UnlockReleaseBuffer().

◆ pg_sequence_parameters()

Datum pg_sequence_parameters ( PG_FUNCTION_ARGS  )

Definition at line 1736 of file sequence.c.

1737 {
1738  Oid relid = PG_GETARG_OID(0);
1739  TupleDesc tupdesc;
1740  Datum values[7];
1741  bool isnull[7];
1742  HeapTuple pgstuple;
1743  Form_pg_sequence pgsform;
1744 
1746  ereport(ERROR,
1747  (errcode(ERRCODE_INSUFFICIENT_PRIVILEGE),
1748  errmsg("permission denied for sequence %s",
1749  get_rel_name(relid))));
1750 
1751  if (get_call_result_type(fcinfo, NULL, &tupdesc) != TYPEFUNC_COMPOSITE)
1752  elog(ERROR, "return type must be a row type");
1753 
1754  memset(isnull, 0, sizeof(isnull));
1755 
1756  pgstuple = SearchSysCache1(SEQRELID, ObjectIdGetDatum(relid));
1757  if (!HeapTupleIsValid(pgstuple))
1758  elog(ERROR, "cache lookup failed for sequence %u", relid);
1759  pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
1760 
1761  values[0] = Int64GetDatum(pgsform->seqstart);
1762  values[1] = Int64GetDatum(pgsform->seqmin);
1763  values[2] = Int64GetDatum(pgsform->seqmax);
1764  values[3] = Int64GetDatum(pgsform->seqincrement);
1765  values[4] = BoolGetDatum(pgsform->seqcycle);
1766  values[5] = Int64GetDatum(pgsform->seqcache);
1767  values[6] = ObjectIdGetDatum(pgsform->seqtypid);
1768 
1769  ReleaseSysCache(pgstuple);
1770 
1771  return HeapTupleGetDatum(heap_form_tuple(tupdesc, values, isnull));
1772 }
static Datum values[MAXATTR]
Definition: bootstrap.c:156
TypeFuncClass get_call_result_type(FunctionCallInfo fcinfo, Oid *resultTypeId, TupleDesc *resultTupleDesc)
Definition: funcapi.c:276
@ TYPEFUNC_COMPOSITE
Definition: funcapi.h:149
static Datum HeapTupleGetDatum(const HeapTupleData *tuple)
Definition: funcapi.h:230
char * get_rel_name(Oid relid)
Definition: lsyscache.c:1932

References ACL_SELECT, ACL_UPDATE, ACL_USAGE, ACLCHECK_OK, BoolGetDatum(), elog(), ereport, errcode(), errmsg(), ERROR, get_call_result_type(), get_rel_name(), GETSTRUCT, GetUserId(), heap_form_tuple(), HeapTupleGetDatum(), HeapTupleIsValid, Int64GetDatum(), ObjectIdGetDatum(), pg_class_aclcheck(), PG_GETARG_OID, ReleaseSysCache(), SearchSysCache1(), SEQRELID, TYPEFUNC_COMPOSITE, and values.

◆ process_owned_by()

static void process_owned_by ( Relation  seqrel,
List owned_by,
bool  for_identity 
)
static

Definition at line 1588 of file sequence.c.

1589 {
1590  DependencyType deptype;
1591  int nnames;
1592  Relation tablerel;
1594 
1595  deptype = for_identity ? DEPENDENCY_INTERNAL : DEPENDENCY_AUTO;
1596 
1597  nnames = list_length(owned_by);
1598  Assert(nnames > 0);
1599  if (nnames == 1)
1600  {
1601  /* Must be OWNED BY NONE */
1602  if (strcmp(strVal(linitial(owned_by)), "none") != 0)
1603  ereport(ERROR,
1604  (errcode(ERRCODE_SYNTAX_ERROR),
1605  errmsg("invalid OWNED BY option"),
1606  errhint("Specify OWNED BY table.column or OWNED BY NONE.")));
1607  tablerel = NULL;
1608  attnum = 0;
1609  }
1610  else
1611  {
1612  List *relname;
1613  char *attrname;
1614  RangeVar *rel;
1615 
1616  /* Separate relname and attr name */
1617  relname = list_copy_head(owned_by, nnames - 1);
1618  attrname = strVal(llast(owned_by));
1619 
1620  /* Open and lock rel to ensure it won't go away meanwhile */
1622  tablerel = relation_openrv(rel, AccessShareLock);
1623 
1624  /* Must be a regular or foreign table */
1625  if (!(tablerel->rd_rel->relkind == RELKIND_RELATION ||
1626  tablerel->rd_rel->relkind == RELKIND_FOREIGN_TABLE ||
1627  tablerel->rd_rel->relkind == RELKIND_VIEW ||
1628  tablerel->rd_rel->relkind == RELKIND_PARTITIONED_TABLE))
1629  ereport(ERROR,
1630  (errcode(ERRCODE_WRONG_OBJECT_TYPE),
1631  errmsg("sequence cannot be owned by relation \"%s\"",
1632  RelationGetRelationName(tablerel)),
1633  errdetail_relkind_not_supported(tablerel->rd_rel->relkind)));
1634 
1635  /* We insist on same owner and schema */
1636  if (seqrel->rd_rel->relowner != tablerel->rd_rel->relowner)
1637  ereport(ERROR,
1638  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1639  errmsg("sequence must have same owner as table it is linked to")));
1640  if (RelationGetNamespace(seqrel) != RelationGetNamespace(tablerel))
1641  ereport(ERROR,
1642  (errcode(ERRCODE_OBJECT_NOT_IN_PREREQUISITE_STATE),
1643  errmsg("sequence must be in same schema as table it is linked to")));
1644 
1645  /* Now, fetch the attribute number from the system cache */
1646  attnum = get_attnum(RelationGetRelid(tablerel), attrname);
1647  if (attnum == InvalidAttrNumber)
1648  ereport(ERROR,
1649  (errcode(ERRCODE_UNDEFINED_COLUMN),
1650  errmsg("column \"%s\" of relation \"%s\" does not exist",
1651  attrname, RelationGetRelationName(tablerel))));
1652  }
1653 
1654  /*
1655  * Catch user explicitly running OWNED BY on identity sequence.
1656  */
1657  if (deptype == DEPENDENCY_AUTO)
1658  {
1659  Oid tableId;
1660  int32 colId;
1661 
1662  if (sequenceIsOwned(RelationGetRelid(seqrel), DEPENDENCY_INTERNAL, &tableId, &colId))
1663  ereport(ERROR,
1664  (errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
1665  errmsg("cannot change ownership of identity sequence"),
1666  errdetail("Sequence \"%s\" is linked to table \"%s\".",
1667  RelationGetRelationName(seqrel),
1668  get_rel_name(tableId))));
1669  }
1670 
1671  /*
1672  * OK, we are ready to update pg_depend. First remove any existing
1673  * dependencies for the sequence, then optionally add a new one.
1674  */
1675  deleteDependencyRecordsForClass(RelationRelationId, RelationGetRelid(seqrel),
1676  RelationRelationId, deptype);
1677 
1678  if (tablerel)
1679  {
1680  ObjectAddress refobject,
1681  depobject;
1682 
1683  refobject.classId = RelationRelationId;
1684  refobject.objectId = RelationGetRelid(tablerel);
1685  refobject.objectSubId = attnum;
1686  depobject.classId = RelationRelationId;
1687  depobject.objectId = RelationGetRelid(seqrel);
1688  depobject.objectSubId = 0;
1689  recordDependencyOn(&depobject, &refobject, deptype);
1690  }
1691 
1692  /* Done, but hold lock until commit */
1693  if (tablerel)
1694  relation_close(tablerel, NoLock);
1695 }
int16 AttrNumber
Definition: attnum.h:21
#define InvalidAttrNumber
Definition: attnum.h:23
signed int int32
Definition: c.h:483
DependencyType
Definition: dependency.h:32
@ DEPENDENCY_AUTO
Definition: dependency.h:34
@ DEPENDENCY_INTERNAL
Definition: dependency.h:35
int errdetail(const char *fmt,...)
Definition: elog.c:1202
int errhint(const char *fmt,...)
Definition: elog.c:1316
List * list_copy_head(const List *oldlist, int len)
Definition: list.c:1592
#define AccessShareLock
Definition: lockdefs.h:36
AttrNumber get_attnum(Oid relid, const char *attname)
Definition: lsyscache.c:857
int16 attnum
Definition: pg_attribute.h:74
int errdetail_relkind_not_supported(char relkind)
Definition: pg_class.c:24
NameData relname
Definition: pg_class.h:38
void recordDependencyOn(const ObjectAddress *depender, const ObjectAddress *referenced, DependencyType behavior)
Definition: pg_depend.c:44
long deleteDependencyRecordsForClass(Oid classId, Oid objectId, Oid refclassId, char deptype)
Definition: pg_depend.c:350
bool sequenceIsOwned(Oid seqId, char deptype, Oid *tableId, int32 *colId)
Definition: pg_depend.c:827
#define llast(l)
Definition: pg_list.h:198
static int list_length(const List *l)
Definition: pg_list.h:152
#define linitial(l)
Definition: pg_list.h:178
#define RelationGetRelid(relation)
Definition: rel.h:504
#define RelationGetNamespace(relation)
Definition: rel.h:545
Relation relation_openrv(const RangeVar *relation, LOCKMODE lockmode)
Definition: relation.c:138
#define strVal(v)
Definition: value.h:82

References AccessShareLock, Assert(), attnum, ObjectAddress::classId, deleteDependencyRecordsForClass(), DEPENDENCY_AUTO, DEPENDENCY_INTERNAL, ereport, errcode(), errdetail(), errdetail_relkind_not_supported(), errhint(), errmsg(), ERROR, get_attnum(), get_rel_name(), InvalidAttrNumber, linitial, list_copy_head(), list_length(), llast, makeRangeVarFromNameList(), NoLock, ObjectAddress::objectId, ObjectAddress::objectSubId, RelationData::rd_rel, recordDependencyOn(), relation_close(), relation_openrv(), RelationGetNamespace, RelationGetRelationName, RelationGetRelid, relname, sequenceIsOwned(), and strVal.

Referenced by AlterSequence(), and DefineSequence().

◆ read_seq_tuple()

static Form_pg_sequence_data read_seq_tuple ( Relation  rel,
Buffer buf,
HeapTuple  seqdatatuple 
)
static

Definition at line 1188 of file sequence.c.

1189 {
1190  Page page;
1191  ItemId lp;
1192  sequence_magic *sm;
1194 
1195  *buf = ReadBuffer(rel, 0);
1197 
1198  page = BufferGetPage(*buf);
1199  sm = (sequence_magic *) PageGetSpecialPointer(page);
1200 
1201  if (sm->magic != SEQ_MAGIC)
1202  elog(ERROR, "bad magic number in sequence \"%s\": %08X",
1203  RelationGetRelationName(rel), sm->magic);
1204 
1205  lp = PageGetItemId(page, FirstOffsetNumber);
1206  Assert(ItemIdIsNormal(lp));
1207 
1208  /* Note we currently only bother to set these two fields of *seqdatatuple */
1209  seqdatatuple->t_data = (HeapTupleHeader) PageGetItem(page, lp);
1210  seqdatatuple->t_len = ItemIdGetLength(lp);
1211 
1212  /*
1213  * Previous releases of Postgres neglected to prevent SELECT FOR UPDATE on
1214  * a sequence, which would leave a non-frozen XID in the sequence tuple's
1215  * xmax, which eventually leads to clog access failures or worse. If we
1216  * see this has happened, clean up after it. We treat this like a hint
1217  * bit update, ie, don't bother to WAL-log it, since we can certainly do
1218  * this again if the update gets lost.
1219  */
1220  Assert(!(seqdatatuple->t_data->t_infomask & HEAP_XMAX_IS_MULTI));
1222  {
1224  seqdatatuple->t_data->t_infomask &= ~HEAP_XMAX_COMMITTED;
1225  seqdatatuple->t_data->t_infomask |= HEAP_XMAX_INVALID;
1226  MarkBufferDirtyHint(*buf, true);
1227  }
1228 
1229  seq = (Form_pg_sequence_data) GETSTRUCT(seqdatatuple);
1230 
1231  return seq;
1232 }
void LockBuffer(Buffer buffer, int mode)
Definition: bufmgr.c:4715
void MarkBufferDirtyHint(Buffer buffer, bool buffer_std)
Definition: bufmgr.c:4544
Buffer ReadBuffer(Relation reln, BlockNumber blockNum)
Definition: bufmgr.c:708
#define BUFFER_LOCK_EXCLUSIVE
Definition: bufmgr.h:159
static Item PageGetItem(Page page, ItemId itemId)
Definition: bufpage.h:351
static ItemId PageGetItemId(Page page, OffsetNumber offsetNumber)
Definition: bufpage.h:240
HeapTupleHeaderData * HeapTupleHeader
Definition: htup.h:23
#define HEAP_XMAX_IS_MULTI
Definition: htup_details.h:209
#define HEAP_XMAX_COMMITTED
Definition: htup_details.h:207
#define HeapTupleHeaderGetRawXmax(tup)
Definition: htup_details.h:371
#define ItemIdGetLength(itemId)
Definition: itemid.h:59
#define ItemIdIsNormal(itemId)
Definition: itemid.h:99

References Assert(), buf, BUFFER_LOCK_EXCLUSIVE, BufferGetPage(), elog(), ERROR, FirstOffsetNumber, GETSTRUCT, HEAP_XMAX_COMMITTED, HEAP_XMAX_INVALID, HEAP_XMAX_IS_MULTI, HeapTupleHeaderGetRawXmax, HeapTupleHeaderSetXmax, InvalidTransactionId, ItemIdGetLength, ItemIdIsNormal, LockBuffer(), sequence_magic::magic, MarkBufferDirtyHint(), PageGetItem(), PageGetItemId(), PageGetSpecialPointer(), ReadBuffer(), RelationGetRelationName, SEQ_MAGIC, HeapTupleData::t_data, HeapTupleHeaderData::t_infomask, and HeapTupleData::t_len.

Referenced by AlterSequence(), do_setval(), nextval_internal(), pg_sequence_last_value(), ResetSequence(), and SequenceChangePersistence().

◆ ResetSequence()

void ResetSequence ( Oid  seq_relid)

Definition at line 261 of file sequence.c.

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

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(), RelationSetNewRelfilenumber(), ReleaseSysCache(), SearchSysCache1(), SEQRELID, and UnlockReleaseBuffer().

Referenced by ExecuteTruncateGuts().

◆ ResetSequenceCaches()

void ResetSequenceCaches ( void  )

Definition at line 1869 of file sequence.c.

1870 {
1871  if (seqhashtab)
1872  {
1874  seqhashtab = NULL;
1875  }
1876 
1877  last_used_seq = NULL;
1878 }
void hash_destroy(HTAB *hashp)
Definition: dynahash.c:863

References hash_destroy(), last_used_seq, and seqhashtab.

Referenced by DiscardAll(), and DiscardCommand().

◆ seq_mask()

void seq_mask ( char *  page,
BlockNumber  blkno 
)

Definition at line 1884 of file sequence.c.

1885 {
1887 
1888  mask_unused_space(page);
1889 }
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 1816 of file sequence.c.

1817 {
1818  XLogRecPtr lsn = record->EndRecPtr;
1819  uint8 info = XLogRecGetInfo(record) & ~XLR_INFO_MASK;
1820  Buffer buffer;
1821  Page page;
1822  Page localpage;
1823  char *item;
1824  Size itemsz;
1825  xl_seq_rec *xlrec = (xl_seq_rec *) XLogRecGetData(record);
1826  sequence_magic *sm;
1827 
1828  if (info != XLOG_SEQ_LOG)
1829  elog(PANIC, "seq_redo: unknown op code %u", info);
1830 
1831  buffer = XLogInitBufferForRedo(record, 0);
1832  page = (Page) BufferGetPage(buffer);
1833 
1834  /*
1835  * We always reinit the page. However, since this WAL record type is also
1836  * used for updating sequences, it's possible that a hot-standby backend
1837  * is examining the page concurrently; so we mustn't transiently trash the
1838  * buffer. The solution is to build the correct new page contents in
1839  * local workspace and then memcpy into the buffer. Then only bytes that
1840  * are supposed to change will change, even transiently. We must palloc
1841  * the local page for alignment reasons.
1842  */
1843  localpage = (Page) palloc(BufferGetPageSize(buffer));
1844 
1845  PageInit(localpage, BufferGetPageSize(buffer), sizeof(sequence_magic));
1846  sm = (sequence_magic *) PageGetSpecialPointer(localpage);
1847  sm->magic = SEQ_MAGIC;
1848 
1849  item = (char *) xlrec + sizeof(xl_seq_rec);
1850  itemsz = XLogRecGetDataLen(record) - sizeof(xl_seq_rec);
1851 
1852  if (PageAddItem(localpage, (Item) item, itemsz,
1853  FirstOffsetNumber, false, false) == InvalidOffsetNumber)
1854  elog(PANIC, "seq_redo: failed to add item to page");
1855 
1856  PageSetLSN(localpage, lsn);
1857 
1858  memcpy(page, localpage, BufferGetPageSize(buffer));
1859  MarkBufferDirty(buffer);
1860  UnlockReleaseBuffer(buffer);
1861 
1862  pfree(localpage);
1863 }
unsigned char uint8
Definition: c.h:493
size_t Size
Definition: c.h:594
#define PANIC
Definition: elog.h:42
void pfree(void *pointer)
Definition: mcxt.c:1456
void * palloc(Size size)
Definition: mcxt.c:1226
struct xl_seq_rec xl_seq_rec
XLogRecPtr EndRecPtr
Definition: xlogreader.h:207
#define XLogRecGetDataLen(decoder)
Definition: xlogreader.h:416
#define XLogRecGetInfo(decoder)
Definition: xlogreader.h:410
#define XLogRecGetData(decoder)
Definition: xlogreader.h:415
#define XLR_INFO_MASK
Definition: xlogrecord.h:62
Buffer XLogInitBufferForRedo(XLogReaderState *record, uint8 block_id)
Definition: xlogutils.c:329

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 1702 of file sequence.c.

1703 {
1704  HeapTuple pgstuple;
1705  Form_pg_sequence pgsform;
1706  List *options = NIL;
1707 
1708  pgstuple = SearchSysCache1(SEQRELID, ObjectIdGetDatum(relid));
1709  if (!HeapTupleIsValid(pgstuple))
1710  elog(ERROR, "cache lookup failed for sequence %u", relid);
1711  pgsform = (Form_pg_sequence) GETSTRUCT(pgstuple);
1712 
1713  /* Use makeFloat() for 64-bit integers, like gram.y does. */
1715  makeDefElem("cache", (Node *) makeFloat(psprintf(INT64_FORMAT, pgsform->seqcache)), -1));
1717  makeDefElem("cycle", (Node *) makeBoolean(pgsform->seqcycle), -1));
1719  makeDefElem("increment", (Node *) makeFloat(psprintf(INT64_FORMAT, pgsform->seqincrement)), -1));
1721  makeDefElem("maxvalue", (Node *) makeFloat(psprintf(INT64_FORMAT, pgsform->seqmax)), -1));
1723  makeDefElem("minvalue", (Node *) makeFloat(psprintf(INT64_FORMAT, pgsform->seqmin)), -1));
1725  makeDefElem("start", (Node *) makeFloat(psprintf(INT64_FORMAT, pgsform->seqstart)), -1));
1726 
1727  ReleaseSysCache(pgstuple);
1728 
1729  return options;
1730 }
#define INT64_FORMAT
Definition: c.h:537
DefElem * makeDefElem(char *name, Node *arg, int location)
Definition: makefuncs.c:549
static char ** options
char * psprintf(const char *fmt,...)
Definition: psprintf.c:46
Definition: nodes.h:129
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, ObjectIdGetDatum(), options, psprintf(), ReleaseSysCache(), SearchSysCache1(), and SEQRELID.

Referenced by transformTableLikeClause().

◆ SequenceChangePersistence()

void SequenceChangePersistence ( Oid  relid,
char  newrelpersistence 
)

Definition at line 540 of file sequence.c.

541 {
542  SeqTable elm;
543  Relation seqrel;
544  Buffer buf;
545  HeapTupleData seqdatatuple;
546 
547  init_sequence(relid, &elm, &seqrel);
548 
549  /* check the comment above nextval_internal()'s equivalent call. */
550  if (RelationNeedsWAL(seqrel))
552 
553  (void) read_seq_tuple(seqrel, &buf, &seqdatatuple);
554  RelationSetNewRelfilenumber(seqrel, newrelpersistence);
555  fill_seq_with_data(seqrel, &seqdatatuple);
557 
558  relation_close(seqrel, NoLock);
559 }

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

Referenced by ATRewriteTables().

◆ setval3_oid()

Datum setval3_oid ( PG_FUNCTION_ARGS  )

Definition at line 1056 of file sequence.c.

1057 {
1058  Oid relid = PG_GETARG_OID(0);
1059  int64 next = PG_GETARG_INT64(1);
1060  bool iscalled = PG_GETARG_BOOL(2);
1061 
1062  do_setval(relid, next, iscalled);
1063 
1065 }
#define PG_GETARG_INT64(n)
Definition: fmgr.h:283
#define PG_GETARG_BOOL(n)
Definition: fmgr.h:274
static void do_setval(Oid relid, int64 next, bool iscalled)
Definition: sequence.c:937

References do_setval(), next, PG_GETARG_BOOL, PG_GETARG_INT64, PG_GETARG_OID, and PG_RETURN_INT64.

◆ setval_oid()

Datum setval_oid ( PG_FUNCTION_ARGS  )

Definition at line 1041 of file sequence.c.

1042 {
1043  Oid relid = PG_GETARG_OID(0);
1044  int64 next = PG_GETARG_INT64(1);
1045 
1046  do_setval(relid, next, true);
1047 
1049 }

References do_setval(), next, PG_GETARG_INT64, PG_GETARG_OID, and PG_RETURN_INT64.

Variable Documentation

◆ last_used_seq

SeqTableData* last_used_seq = NULL
static

Definition at line 96 of file sequence.c.

Referenced by lastval(), nextval_internal(), and ResetSequenceCaches().

◆ seqhashtab

HTAB* seqhashtab = NULL
static

Definition at line 90 of file sequence.c.

Referenced by create_seq_hashtable(), init_sequence(), and ResetSequenceCaches().